Thursday, September 24, 2015

Custom HTML Helpers- Extend ActionLink

Requirement: Create custom container DIV control that takes in HTML markup as input.

Assuming you already have an MVC website created.

Step 1: Create a folder named "Helpers" in the root of your MVC website.

Step 2: Create a static class named "HtmlHelper" under the newly created folder.

Step 3: Use following Namespaces:

using System;
using System.Text;
using System.Web;
using System.Web.Mvc;

Step 4: Create a static function as follows:

public static IHtmlString CustomActionLink(this HtmlHelper helper, string Id, string caption, string action, string controller, string tooltip, Dictionary<string, object> htmlAttributes = null)
        {
            //If htmlAttributes is null, create an instance
            if (htmlAttributes == null)
            {
                htmlAttributes = new Dictionary<string, object>();
            }

            //Add properties
            htmlAttributes.Add("title", tooltip);
            htmlAttributes.Add("class", "InformActionLink");

            //Finally return the custom ActionLink
            return helper.ActionLink(caption, action, controller, null, htmlAttributes);
        }

Step 5: Compile the project.

Step 6: Open the view in which you want to render the above control.

Step 7: Add reference to the newly created control on top of your view:

@using <Your ProjectName>.<FolderName>
Example @using HtmlHelpers.Helpers

Step 8: Add following markup:

@Html.CustomActionLink("lnkAddNew", "Add New", "ClientActionName", "ClientControllerName", "Add New Client")
OR
@Html.CustomActionLink("lnkAddNew", "Add New", "ClientActionName", "ClientControllerName", "Add New Client", null)
OR
@Html.CustomActionLink("lnkAddNew", "Add New", "ClientActionName", "ClientControllerName", "Add New Client", new Dictionary<string, object>() {{ "onclick" , "alert('testing')"}})

Custom HTML Helpers- Link

Requirement: Create custom container DIV control that takes in HTML markup as input.

Assuming you already have an MVC website created.

Step 1: Create a folder named "Helpers" in the root of your MVC website.

Step 2: Create a static class named "HtmlHelper" under the newly created folder.

Step 3: Use following Namespaces:

using System;
using System.Text;
using System.Web;
using System.Web.Mvc;

Step 4: Create a static function as follows:

public static IHtmlString CustomLink(this HtmlHelper helper, string Id, string caption, string tooltip, Dictionary<string, object> htmlAttributes = null)
        {
            var attributes = new StringBuilder();

            //Read HTML Attributes and construct string out of it
            if (htmlAttributes != null)
            {
                foreach (var attr in htmlAttributes.ToArray())
                {
                    attributes.Append($"{attr.Key.ToString()}=\"{attr.Value.ToString()}\"");
                }

            }
            else
            {
                htmlAttributes = new Dictionary<string, object>();
            }

            var sb = new StringBuilder();

            //Construct final control with markup and htmlAttributes
            sb.Append($"<a id='{Id}' class='InformActionLink' {attributes} title='{tooltip}'>{caption}</a>");

            //Return as HTML String
            return new HtmlString(sb.ToString());

        }

Step 5: Compile the project.

Step 6: Open the view in which you want to render the above control.

Step 7: Add reference to the newly created control on top of your view:

@using <Your ProjectName>.<FolderName>
Example @using HtmlHelpers.Helpers

Step 8: Add following markup:

@Html.CustomLink ("lnkAddNew", "Add", "Add New Client", new Dictionary<string, object>() { { "onclick" , "alert('testing')"} })
OR
@Html.CustomLink ("lnkAddNew", "Add", "Add New Client", null)
OR
@Html.CustomLink ("lnkAddNew", "Add", "Add New Client")

Monday, September 21, 2015

Custom Authorize using AuthorizeAttribute

Requirement: Once authenticated, a user should be authorized using his/her role to access certain modules of my application.

Assuming you already have a login page and users are being validated against DB. Please read Custom Authentication using IAuthenticationFilter

Step 1: Create a folder named "CustomAttributes" in the root of your MVC website.

Step 2: Create a class named "CustomUserAuthorizationAttribute" under the newly created folder.

Step 3: Inherit and implement the class using AuthorizeAttribute

public class CustomUserAuthorizationAttribute : AuthorizeAttribute
{
 //Implemention goes here
}

Step 4: Use following Namespaces:

using System.Web.Mvc;
using System.Web.Mvc.Filters;

Step 5: Create members shown below:

     /// <summary>
        /// List of roles allowed. This will be passed in the attribute declarartion
        /// </summary>
        private readonly string[] RolesAllowed;


        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="roles">The roles.</param>
        public CustomUserAuthorizationAttribute(params string[] roles)
        {
            this.RolesAllowed = roles;
        }


        /// <summary>
        /// This is called when a controller/Action decorated with [CustomUserAuthorization] is executed
        /// </summary>
        /// <param name="httpContext">The HTTP context.</param>
        /// <returns></returns>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            //This holds the authorization token in form of a boolean
            bool authorize = false;

            //Get User info from Session
            var currentUserSessionInfo = Common.GetFromSession<UserSessionInfo>(Common.SessionKeys.UserSessionInfo);
            
            //Read all the roles passed in RolesAllowed from attribute declaration on a Controller/Action
            foreach (var role in RolesAllowed)
            {
                //If User is null OR User Role is NULL, set authorize token to false
                if (currentUserSessionInfo == null || currentUserSessionInfo.Role == null)
                {
                    authorize = false;
                }
                //match user's role, if match is found; set the authorize token to true 
                else if (currentUserSessionInfo.Role.Equals(role, StringComparison.OrdinalIgnoreCase))
                {
                    authorize = true;
                }
            }
            return authorize;
        }



        /// <summary>
        /// This is triggered after AuthorizeCore has returned autorize token. You may redirect to a specific page
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.Result = new HttpUnauthorizedResult();
            //Redirect to a specific page to let user know that he/she is not authorized to view the page or take action.
        }

Step 6: Now decorate an action with [CustomUserAuthorization].

I wanted to allow only authenticated users to access my home page, my controller looked like this:

[CustomUserAuthorization("Admin", "SuperAdmin")]
public ActionResult DeleteUser()
{
    //Implemention goes here
}

Every time DeleteUser action is called, user is authorized to see if he/she is belongs to Admin or SuperAdmin role. You may simply decorate new actions with specified roles.

Custom Authentication using IAuthenticationFilter


Requirement: Only validated users/Logged in users should be able to view application pages, others should be redirected to login screen.

Assuming you already have a login page and users are being validated against DB.

Step 1: Create a folder named "CustomAttributes" in the root of your MVC website.

Step 2: Create a class named "CustomUserAuthenticationAttribute" under the newly created folder.

Step 3: Inherit and implement the class using System.Web.Mvc.ActionFilterAttribute, IAuthenticationFilter

public class CustomUserAuthenticationAttribute : System.Web.Mvc.ActionFilterAttribute, IAuthenticationFilter
{
 //Implemention goes here
}

Step 4: Use following Namespaces:

using System.Web.Mvc;
using System.Web.Mvc.Filters;

Step 5: Create methods shown below:

     /// <summary>
        /// This is Called when a Controller/Action decorated with [CustomUserAuthentication] is executed.
        /// </summary>
        /// <param name="context">The context.</param>
        public void OnAuthentication(AuthenticationContext context)
        {
            //Get Logged in User info from Session
            var currentUserSessionInfo = Common.GetFromSession<UserSessionInfo>(Common.SessionKeys.UserSessionInfo);

            //Return unauthorized result if user info is null
            if (currentUserSessionInfo == null)
            {
                context.Result = new HttpUnauthorizedResult();
            }
            //If User is not logged in OR Branch Logged in is null, logout user and return unauthorized result 
            else if (!currentUserSessionInfo.IsUserLoggedIn || string.IsNullOrEmpty(currentUserSessionInfo.BranchLoggedIn))
            {
                var usr = currentUserSessionInfo.LoggedInUser;
                if (usr != null)
                {
                    usr.Logout();
                    usr.Dispose();
                }
                context.Result = new HttpUnauthorizedResult();
            }

        }


        /// <summary>
        /// This gets called after OnAuthentication has returned its result
        /// </summary>
        /// <param name="context">The context.</param>
        public void OnAuthenticationChallenge(AuthenticationChallengeContext context)
        {
            //If an unauthorizedResult is detected, redirect to login screen
            if (context.Result == null || context.Result is HttpUnauthorizedResult)
            {
                context.Result = new RedirectToRouteResult("Default",
                    new System.Web.Routing.RouteValueDictionary{
                        {"controller", "Account"},
                        {"action", "Login"},
                        {"returnUrl", context.HttpContext.Request.RawUrl}
                    });
            }
        }

Step 6: Now decorate a controller with [CustomUserAuthentication].

I wanted to allow only authenticated users to access my home page, my controller looked like this:

[CustomUserAuthentication]
    public class HomeController : BaseController
    {

        public ActionResult Index()
        {
            return View();
        }

    }

Every time home page is called, users are validated using IAuthenticationFilter. This prevents home page from any unauthenticated user's access. If I need more such pages, I just need to decorate the new page's controller/ action.