Introduction
As Most of You Might Already Be Having Some Experience With ASP.NET Mvc ,Let’s Have a Look Into Some of the New Features Introduced With ASP.NET Mvc 5.We Could Have Implemented Functionality Provided by Some of These New Features in Earlier Versions of Mvc as Well But Now as These Features Are a Part of the Mvc Framework Using Them Is Easier Than Ever as There Are No Configuration Changes or External Components required.As We Discuss the New Features We Would Be Refreshing Our Knowledge of the Functionality Provided in the Prior Versions Before the Introduction of These New Features.
The first feature that would be specially useful for us is Attribute based routing. To understand Attribute based routing we will see how routing is implemented in the previous versions of MVC.
Routing in MVC
As MVC is all about creating loosely coupled applications ,most of the features in MVC compliment creating loosely coupled architecture. Routing is one such MVC feature which decouples the URL schema of the application from the rest of the application. To understand use of routing let's see how request handling was done one or two decades earlier.
In ASP.NET webforms and in previous web technologies whenever we make a browser request for a resource such as a web page, the web server expects that it exists physically on the server which it returns to the browser ,either executing it and returning the HTML (in the case of dynamic pages such as aspx pages) or as such if it’s an html page. In other words there has to be One to One mapping between the URL and the requested resource such as the web form or the html page.
Request handling in conventional Web Forms application 's
This was the normal scenario prior to the ASP.NET MVC. In ASP.NET MVC since the request is handled by action methods there has to be some way to map the URL to the appropriate action method as there is no physical file to handle the requested URL.This mapping is provided by the routing system.
Request handling in MVC application
All the routes used in the application are added to the RouteCollection .So routing system acts as an interface between the request and the request handler. This means we can structure our URL according to our requirement like we can create user friendly and Search Engine Optimized URL's. Also the URL's can be changed anytime without requiring the change to the application logic since the application logic is decoupled from the URL schema used in the application.
Following is the basic structure of a requested URL as understood by the routing system.
Notice that the segments are a part of the URL separated by the slash character (“/”) excluding the host name. We can define a route to handle the above URL in the RegisterRoutes method in RouteConfig.cs file as
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Ecommerce",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "About", id = UrlParameter.Optional }
);
}
Here url is the url -pattern that is used to determine if the incoming url should be handled by the route as Mvc application can have multiple routes.The segments in the url-pattern in the braces {} are called the segments variables ,like {controller},{action} and {id} .The values for these segment variables are extracted from the url.Though we have used variables here segments can also be a literal like a string.
The above route is added to the routes route collection when the application is initialized as the method is called from the Application_Start method in global.asax.
Now suppose we want to change the url-pattern that is handled by a specific action method in a controller we need to make the change in the common RegisterRoutes method.This has the following disadvantages
- Since RegisterRoutes is the common method which define's all the routes in the application ,our change could break the url handling of the application.
- Since routing is setup when the application is launched we don’t have any easy way to change the routing schema of the application without effecting the existing routes in the application as we need to consider the order in which we have to add our route(as routes are evaluated from top to bottom).This requires proper testing for verifying if new bugs are introduced because of a newly added route.
- Also keeping the route definition separate from the controller and action methods which is the handler of the request is not much intuitive.
Attribute based routing provides an elegant way to solve this issue.
Attribute based routing in MVC 5
This is where attribute based routing comes in. Using attribute based routing we can define the route in the same place where action method is defined. Following is an example of a route defined using the Route attribute. As you can see the route is directly attached to the action method.
[Route("Products/Electronics/{id}")]
public ActionResult GetElectronicItems(string id)
{
ViewBag.Id = id;
return View();
}
To enable attribute based routing we need to add the following in the RouteConfig file.
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcAttributeRoutes();
}
So now we have attached the Route attribute to our action method our action method will be able to handle the requests which matches the URL pattern defined by the Route attribute.
Optional Parameter
We can also specify if there is any optional parameter in the URL pattern defined by the Route attribute with the “?” character.
If the above action method is called and and the value for “id” parameter is not provided we will get an exception since id is a required parameter. We can make it an optional parameter by making the following changes.
[Route("Products/Electronics/{id?}")]
public ActionResult GetElectronicItems(int? id) {
ViewBag.Id = id; return View();
}
Note that we have made id an optional parameter by using “?”.Also since id is a value type we have to make it nullable type since we always need to provide values for value type parameters as they cannot have null values.
Route constraints
We can also specify parameter constraints placing the constraint name after the parameter name separated by colon. For example we can specify that the parameter type should be integer by using the following
[Route("Products/Electronics/{id:int}")]
Now If we do not specify integer parameter then the route will not match even if other segments match. Some of the other useful constraints that we can use in Route attribute are:
Route Constraint
| Used To
|
x:bool
| Match a bool parameter
|
x:maxlength(n)
| Match a string parameter with maximum length of n characters
|
x:minlength(n)
| Match a string parameter with minimum length of n characters
|
x:max
| Match an integer parameter with a maximum value of n.
|
x:min
| Match an integer parameter with a minimum value of n.
|
x:range
| Match an integer parameter within a range of values.
|
x:float
| Match floating-point parameter.
|
x:alpha
| Match uppercase or lowercase alphabet characters
|
x:regex
| Match a regular expression.
|
x:datetime
| Match a DateTime parameter.
|
Route Prefix
If we have multiple action methods in a controller all using the same prefix we can use RoutePrefix attribute on the controller instead of putting that prefix on every action method.
Like we can attach the following attribute on the controller
[RoutePrefix("Products")]
So now our Route attribute on our action method does not need to specify the common prefix
[Route("Electronics/{id}")]
Filter's in MVC
Filters in MVC provide us with an elegant way to implement cross cutting concerns.Cross cutting concerns is the functionality that is used across our application in different layers.Common example of such functionality includes caching ,exception handling and logging.
Cross cutting concerns should be centralized in one location instead of being scattered and duplicated across the entire application.This makes updating such functionality very easy as it is centralized in one location. Filters provide this advantage as they are used to implement cross cutting concerns using a common logic that can be applied to different action methods and controllers.Filters are implemented as classes that contains code that is executed either before the action method is executed or after the action method executes. We can create global or controller filters in MVC 4.Global filters are filters that are applied to all the action methods in the application while controller filters apply to all the action methods in the controller.
We can create a global filter by creating a class and registering it as a global filter
public class TestGlobalFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
context.RequestContext.HttpContext.Response.Write("Global filter's in MVC are cool...");
}
}
GlobalFilters.Filters.Add(new TestGlobalFilterAttribute());
As we have registered our filter as global action filter this will automatically cause the filter to execute for any action method .Below we can see our global filter in action.
Now suppose we want one of our action method’s not to execute filter logic.In MVC 4 there is not direct way to implement this.
Filter Overrides in MVC 5
MVC 5 provides a filter overrides feature which we can apply to the action method or controller which selectively excludes the global filter or the controller filter for the specified action method or controller.
Now if want to override our global action filter in one of our action method's then we just need to apply the OverrideActionFilters attribute.Below we have applied the attribute to the default About method in the HomeController.
[OverrideActionFilters]
public ActionResult About(){
ViewBag.Message = "Your application description page.";
return View();
}
This is a very simple example to understand Filter overrides.But they can be useful in many different scenarios.One scenario where it is useful is :
[Authorize(Users="ashish")][RoutePrefix("Products")]
public class ProductsController : Controller
{
[Route("Electronics/{categoryId:maxlength(3)}")]
[OverrideAuthorization]
public ActionResult GetElectronics(string categoryId)
{
ViewBag.categoryId= t;
return View();
}
Here we have applied the Authorize filter to the controller and then have selectively overridden it for the GetElectronics action method.
As filters are of four types as:
- ActionFilter
- AuthenticationFilter
- AuthorizationFilter
- Exception Filter
So we can have four Filter Overrides corresponding to these
- OverrideActionFiltersAttribute
- OverrideAuthenticationAttribute
- OverrideAuthorizationAttribute
- OverrideExceptionAttribute
All of the above Attributes implements the IOverrideFilter interface.Infact this is how the MVC framework determines whether to exclude any filter type for an action method or controller.
I feel this is one feature that will be useful in many different scenario's.
ASP.NET Membership System
Prior to ASP.NET MVC 5 ASP.NET Membership was the common way to handle the authentication. What this meant was that the task of authenticating and managing the user credentials was handled by ASP.NET automatically. Using ASP.NET membership the user credentials were stored in the database typically relational database such as SQL Server.
But with advances in the technology user’s today are connected with each other using social networks and using portable devices. So the ASP.NET membership system which expected the user credentials to be stored in the local database that needed to be overhauled.This much needed change is provided by the new membership system in ASP.NET which is called ASP.NET Identity.
ASP.NET IDENTITY
Some of the main features of ASP.NET Identity are
- It can be used by any ASP.NET framework such as ASP.NET MVC and WebForms.
- We can easily add third party party authentication providers like google , facebook
- We have control of the persistence storage.So we can now store the credentials not only in
- the SQL Server database but can also use other persistence storages like Azure and NoSQL databases.
Using third party authentication providers the task of authenticating the users can be delegated to a third party site such as google. There are numerous sites that supports openID protocol such as google. With MVC 5 we can use it as part of a newly created project
Let's see how we can create an MVC project that using ASP.NET Identity to authenticate a user using a social site such as google.
When we select create a new project option in visual studio first thing we notice is that there is only single template to create ASP.NET options instead of multiple templates for ASP.NET WebForms , MVC and other ASP.NET frameworks. This common window is part of newly introduced One ASP.NET which means that services like scaffolding are available to all the ASP.NET frameworks like WebForms and MVC.
On selecting the ASP.NET web application template option a new window opens.It has options to select and customize different frameworks like MVC and Web Forms and to chose the Authentication system.
Run the application in the home page when you click the login link on the right corner you will navigate to the login page. Notice that there is option here to use another service to login.
We can enable to use another service by going to the ConfigureAuth method in Startup.Auth file and un-commenting the last line.
Now if we run the application and go to the login page we can see the below page.
On clicking Google button we are redirected to the following screen where user name and password can be entered.
The google authentication is enabled since we used the UseGoogleAuthentication() method. Similarly we can use the authentication methods for Microsoft and other social sites. So using ASP.NET Identity it's just a matter of making a method call to use third party authentication.
Generating code using Scaffolding
Scaffolding means generating code automatically from the model.Suppose we have some model for which we want to generate the skeleton code for the basic Create Read Update and Delete operations then instead writing the common code we can use Scaffolding feature of MVC 5.
There is a code generator for MVC application that can automatically generate code from the model. We have ElectronicItems class that we can use to automatically generate the controller code and view. The advantage of using Scaffolding is that we can very easily and quickly generate code using a model.
public class ElectronicItems
{
public string Name { get; set; }
public string Description { get; set; }
public int Id { get; set; }
}
For using scaffolding right click a item in a project and select “New Scaffolded Item”.
Select the “MVC 5 Controller..” option from the dialog box that opens.
Enter the Controller name and select the model for which to generate the controller for.Click on Add and we will have the controller and view generated for us.
As you can see the following Controller is Generated containing the basic C.R.U.D operations that you had to write manually in the previous versions.
So you might have felt how scaffolding can reduce the amount of code that you had to write manually in the earlier versions of MVC.
So these are some of the new features introduced in MVC 5.I am sure they will make your life easier as a developer.
For common C# questions you will find the following helpful:C# Common Questions