Introducing ASP.NET MVC 6

ASP.NET MVC 6 is a ground up rewrite of the popular .NET web platform. Sweeping changes were made throughout, with even some of the most basic elements being reorganized. These changes are immediately apparent when starting a new MVC6 project, especially to developers familiar with previous versions of the framework.

Let’s hit “file new project” and take a tour of the new MVC6 project template. We’ll look at what’s missing from MVC5, what we can expect to stay the same, and what’s new.

What’s missing

Before beginning work on a new project it’s important to understand where some familiar items have gone. Considering that MVC6 is a complete rewrite, some changes should be expected, however there are some key players missing that might come as a surprise.

All items in this list that have a replacement counterpart will be explained in detail under the “What’s new” section.

  • App_Start : The App_Start folder previously contained various startup processes and settings such as configuration, identity, and routing. These items have been replaced by the Startup.cs class which is now responsible for all app startup tasks.
  • App_data : The App_data folder once held application data such as local database files and log files. The folder isn’t included in this release but it can be added back and used. If you choose to use the app_data folder, proceed with caution so as to not make files publicly available by accident.
  • Global.ASAX : The Global.ASAX is no longer needed since it was yet another place for startup routines. Instead all startup functionality has been placed in Startup.cs.
  • Web.Config : It may come as a surprise that the root Web.Config file is gone from MVC. The Web.Config was once the XML equivalent to a settings junk drawer, now all application settings are found in config.json. Note: A Web.Config can still be found in MVC for configuring static application resources.
  • Scripts : The scripts directory used to house the application’s JavaScript files has been given a new home. All JavaScript files now reside under wwwroot/js as a static resource.
  • Content : Much like the aforementioned Scripts folder, static site resources can be found under wwwroot.

What’s the same

Very few things remain unchanged in the MVC6 project template. In fact the only three items that really stayed the same are the fundamental components of the MVC pattern itself: Models, Views and Controllers.

  • Models : The models folder remains with a minor change. The Models folder will now contain data Models only.
  • Views : Views in MVC6 are as they were in previous versions, they are dynamic HTML (or .cshtml) rendered on the server before being sent to the client. Views contain the application UI and are by default built with Bootstrap. One new addition to the views folder is the _ViewImports.cshtml. The _ViewImports file provides namespaces which can be used by all other views. In previous MVC projects, this functionality was the responsibility of the web.config file in the Views folder. However, the web.config no longer exists and global namespaces are now provided by _ViewImports.
  • ViewModels : The ViewModels folder was added to differentiate between models used for data and models used specifically for View data. This addition helps promote separation of concerns within the application.
  • Controllers : In MVC6 the controllers folder retains its responsibility to hold application controllers. Controllers were commonly used to return views, but can serve as Web API endpoints now that Web API and MVC have merged. In MVC6, both MVC controllers and Web API controllers use the same routes and Controller base class.

What’s new

At first glance, it’s apparent that there’s a lot of new parts to an MVC project. From the root folder down there are many new files and folders that come with all new conventions. Let’s explore the new items and understand their purpose in the project.

  • src : The absolute root folder of the project is the src (source) folder. This folder is used to identify the source code of the project. It was added in this version of .NET to match a convention commonly found in open source projects, including many popular ones on GitHub.
  • wwwroot : The wwwroot folder is used by the host to serve static resources. Sub-folders include js (JavaScript), CSS, Images and lib. The lib folder contains third party JavaScript libraries that were added via the Bower package manager.
  • Dependencies : More package management options are available in MVC 6. Bower and NPM support has been added in this version. Configuration for both Bower and NPM can be managed via the GUI here. Additionally, configuration can be managed by their respective .json files found in the root src folder.
  • Migrations : MVC 6 ships with Entity Framework 7 (EF7) which no longer supports EDMX database modeling. Because EF7 is focused on code first, the migrations folder is where you’ll find database creation, initialization, and migration code.
  • Services : Services are at the forefront of MVC 6. Since MVC 6 was built with dependency injection at it’s core, services can easily be instantiated by the framework and used throughout the application.
  • bower.json & package.json : To support “all things web,” MVC 6 has added first class support for Bower and NPM. These popular package management systems were born from the web and open source development communities. Bower hosts popular packages like Bootstrap while NPM brings in dependencies like Gulp. The bower.json and package.json files are used to register and install Bower and NPM packages with full Intellisense support.
  • gulpfile.js : Gulp is another tool built “for the web, by the web.” It is given first class support in MVC 6. Gulp is a Node.js-based task runner that has many plug-ins available from NPM. There are packages for compiling, minifying and bundling CSS. There are also packages for .NET developers for invoking MSBuild, NuGet, NUnit and more. gulpfile.js is where Gulp tasks are defined for the application.
  • hosting.ini : ASP.NET 5 is designed with a pluggable server layer, removing the hard dependency on IIS. The hosting.ini file is mainly used for configuring WebListener for hosting without IIS & IIS Express.
  • project.json : The project.json file is used to describe the application and its .NET dependencies. Unlike prior versions of MVC, .NET dependencies for your application can be added and removed using the project.json file. These dependencies are resolved through NuGet and full Intellisense is enabled within the file. This means that you can begin typing the desired NuGet package name and suggestions will appear on-the-fly. Cross platform compilation and build scripts are also configured here.
  • startup.cs : In previous versions, MVC application startup was handled in App_Start and Global.asax. With ASP.NET 5, startup is handled in Startup.cs. The Startup method is the first method in the application to run and is only run once. During startup the application’s configuration is read, dependencies are resolved and injected, and routes are created.

Wrapping up

The MVC6 project template embraces the web in many ways. From the root folder and below, most of the project structure has changed to align with the ever changing web. The inclusion of NPM and Bower in addition to NuGet provide developers with a wide range of options for bringing modular components to their application. The standardization on the JSON format for configuration further aligns with web methodologies. While many things have changed in the project template, the core MVC components have remained.

“File new project” may be a bit intimidating at first, but knowing where to find each piece and its purpose will give you a head start.

ASP.NET MVC Localization

The goal of this post is to show how to get URL like this /{culture}/{Controller}/{Action}… in your application like /fa/Home/AboutUS

Custom Route Handlers

First of all we’ll need to extend standard MvcRouteHandler class. One class MultiCultureMvcRouteHandler for routes that will use culture in params and SingleCultureMvcRouteHandler class (will be used as a marker, no implementation changes)

public class MultiCultureMvcRouteHandler : MvcRouteHandler
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
        var culture = requestContext.RouteData.Values["culture"].ToString();
        var ci = new CultureInfo(culture);
        Thread.CurrentThread.CurrentUICulture = ci;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
        return base.GetHttpHandler(requestContext);

In the overridden GetHttpHandler before calling it’s base implementation we just get “culture” param from RouteData collection, create CultureInfo object and set it to current thread current culture. So here is a place where we set culture and will not use Application_AcquireRequestState method in Global.asax

public class SingleCultureMvcRouteHandler : MvcRouteHandler {}

As I mention this class will be used only for marking some routes for case if you’ll need some routes to be culture independent.

Registering routes

Now lets go to Global.asax file where we have route registering method RegisterRoutes(). Right after last route mapping add foreach statement code snippet like in the following example.

public static void RegisterRoutes(RouteCollection routes)

    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults

    foreach (Route r in routes)
        if (!(r.RouteHandler is SingleCultureMvcRouteHandler))
            r.RouteHandler = new MultiCultureMvcRouteHandler();
            r.Url = "{culture}/" + r.Url;
            //Adding default culture
            if (r.Defaults == null)
                r.Defaults = new RouteValueDictionary();
            r.Defaults.Add("culture", Culture.fa.ToString());

            //Adding constraint for culture param
            if (r.Constraints == null)
                r.Constraints = new RouteValueDictionary();
            r.Constraints.Add("culture", new CultureConstraint(Culture.en.ToString(),

OK, lets go through this code… So for each route we first of all check whether its handler type is SingleCultureMvcRouteHandler or not… So if not we change RouteHandler property of the current route to MultiCulture one, add prefix to Url, add default culture and finally add constraint for culture param checking.

public class CultureConstraint : IRouteConstraint
    private string[] _values;
    public CultureConstraint(params string[] values)
        this._values = values;
    public bool Match(HttpContextBase httpContext,Route route,string parameterName,
    RouteValueDictionary values, RouteDirection routeDirection)
        // Get the value called "parameterName" from the
        // RouteValueDictionary called "value"
        string value = values[parameterName].ToString();
        // Return true is the list of allowed values contains
        // this value.
        return _values.Contains(value);

And enum of cultures

public enum Culture
    fa = 1,
    en = 2

Simple culture switching mechanism

For changing culture we’ll need following simple action which I placed in AccountController

public ActionResult ChangeCulture(Culture lang, string returnUrl)
    if (returnUrl.Length >= 3)
        returnUrl = returnUrl.Substring(3);
    return Redirect("/" + lang.ToString() + returnUrl);

and partial view with languages links – CultureSwitchControl.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%= Html.ActionLink("eng", "ChangeCulture", "Account",
    new { lang = (int)MvcLocalization.Helpers.Culture.en, returnUrl =
    this.Request.RawUrl }, new { @class = "culture-link" })%>
<%= Html.ActionLink("per", "ChangeCulture", "Account",
    new { lang = (int)MvcLocalization.Helpers.Culture.fa, returnUrl =
    this.Request.RawUrl }, new { @class = "culture-link" })%>

Single culture case

Finally, if we need some single culture route all we need to do is to set RouteHandler property to SingleCultureMvcRouteHandler like this

        new { controller = "Home", action = "About"}
    ).RouteHandler = new SingleCultureMvcRouteHandler();

So, that’s it Localization with use of routing.