Continuing with my previous example, we will try to customize how the default Razor View Engine works. I request that you go through my previous article if you haven't, here is the link:
How Razor Engine Works With Views in MVC 4
Whenever a request comes for a specific view the Razor Engine tries to find the view in the specific locations. For example let's say the controller name is "SimpleController" and the action name is “Index” then the Razor Engine will try to find the view in the following locations.
~/views/Simple/Index.cshtml
~/views/Simple/Index.vbhtml
~/views/Shared/Index.cshtml
~/views/Shared/Index.vbhtml
If you have created an area in your application then a search will be done in the following locations also:
~/Areas/AreaName/Views/Simple/Index.cshtml
~/Areas/AreaName/Views/Simple/Index.vbhmtl
~/Areas/AreaName/Views/Shared/Index.cshtml
~/Areas/AreaName/Views/Shared/Index.vbhtml
NOTE: The Razor View Engine will search for both of the pages/views, in other words it will search for the view with a .cshtml extension, .vbhtml extension as well as with .aspx and .ascx extension.
The conventions that the Razor View Engine follows are the following:
1. For searching views, weforms, master pages or partial views or user controls:
~/Views/{1}/{0}.cshtml
~/Views/{1}/{0}.vbhtml
~/Views/Shared/{0}.cshtml
~/Views/Shared/{0}.vbhtml
2. For searching views, weforms, master pages or partial views or user controls inside the area:
~/Areas/{2}/Views/{1}/{0}.cshtml
~/Areas/{2}/Views /{1}/{0}.vbhmtl
~/Areas/{2}/Views /Shared/{0}.cshtml
~/Areas/{2}/Views /Shared/{0}.vbhtml
NOTE: The notations used as {0}, {1} and {2} are basically like a placeholder; each one will hold a value at runtime.
{0} is for holding view name
{1} is for holding controller name
{2} is for holding area name
This is the default way to search for a specific view whenever a request arises from the user. You can however customize how the Razor Engine works by creating your own view engine. For creation of a new view engine your class needs to derive from the “RazorViewEngine” class or you can also implement the “IView” interface.
Let's move on to the example. I'm adding a new folder to my application with the name “Concrete” and inside that I'm adding a class with “CustomizeViewEngine.cs”.
By using this class we'll try to customize how views are searched by the Razor Engine. We've added a “special” folder inside the views folder and also added a view with the name “Special” that will be called whenever a request comes for that view.
Here is the code snippet for the Special View:
- @using ViewsInDepth.Models
- @model IEnumerable<Employee>
- @{
- ViewBag.Title = "Special";
- }
- <h2>
- Special</h2>
- <table>
- <thead>
- <tr>
- <td>
- Emp ID
- </td>
- <td>
- Name
- </td>
- </tr>
- </thead>
- <tbody>
- @foreach (var emp in Model)
- {
- <tr>
- <td>
- @emp.EID
- </td>
- <td>
- @emp.EName
- </td>
- </tr>
- }
- </tbody>
- </table>
Create a new action method inside the Home Controller with the name Special. Here is the code snippet:
- public ActionResult Special()
- {
- return View(lstEmployees);
- }
Here is the code snippet for the CustomizeViewEngine.cs file:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
-
- namespace ViewsInDepth.Concrete
- {
- public class CustomizeViewEngine : RazorViewEngine
- {
- public CustomizeViewEngine()
- {
-
- ViewLocationFormats = new string[] { "~/Views/{1}/{0}.cshtml", "~/Views/special/{0}.cshtml" };
- }
- }
- }
Once our customize view engine is ready we can make use of it, we just need to register it with our application. For doing this we need to make an entry in the global.asax file.
The following are the entries:
-
- ViewEngines.Engines.Clear();
-
- ViewEngines.Engines.Add(new CustomizeViewEngine());
It is now time to test the application by running it. Enter the URL /Home/Special and you'll find that your view is displayed from the special folder inside the views. Now the views inside the shared folders are not considered.