EPiServer login functionality using Web API 2

Introduction

Recently, I worked on EPiServer website that had quite complex UI with lots of ajax calls.

The idea was to use Web API 2 instead of creating controller actions in page / block controllers and registering custom routes.

In this blog post, we will see how to create a login functionality in EpiServer AlloyTech website using Web API 2.

Installing Web API

AlloyTech doesn't come with WebAPI, so we have to install Microsoft.AspNet.WebApi nuget package.

We need to make sure that our web application is using .NET framework 4.5 before we install the WebApi nuget package

Inside Business / Initialization folder, we will create a new class called WebApiConfig

using System.Web.Http;

namespace EPiServer.Templates.Alloy.Business.Initialization
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Attribute routing.
            config.MapHttpAttributeRoutes();
        }
    }
}

Open Global.asax.cs and add the following line inside Application_Start()

GlobalConfiguration.Configure(WebApiConfig.Register);

 

AccountController

Next, we will create a new folder called Api, and web api controller called AccountController

namespace EPiServer.Templates.Alloy.Api
{
    [RoutePrefix("api/account")]
    public class AccountController : ApiController
    {
        public class LoginInfo
        {
            [Required]
            public string Username { get; set; }

            [Required]
            public string Password { get; set; }
        }

        [Route("login")]
        [HttpPost]
        public IHttpActionResult AuthenticateUser(LoginInfo loginInfo)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (!Membership.ValidateUser(loginInfo.Username, loginInfo.Password))
            {
                ModelState.AddModelError("", "Incorrect username or password");
                return BadRequest(ModelState);
            }

            FormsAuthentication.SetAuthCookie(loginInfo.Username, true);

            return Ok();
        }
    }
}

Note: Web API 2 in combination with EPiServer 7 doesn't allow multiple action arguments (both username and password), and that's the reason why we had to create the LoginInfo class that contains all the properties we need.

Start page

On the start page, we want to display a currently logged in user. If the user is not logged in, we want to display the login form.

Here's the code:

@if (PrincipalInfo.CurrentPrincipal.Identity.IsAuthenticated)
{
    <p>Welcome, <strong>@PrincipalInfo.CurrentPrincipal.Identity.Name</strong></p>
}
else
{
    <form action="#" id="login-form">
        <label for="username">Username:</label>
        <input type="text" name="username" id="username"/>
        
        <label for="password">Password:</label>
        <input type="password" name="password" id="password"/>
        <div><input type="submit"/></div>
        
    </form>
    
   <script>
       $(document).ready(function () {
           $("#login-form").submit(function (e) {
               e.preventDefault();

               var username = $('#username').val();
               var password = $('#password').val();

               $.ajax({
                   type: 'POST',
                   url: '/api/account/Login/',
                   data: { Username: username, Password: password },
                   success: function () {
                       // refresh the page if username and password are correct
                       location.reload();
                   }
               });
           });
       });
</script>
}

Configuring Web API using InitializationModule

In order to work with Web API, we had to call GlobalConfiguration.Configure(WebApiConfig.Register) inside Global.asax.cs -> Application_Start(). Sometimes we don't have access to global.asax.cs because we're creating an addon or something... Routes can be easily configured using initialization module:

using System.Web.Http;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;

namespace EPiServer.Templates.Alloy.Business.Initialization
{
    [InitializableModule]
    public class WebApiConfig : IInitializableModule
    {
        public static void Register(HttpConfiguration config)
        {
            // Attribute routing.
            config.MapHttpAttributeRoutes();
        }

        public void Initialize(InitializationEngine context)
        {
            GlobalConfiguration.Configure(Register);
        }

        public void Uninitialize(InitializationEngine context)
        {
        }

        public void Preload(string[] parameters)
        {
        }
    }
}
comments powered by Disqus