Monday, November 14, 2011

Less CSS and IIS 7

In case you are using Less CSS to generate CSS markups, IIS won’t find your .less files by default. You will get a 404 Not Found error. The problem is the missing MIME type.

The solution is simple, just register the MIME type for .less in web.config:

<system.webServer>
<staticContent>
<mimeMap fileExtension=".less" mimeType="text/css"/>
</staticContent>
</system.webServer>

Sunday, September 18, 2011

ASP.NET MVC Internals 3: Controller structure

Controllers implement the IController interface:
public interface IController 
{
    void Execute(RequestContext requestContext);
}
ControllerBase abstract class implements the IController interface:
public abstract class ControllerBase : MarshalByRefObject, IController 
{

    private TempDataDictionary _tempDataDictionary;
    private bool _validateRequest = true;
    private IDictionary<string, ValueProviderResult> _valueProvider;
    private ViewDataDictionary _viewDataDictionary;

    public ControllerContext ControllerContext {
        get;
        set;
    }

    public TempDataDictionary TempData {
        get {
            if (_tempDataDictionary == null) {
                _tempDataDictionary = new TempDataDictionary();
            }
            return _tempDataDictionary;
        }
        set {
            _tempDataDictionary = value;
        }
    }

    public bool ValidateRequest {
        get {
            return _validateRequest;
        }
        set {
            _validateRequest = value;
        }
    }

    public IDictionary<string, ValueProviderResult> ValueProvider {
        get {
            if (_valueProvider == null) {
                _valueProvider = new ValueProviderDictionary(ControllerContext);
            }
            return _valueProvider;
        }
        set {
            _valueProvider = value;
        }
    }

    public ViewDataDictionary ViewData {
        get {
            if (_viewDataDictionary == null) {
                _viewDataDictionary = new ViewDataDictionary();
            }
            return _viewDataDictionary;
        }
        set {
            _viewDataDictionary = value;
        }
    }

    protected virtual void Execute(RequestContext requestContext) {
        if (requestContext == null) {
            throw new ArgumentNullException("requestContext");
        }

        Initialize(requestContext);
        ExecuteCore();
    }

    protected abstract void ExecuteCore();

    protected virtual void Initialize(RequestContext requestContext) {
        ControllerContext = new ControllerContext(requestContext, this);
    }
    
    [...]
}

Saturday, September 17, 2011

ASP.NET MVC Internals 2: Controller

The MvcHandler class processes an HTTP request. The routing framework calls its ProcessRequest() function in case of an incoming request matching an MVC route.
public class MvcHandler : IHttpHandler, IRequiresSessionState 
{
    [...]
    protected internal virtual void ProcessRequest(HttpContextBase httpContext) 
    {
        AddVersionHeader(httpContext);

        // Get the controller type
        string controllerName = RequestContext.RouteData.GetRequiredString(&quot;controller&quot;);

        // Instantiate the controller and call Execute
        IControllerFactory factory = ControllerBuilder.GetControllerFactory();
        IController controller = factory.CreateController(RequestContext, controllerName);
        if (controller == null) {
            throw new InvalidOperationException(
                String.Format(
                    CultureInfo.CurrentUICulture,
                    MvcResources.ControllerBuilder_FactoryReturnedNull,
                    factory.GetType(),
                    controllerName));
        }
        try {
            controller.Execute(RequestContext);
        }
        finally {
            factory.ReleaseController(controller);
        }
    }
    [...]
}

Firstly it reads the controller name from the routing data and after that it creates a controller by the name read before. Finally it calls the Execute method of the controller to run the controller’s code.

Thursday, September 15, 2011

ASP.NET MVC Internals 1: Bootstrapping

The topic of this article is the ASP.NET MVC bootstrapping process.

Everything starts in Global.asax:

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );

    }

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
    }
}

This code initializes the ASP.NET Routing framework. The MapRoute() function is an extension method, defined in RouteCollectionExtensions.cs. It’s code is simple:

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
	if (routes == null) {
		throw new ArgumentNullException("routes");
	}
	if (url == null) {
		throw new ArgumentNullException("url");
	}

	Route route = new Route(url, new MvcRouteHandler()) {
		Defaults = new RouteValueDictionary(defaults),
		Constraints = new RouteValueDictionary(constraints)
	};

	if ((namespaces != null) && (namespaces.Length > 0)) {
		route.DataTokens = new RouteValueDictionary();
		route.DataTokens["Namespaces"] = namespaces;
	}

	routes.Add(name, route);

	return route;
}

Simply creates a route with an MvcRouteHandler at line 9. ASP.NET MVC registers this routing handler to catch the routing requests (MvcRouteHandler.cs):

namespace System.Web.Mvc {
    using System.Web.Routing;

    public class MvcRouteHandler : IRouteHandler {
        protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) {
            return new MvcHandler(requestContext);
        }

        #region IRouteHandler Members
        IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) {
            return GetHttpHandler(requestContext);
        }
        #endregion
    }
}

This code registers the MvcHandler class (MvcHandler.cs) for handling MVC routing requests:

public class MvcHandler : IHttpHandler, IRequiresSessionState 
{ [...] }

The class implements the IHttpHandler interface from System.Web.dll to be able to ‘synchronously process HTTP Web requests using custom HTTP handlers’. This interface has only one method:

void ProcessRequest(httpContext context)

The implementation of this method will handle the HTTP request. It builds up the MVC infrastructure and calls the appropriate classes (in transitive way) to select the controller, find the action method and do all the related functionality.

Photobucket

Link: ASP.MET MVC Bootstrapping process