European ASP.NET MVC Hosting

BLOG about Latest ASP.NET MVC Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET MVC 3 Hosting :: The Reason You Should Use ViewModels

clock October 14, 2011 08:02 by author Scott

This is the reason why you should use View Models:

1. Remove logic from your Views

When you start working with ASP.NET MVC, you’ll most likely ask yourself why you should use a View Model. Using your domain model or entity model works perfectly fine. And it does. For a while. But as you continue to use your Models, you’ll discover that you have to add some adaptations in your Views. Here is a typical usage adaptation (using the Razor View engine):

Hello @model.UserName

Your age: @(model.Age != 0 ? model.Age.ToString() : "n/a")

Not so bad, is it? The problem is that you have introduced logic into your View, which is bad for two reasons:

1. You can not unit test that code, and the only way to make sure that it works is user testing.
2. You need to repeat that code for every View that intends to use your Model (code duplication = code smell).

All those small adaptations will lead to a big mess eventually.

2. Security

One of the biggest advantages with View Models is removing security risks. Your database objects or domain objects will most likely contain properties that the user should not be able to change. It can be a property called IsAdmin or Reputation.


All those properties will automatically be changed by the model binder if they exist in the model (and are posted in the FORM, which is quite easy to do if you know HTML). Simply remove them from the View Model and they’ll never be changed.

3. Loose coupling

By using domain models or entity models, you are adding coupling between your lower layers and the presentation layer, and that is seldom good. Google “loose coupling” to find out more.

Basically, it means that if you change your domain/entity model, you have to change all your Views that use that Model. If you use a ViewModel, you only have to change the code that maps between an entity/domain model and the View Model.



European ASP.NET MVC 3 Hosting :: How to Add ELMAH in your ASP.NET MVC Application

clock October 6, 2011 10:12 by author Scott

In this tutorial, you will find a step by step instruction how to add ELMAH (Error Logging Modules and Handlers for ASP.NET) to your existing ASP.NET MVC application. ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.

I've tested the steps below with ASP.NET MVC 2 and ASP.NET MVC 3 applications, but they may work also for other types of ASP.NET applications.

First you have to download ELMAH from the
download page. After adding a reference to Elmah.dll in your project, all you have to do is to add the ELMAH configuration to your Web.config.

The example configuration shown above includes two customizings I found very useful for web applications:

- If the server returns a status code between 400 (included) and 500 (excluded), ELMAH ignores the exceptions.
- A remote access to the /elmah.axd web interface is enabled for specific (admin) users.

<configSections>
  [...]
  <sectionGroup name="elmah">
    <section name="security" requirePermission="false"
type="Elmah.SecuritySectionHandler, Elmah" />

    <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
    <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
    <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
  </sectionGroup>
  [...]
</configSections> 

<system.web>
  [...]
  <httpHandlers>
    <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
  </httpHandlers>
  <httpModules>
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
    <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
    <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
  </httpModules>
  [...]
</system.web> 

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
  </modules>
  <handlers>
    <add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
  </handlers>
</system.webServer> 

<elmah>
  <security allowRemoteAccess="1" />
  <errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/App_Data" />
  <errorMail from="[FROM_ADDRESS]" to="[TO_ADDRESS]" subject="[SUBJECT]" async="true" smtpPort="25" smtpServer="[SMTP_SERVER]"/>
  <errorFilter>
    <test>
      <and>
        <greater binding="HttpStatusCode" value="399" type="Int32" />
        <lesser binding="HttpStatusCode" value="500" type="Int32" />
      </and>
    </test>
  </errorFilter>
</elmah> 

<location path="elmah.axd">
  <system.web>
    <authorization>
      <allow users="[ALLOWED_ADMIN_USERS]" />
      <deny users="*" />
    </authorization>
  </system.web>
</location>



European ASP.NET MVC 3 Hosting :: ASP.NET MVC 3 Model Metadata Providers

clock October 5, 2011 09:37 by author Scott

There are different types of filters in MVC. Depending on the type of the Filter, and the scope of the Filter, the order of the execution also changes.

You may already aware that there are different types of filters within MVC framework. They are listed below.

1. Authorization filters
2. Action filters
3. Response/Result filters
4. Exception filters

The above list is ordered as exactly the order they executes within MVC framework. The Authorization filters always run first, and the Exception filters run at the end.

Specifying the Order property for Filters

Within each filter, you may specify the Order property. (All filters are derived from the abstract class FilterAttribute, and this class has an Order property). This property will ensure the filter runs in a specific Order. For an example, let’s say we have 2 Authorization filters, AuthorizationFilterA and AuthorizationFilterB and they are implemented as below.


public class AuthorizationFilterA : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        Debug.WriteLine("OnAuthorization : AuthorizationFilterA");
    }
}

public class AuthorizationFilterB : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        Debug.WriteLine("OnAuthorization : AuthorizationFilterB");
    }
}

Now, if I want these two filters to run in a specific order - AuthorizationFilterB to run first, and AuthorizationFilterA to run second, I can simply specify the execution order as below.


[AuthorizationFilterA(Order=2)]
[AuthorizationFilterB(Order=1)]
public ActionResult Index()
{
    return View();
}

When you run the code, the Output window should display that AuthorizationFilterB runs first, AuthorizationFilterA runs second.

OnAuthorization : AuthorizationFilterB

OnAuthorization : AuthorizationFilterA

Filter Scope

Within each filter type, you can define a scope. For an example, I could scope all my Authorization Filters to run within the Controller Scope, and all Action Filters to run in Global scope (Every Action within the MVC application).

FilterScope.Global is a new scope which was introduced in MVC 3. The existing scopes are First, Controller, Action, and Last. The complete enumeration is defined as below.

namespace System.Web.Mvc {
    public enum FilterScope
        First = 0,
        Global = 10,
        Controller = 20,
        Action = 30,
        Last = 100,
    }
}

By default, the filters with the lowest scope runs first. For an example, scope Global (10) executes first and scope Controller (20) executes second.


Filter Scope with explicit Ordering

Below example shows, how explicit filter ordering (using Order property) and scope of the filters determine their correct run order.

Let’s add the scope to our existing Authorization Filters – AuthorisationFilterA and AuthorisationFilterB. Please note that we haven’t changed the usage of Order property.

AuthorizationFilterA(Order 2) has the scope Global.

AuthorizationFilterB(Order 1) has the scope Action.

public class AuthorizationFilterA : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        Debug.WriteLine("OnAuthorization : AuthorizationFilterA (Order: 2) in scope : Global");
    }
}

public class AuthorizationFilterB : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        Debug.WriteLine("OnAuthorization : AuthorizationFilterB (Order: 1) in scope : Action");
    }
}


[AuthorizationFilterB(Order = 1)]
public ActionResult Index()
{
    return View();
}

GobalFilters.Filters.Add(new AuthorizationFilterA() { Order = 2});

According to the above Filter Scope enumeration, if we were to specify only the scope but not the Order property, then we would expect AuthorizationFilterA (in Global scope) to run first, and AuthorizationFilterB (in Action scope) to run second. Since we are explicitly specifying the Order property for both filters, AuthorizationFilterB (in Action scope – Order 1) runs first and AuthorizationFilterA (in Global scope – Order 2) runs second.


Output:

OnAuthorization : AuthorizationFilterB (Order: 1) in scope : Action

OnAuthorization : AuthorizationFilterA (Order: 2) in scope : Global

Now let’s add another Authorization filter (AuthorizationFilterC) to Global scope. Also note that we have not specified the Order property.

public class AuthorizationFilterC : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            Debug.WriteLine("OnAuthorization : AuthorizationFilterC (no Order defined) in scope : Global");
        }
    }

GlobalFilters.Filters.Add(new AuthorizationFilterC());

After running all three filters, you can see the output as below. 

Output

OnAuthorization : AuthorizationFilterC (no Order defined) in scope : Global

OnAuthorization : AuthorizationFilterB (Order: 1) in scope : Action

OnAuthorization : AuthorizationFilterA (Order: 2) in scope : Global

For same Filter type, the filters without the explicit ordering (i.e AuthorizationFilterC) take precedence over the filters with explicit ordering (AuthorizationFilterB, AuthorizationFilterA).

Now let’s remove the Order property from both AuthorizationFilterB and AuthorizationFilterA

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

GlobalFilters.Filters.Add(new AuthorizationFilterA());

Output:

OnAuthorization : AuthorizationFilterA (no order defined) in scope : Global

OnAuthorization : AuthorizationFilterC (no order defined) in scope : Global

OnAuthorization : AuthorizationFilterB (no order defined) in scope : Action

As we would expect, the filters with scope Global (AuthorizationFilterA and AuthorizationFilterC) run first and second in order, the scope Action filter (AuthorizationFilterC) runs at the end. 2 Global filters (AuthorizationFilterA and AuthorizationFilterC) run order relies on the order which they were added to the Global Filter collection. In this example AuthorizationFilterA which was added prior to AuthorizationFilterC , runs first.

For the same filters, when determine the run order, first it sorts them by their order (lowest numbers first), and then by their scope (also lowest numbers first).

Controller as a Filter

In MVC the Controller itself is also a Filter. Controller implements all filters, so Controller can subscribe to all filter events.

public abstract class Controller : ControllerBase,
IActionFilter, IAuthorizationFilter, IDisposable,
IExceptionFilter, IResultFilter

MVC framework ensures, the Controller always runs first, before any other filters get executed. It has been accomplished by specifying the scope as the First and the order property as Int32.MinValue. By default, an MVC filter has the value for the Order -1. Therefore Int32.MinValue along with the Scope First together ensures the Controller always runs first.

public class ControllerInstanceFilterProvider : IFilterProvider {
        public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
            if (controllerContext.Controller != null) {
               
// Use FilterScope.First and Order of Int32.MinValue to ensure controller instance methods always run first
                yield return new Filter(controllerContext.Controller, FilterScope.First, Int32.MinValue);
            }
        }
    }

Forward Filter Order and Reverse Filter Order

So far we have discussed the order of filters which get executed based on the explicit ordering (using Order property) and the scope which they can be belong to. However, MVC filters run order, do not only rely only by these two factors. Sometimes filters run in forward order and sometimes filters run in reverse order. Let’s see the below example.

Let’s say I have three Action filters (ActionFilter1, ActionFilter2, ActionFilter3), one Authorization filter (AuthorizationFilter) and two Exception filters (HandleErrorA, HandleErrorB). They are implemented as below.

public class ActionFilter1 : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Debug.WriteLine("Forward Order - OnActionExecuting : ActionFilter1 (Scope Global)");
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnActionExecuted : ActionFilter1 (Scope Global)");
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        Debug.WriteLine("Forward Order - OnResultExecuting : ActionFilter1 (Scope Global)");
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnResultExecuted : ActionFilter1 (Scope Global)");
    }
}


public class ActionFilter2 : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Debug.WriteLine("Forward Order - OnActionExecuting : ActionFilter2 (Scope Controller)");
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnActionExecuted : ActionFilter2 (Scope Controller)");
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        Debug.WriteLine("Forward Order - OnResultExecuting : ActionFilter2 (Scope Controller)");
    } 

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnResultExecuted : ActionFilter2 (Scope Controller)");
    }
}

public class ActionFilter3 : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Debug.WriteLine("Forward Order - OnActionExecuting : ActionFilter3 (Scope Action)");
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnActionExecuted : ActionFilter3 (Scope Action)");
    } 

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        Debug.WriteLine("Forward Order - OnResultExecuting : ActionFilter3 (Scope Action)");
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnResultExecuted : ActionFilter3 (Scope Action)");
    }
}    


public class AuthorizationFilter : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        Debug.WriteLine("Forward Order - OnAuthorization : AuthorizationFilter (Scope Controller)");
    }
}   


public class HandleErrorA : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnException : HandleErrorA (Scope Action)");
    }
}

public class HandleErrorB : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnException : HandleErrorB (Scope Action)");
    }
}

We will register the above filters as below…


ActionFilter1 has the scope Global, ActionFIlter2 has the scope Controller, ActionFIlter3 has the Scope Action, AuthorizationFilter has the scope Controller, HandleErrorA has the scope Global, and HandleErrorB has the scope Action.

At the beginning of this article I mentioned that the run order of different types of filters. First Authorization filters, then Action Filters, followed by Result filters and at the end the Exception filters. This is true, however within each type of filters, some executes in reverse order and some executes in forward order.

The best way to explain is to examine the generated output.

Forward Order - OnAuthorization : AuthorizationFilter (Scope Controller)

Forward Order - OnActionExecuting : ActionFilter1 (Scope Global)

Forward Order - OnActionExecuting : ActionFilter2 (Scope Controller)

Forward Order - OnActionExecuting : ActionFilter3 (Scope Action)

Home Controller, Index Action

Reverse Order - OnActionExecuted : ActionFilter3 (Scope Action)

Reverse Order - OnActionExecuted : ActionFilter2 (Scope Controller)

Reverse Order - OnActionExecuted : ActionFilter1 (Scope Global)

Forward Order - OnResultExecuting : ActionFilter1 (Scope Global)

Forward Order - OnResultExecuting : ActionFilter2 (Scope Controller)

Forward Order - OnResultExecuting : ActionFilter3 (Scope Action)

Reverse Order - OnResultExecuted : ActionFilter3 (Scope Action)

Reverse Order - OnResultExecuted : ActionFilter2 (Scope Controller)

Reverse Order - OnResultExecuted : ActionFilter1 (Scope Global)

Reverse Order - OnException : HandleErrorB (Scope Action)

Reverse Order - OnException : HandleErrorA (Scope Global)

-
There is only one Authorization Filter in Controller scope and it runs first as expected.

-
The Action Filters run at second. Notice that OnActionExecuting event runs in an order where the order of filter execution is determined by their scope (lowest number first in the enumeration). As you see, Action Filters OnActionExecuting event runs in a forward order.

-
Home Controller’s Index Action executes.

-
Action Filters do not always run in forward order. As you see during OnActionExecuted event, they run in a reverse order.

-
Very similar to OnActionExecuted event, OnResultExecuted event runs in reverse order.

-
Error Handler filters run at last. For each Error Handler filter, OnException event runs in  reverse order. Prior to MVC 3, ErrorHandler’s OnException event ran in forward order. This approach makes MVC exception filters more aligned with .NET exception handlers.

Summary

There are multiple factors involved when deciding the run order of MVC filters. This includes the explicit ordering, the scope they belong to, and the type of the filter. Controller itself is a filter and always run first. By design, MVC executes certain filters in specific order. Some are run in forward order and some are run in reverse order.

 



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Month List

Tag cloud

Sign in