Wednesday 30 January 2013

ASP.NET MVC Filters

Filters are .NET attributes that add extra steps to the request processing pipeline. MVC Filters supports to perform logic, either before an action method is called or after an action method runs. Attributes are special .NET classes derived from System.Attribute.

Types of Filters:

The MVC Framework supports four different types of filters.

Filter Type
Interface
Default Implementation
Description
Authorization IAuthorizationFilter AuthorizeAttribute Runs first, before any other filters or the action method
Action IActionFilter ActionFilterAttribute Runs before and after the action method
Result IResultFilter ActionFilterAttribute Runs before and after the action result is executed
Exception

IExceptionFilter

HandleErrorAttribute Runs only if another filter, the action method, or the action result throws an exception

The framework includes default attribute classes that implement the filter interfaces. The Controller class implements each of the filter interfaces. We can implement filters for a specific controller by overriding the controller's On<Filter> method. We can implement the following On<Filter> methods in a controller:
  • OnAuthorization
  • OnException
  • OnActionExecuting
  • OnActionExecuted
  • OnResultExecuting
  • OnResultExecuted 
Filters run in the following sequence:
  • Authorization filters
  • Action filters
  • Result filters
  • Exception filters
How To Create a Filter:
Filter can create in the following ways:
  • Override one or more of the controller's On<Filter> methods.
  • Create an attribute class that derives from FilterAttribute and apply the attribute to a controller or an action method.
  • Register a filter with the filter provider (the FilterProviders class).
  • Register a global filter using the GlobalFilterCollection class.
Applying Filters to Controllers and Action Methods: Filter can be applied to an entire controller or action methods. We can also apply multiple filters and can manage order of execution of those custom filters.

Example:
[Authorize] // controller level attribute/filter - applies to all actions
public partial class AccountController : Controller
{
      
       [OutputCache(Duration = 60)] // applies to this action
[HeaderType] // applies to this action
[HttpGet]
        public ActionResult GetAccountHeader()
        {
           
        }
}

Authorization Filters: Authorization filters run first before the other kinds of filters and action method is invoked. This filter use to authenticate user before executing action methods. Authorization filters implement the IAuthorizationFilter interface

public interface IAuthorizationFilter
{
    void OnAuthorization(AuthorizationContext filterContext);
}

A Custom Authentication Filter:
Example:
public class DemoAuthAttribute : AuthorizeAttribute
{
    private string[] _roles;
    public DemoAuthAttribute(params string[] roles)
    {
        _roles = roles;
    }
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        return httpContext.Request.IsAuthenticated && httpContext.User.IsRole(_roles);
    }
    public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            if (AuthorizeCore(filterContext.HttpContext))
            {
                // your custom logic here
               string text = string.Format("<u><h5>Auth successfull.....</h5></u></br>");
                filterContext.HttpContext.Response.Write(text);
            }
            else
            {
                // RedirectResult, etc.
                string text = string.Format("<u><h5>Auth unsuccessfull.....</h5></u></br>");
                filterContext.HttpContext.Response.Write(text);
            }
        }
}

The simplest way to create an authorization filter is to subclass the AuthorizeAttribute class and overrides the AuthorizeCore method. This ensures that we benefit from the features built in to AuthorizeAttribute.


By default AuthorizeCore gets called by both OnAuthorize and OnCacheAuthorization. This allows the authorization to be cached but still allow certain actions and to make the actual decisions about the authorization. If we need something from the AuthorizationContext then we can create a property to hold the information and then access that in the AuthorizeCore method.


 AuthorizationContext Properties

Name Type Description
ActionDescriptor ActionDescriptor Provides details of the action method
Result ActionResult The result for the action method; a filter can cancel the request by setting this property to a non-null value

Exception Filters: Exception filters are run only if an unhandled exception has been thrown when invoking an action method. The exception can come from another kind of, the action method itself and when the action result is executed.

public interface IExceptionFilter
{
    void OnException(ExceptionContext filterContext);
}

Name Type Description
ActionDescriptor ActionDescriptor Provides details of the action method
Result ActionResult The result for the action method; a filter can cancel the request by setting this property to a non-null value
Exception Exception The unhandled exception
ExceptionHandled bool Returns true if another filter has marked the exception as handled

Example:
public class MyExceptionAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        if (!filterContext.ExceptionHandled &&
        filterContext.Exception is NullReferenceException)
        {
            filterContext.Result = new RedirectResult("/ErrorPage.html");
            filterContext.ExceptionHandled = true;
        }
    }
}

[MyException]
public ActionResult Index() {
}

Action and Result FiltersAction and result filters follows similar pattern and runs before and after the action method/result. ActionFilterAttribute class implements both IActionFilter and IResultFilter.

public interface IActionFilter
{
    void OnActionExecuting(ActionExecutingContext filterContext);
    void OnActionExecuted(ActionExecutedContext filterContext);
}

   
public interface IResultFilter
{
       
    void OnResultExecuted(ResultExecutedContext filterContext);
    void OnResultExecuting(ResultExecutingContext filterContext);
}

OnActionExecuting: The OnActionExecuting method run before the action method is invoked. We can modify/cancel the request or do some activity.

OnActionExecutedThis filter use to perform some activity after execution of the action method.

ActionExecutingContext   is a Subclass of ControllerContext which is passing as parameter in the method.  ActionExecutingContext   defines following properties which are described below.

Name Type Description
ActionDescriptor ActionDescriptor Provides details of the action method
Result ActionResult The result for the action method; a filter can cancel the request by setting this property to a non-null value
Canceled Bool Returns true if the action has been canceled by another filter
Exception Exception The unhandled exception
ExceptionHandled bool Returns true if another filter has marked the exception as handled

Example: 
    public class ExecutionTimeAttribute : FilterAttribute, IActionFilter
    {
        private Stopwatch timer;

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            timer = Stopwatch.StartNew();
        }
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            timer.Stop();
            if (filterContext.Exception == null)
            {
                filterContext.HttpContext.Response.Write(
                string.Format("Action method execution time: {0}", timer.Elapsed.TotalSeconds));
            }
        }
    }

OnResultExecuting: The OnResultExecuting method is invoked once the action method has returned an action result, but before the action result is executed.

OnResultExecuted: The OnResultExecuted method is invoked after the action result is executed.

The parameters to these methods are ResultExecutingContext and ResultExecutedContext objects, respectively, and they are very similar to their action filter counterparts.

Example:
    public class ExecutionTimeResultAttribute : FilterAttribute, IResultFilter
    {
        private Stopwatch timer;
        public void OnResultExecuting(ResultExecutingContext filterContext)
        {
            timer = Stopwatch.StartNew();
        }
        public void OnResultExecuted(ResultExecutedContext filterContext)
        {
            timer.Stop();
            filterContext.HttpContext.Response.Write(
            string.Format("Result execution - elapsed time: {0}",
            timer.Elapsed.TotalSeconds));
        }
    }

[ExecutionTime]
[ExecutionTimeResult]
public ActionResult Index()
{
     return View();
}

Override Filters in a Controller: Create a controller class that implements filter interfaces and can use as base controller so that other controller can use functionality across application. Through this we can put code that is required across the application in one reusable location.

Example:
public class BaseController : Controller
{
   
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //write your logic here
    }
    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //write your logic here
    }
    protected override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        //write your logic here
    }
    protected override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        //write your logic here
    }
}

Global Filter: Global filters are a way of applying filters in all action methods in application. The advantage of this is we no longer need to apply attribute s on every controller or action methods.
We can make a regular filter into a global filter through the RegisterGlobalFilters method in Global.asax. The RegisterGlobalFilters method is called from the Application_Start method, which ensures that the filters are registered when your MVC application starts.

Example:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new ExecutionTimeResultAttribute());
    filters.Add(new MyExceptionAttribute());
}

Filter Scope and Order:  

The Scope enumeration value specifies the order for filters. This enumeration defines the following filter scope:

Name
Description
First
Specifies first.
Global
Specifies an order before Controller and after First.
Controller
Specifies an order before Action and after Global.
Action
Specifies an order before Last and after Controller.
Last
Specifies last.

We can also take control execution order of filter to specify order if scope is same.

For example, an OnActionExecuting(ActionExecutingContext) filter that has the Order property set to zero and filter scope set to First runs before an action filter that has the Order property set to zero and filter scope set to Action. Because exception filters run in reverse order, an exception filter that has the Order property set to zero and filter scope set to First runs after an action filter that has the Order property set to zero and filter scope set to Action.

The execution order of filters that have the same type, order, and scope is undefined.
The OnActionExecuting(ActionExecutingContext), OnResultExecuting(ResultExecutingContext), and OnAuthorization(AuthorizationContext) filters run in forward order. The OnActionExecuted(ActionExecutedContext), OnResultExecuting(ResultExecutingContext), and OnException(ExceptionContext) filters run in reverse order.

If we don’t specify a value for the Order property, it is assigned a default value of -1. This means that if you mix filters so that some have Order values and others don’t, the ones without these values will be executed first, since they have the lowest Order value.

Example:
// AttributeTargets  : Attribute can be applied to a method and class.
// AllowMultiple : True if more than one instance is allowed to be specified;
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
public class SampleAttribute : FilterAttribute, IActionFilter
{
    public string ExecutionOrder { get; set; }
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Write(ExecutionOrder);
    }
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.Write(ExecutionOrder);
    }
}

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new SampleAttribute() { Message = "Global", Order = 1 });
}

[Sample(Message = "Controller", Order = 1)]
public class DemoController : Controller
{
    [Sample(Message = "Action", Order = 1)]
    [Sample(Message = "Action2", Order = 2)]
    public ActionResult Index()
    {
        Response.Write("Action method");
        return View();
    }
}

Order of execution for OnActionExecuting would be:
Global => Contoller => Action => Action2 =>  Action method
Order of execution for OnActionExecuted would be:
Action method => Action2  => Action => Contoller => Global


It's important to note here that "Controller" scope means "filters applied at the controller level"; the controller itself is also a filter which always runs first (that is, its order is Int32.MinValue and Scope is First). The execution order of filters with the same order and scope is undefined.

Canceling Filter Execution: We can cancel filter execution in the OnActionExecuting and OnResultExecuting methods by setting the Result property to a non-null value. Any pending OnActionExecuted and OnActionExecuting filters will not be invoked and the invoker will not call the OnActionExecuted method for the canceled filter or for pending filters. The OnActionExecuted filter for previously run filters will run. All of the OnResultExecutingand OnResultExecuted filters will run.

Example:
if (filterContext.RouteData.Values.ContainsValue("Cancel")) {
    filterContext.Result = new RedirectResult("~/Home/Index");
}

Other important built-in filters:
OutputCache: The OutputCache filter tells the MVC Framework to cache the output from an action method so that the same content can be reused to service subsequent requests for the same URL. There is number of parameters in OutputCache filter to manage caching.

Example:
[OutputCache(Duration = 30)]
public ActionResult About()
{
   return View();
}

RequireHttps: The RequireHttps filter helps to force the client to access a particular action to be accessed over HTTPS channel. If the action is not accessed over HTTPS then the filter redirect the user to access the same over HTTPS. The important thing is this filter works only for the GET requests.

Example:
[RequireHttps]
public ActionResult Login(string name, string password)
{

}

ChildActionOnly: A child action method renders inline HTML markup for part of a view instead of rendering a whole view. Child actions cannot be called directly called from the browser. Any method that is marked with ChildActionOnlyAttribute can be called only with the Action or RenderAction HTML extension methods.

Example:
[ChildActionOnly]
public ViewResult Header()
{
    string ="This is header";
    return PartialView(header);
}

@Html.Action("Header")
@Html.RenderAction("Header")

Other Posts: MVC3 Overview | Controller and Actions

Monday 28 January 2013

ASP.NET MVC Controller and Actions


Controllers are classes which are responsible for processing incoming requests, performing operations on the domain model, and selecting views to render to the user.

Controller classes must implement the IController interface from the
System.Web.Mvc namespace.

public interface IController {
void Execute(RequestContext requestContext);
}

The base class for all controllers is the ControllerBase class, which provides general MVC handling. The Controller class inherits from ControllerBase and is the default implement of a controller. The Controller class is responsible for the following processing stages:

Locating the appropriate action method to call and validating that it can be called.

Getting the values to use as the action method's arguments.

Handling all errors that might occur during the execution of the action method.

Providing the default WebFormViewEngine class for rendering ASP.NET page types (views).

All controller classes must be named by using the "Controller" suffix.

Main features of controller:
• Action methods: Action method is exposed on a different URL and is invoked with parameters extracted from the incoming request.
• Action results: Action methods return an instance of a class that derives from ActionResult. The ActionResult class is the base for all action results.
• Filters: You can encapsulate reusable behaviors as filters, and then tag each behavior onto one or more controllers or action methods by putting an [Attribute] in your source code.
  

Actions Methods: Action method typically map with user interaction.  When user requests a URL, the MVC use the route to determine controller and action method to handle the request. Most action method returns an instance of ActionResult.

Receiving Input: Controllers access incoming data, such as query string values, form values, and parameters parsed from the incoming URL by the routing system.

Commonly Used Context Objects use to get data are:
Property Type Description
Request.QueryString NameValueCollection GET variables sent with this request
Request.Form NameValueCollection POST variables sent with this request
Request.Cookies HttpCookieCollection Cookies sent by the browser with this
Request.HttpMethod string The HTTP method (verb, such as GET or POST) used for this request
Request.Headers NameValueCollection The full set of HTTP headers sent with this request.
Request.Url Uri The URL requested
Request.UserHostAddress string The IP address of the user making this
RouteData.Route RouteBase The chosen RouteTable.Routes entry for this request
RouteData.Values RouteValueDictionary Active route parameters (either extracted from the URL or default values)
HttpContext.Application HttpApplicationStateBase Application state store
HttpContext.Cache Cache Application cache store
HttpContext.Items IDictionary State store for the current request
HttpContext.Session HttpSessionStateBase State store for the visitor’s session
User IPrincipal Authentication information about the logged-in user
TempData TempDataDictionary Temporary data items stored for the current user

Action Methods Parameters:

Value-type parameters are compulsory. To make them optional, either specify a default value or change the parameter type to a nullable type, so the MVC Framework can pass null if no value is available.

Reference-type parameters are optional. To make them compulsory (to ensure that a non-null value is passed), add some code to the top of the action method to reject null values.

ActionResult Return Type: ActionResult class is the base for all action results. However, there are different action result types, depending on the task that the action method is performing. The most common action is to call the View method. The View method returns an instance of the ViewResult class, which is derived from ActionResult.
The following table shows the built-in action result types and the action helper methods that return them.


Action Result
Helper Method
Description
ViewResult View Renders a view as a Web page.
PartialViewResult PartialView Renders a partial view, which defines a section of a view that can be rendered inside another view.
RedirectResult Redirect Redirects to another action method by using its URL.
RedirectToRouteResult RedirectToAction
RedirectToRoute
Redirects to another action method.
ContentResult Content Returns a user-defined content type.
JsonResult Json Returns a serialized JSON object.
JavaScriptResult JavaScript Returns a script that can be executed on the client.
FileResult File Returns binary output to write to the response.
EmptyResult (None) Represents a return value that is used if the action method must return a null result (void).

Examples:
public ViewResult Index()
        {
            ViewBag.CurrentDate = DateTime.Now;
            ViewData["Message"] = "Hello";
            var model = new IndexModel()
            return View(model);
        }

        public ContentResult Index(string contentType)
        {
            switch (contentType)
            {
                case "plain" :
                    return Content("This is plain text", "text/plain", Encoding.Default);
                    break;
                case "xml":
                     XElement data = new XElement("Emp", new XAttribute("firstname", e.Title), new XAttribute("lastname", e.Description));
                     return Content(data.ToString(), "text/xml");
                    break;
                default:
                    return Content("This is plain text", "text/plain", Encoding.Default);
                    break;
            }
        }

     
        public JsonResult JsonData()
        {
            var model = new IndexModel()
            return Json(model);
        }

        public FileResult AnnualReport()
        {
            string filename = @"c:\Report.pdf";
            string contentType = "application/pdf";
            string downloadName = "Report2013.pdf";
            return File(filename, contentType, downloadName);
        }

        public FileStreamResult DownloadReport(){
            Stream stream = "...stream...";
            return File(stream, "text/html");
        }

        public HttpStatusCodeResult StatusCode()
        {
            return new HttpStatusCodeResult(404, "URL cannot be serviced");
        }


Other Posts: MVC3 Overview | Filters