As the title suggest,
in this article we will learn bit of performance improvement by attaching right
view engine in MVC and then we will learn to extend the existing Razor view
engine and the implementation of our own view engine.
So, let’s start with
the view engine tuning part at first. We know that ActionResult is the super
class of all result type of action and ViewResult is one of them. If we want to
return a View we can either explicitly specify the view name or may not
mention. Now, view execution process is
handle by view engine which performs in last part of MVC pipeline.
At first it decides
that whether the return result is ViewResult type or not and if the result is ViewResult
type then it view Engine’s responsibility to invoke the appropriate view. Generally,
MVC framework uses two view engines by default, those are Web Form view engine
and Razor view engine and MVC framework searches for Web Form view engine at
first, if not present then Razor view engine. So, in theory, whenever MVC framework wants to
invoke a view, if search for Web Form view engine at first then search for
Razor view engine, even if we use only Razor view engine in application. So,
let’s see in action.
Here is the controller which
contains Index() action and we are trying to return Test view which is not
available in application.
public class TestController : Controller
{
public ActionResult Index()
{
return View("Test");
}
}
Obviously we should see the below screen, because we don’t
have the view at all. If we check the search step closely then we will see that
MVC framework is searching .aspx page at first then .cshtml and all, so the Web
Form view is performing at first then Razor view.
As we said earlier, this will slow down the view execution process,
ok. Let’s solve the problem. We know that MVC is highly customize and configurable.
Now, we will detach Web Form view engine from MVC pipeline and we will attach only
Razor view Engine then the framework will not search for Web Form view in time
of execution.
The process is very simple ,just open Global.asax page of
application and modify code accordingly.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
//Remove all view engine
ViewEngines.Engines.Clear();
//Add Razor view Engine
ViewEngines.Engines.Add(new RazorViewEngine());
Bootstrapper.Initialise();
}
}
Here we are clearing all view engines from MVC pipeline and
then we are registering only Razor view engine. Now, if we run the same
application, we will find below output and we are seeing that now MVC framework
is not searching for .aspx page.
Customize the Razor
view Engine
Now, there is another small problem in application. We are
seeing that Razor view engine is searching both for vbhtml and cshtml page.
Now, it’s very much common in application that you might use single programming
language in View , either C# or VB. So, here we can again customize the existing
Razor view engine to let it search only for cshtml page or vbhtml page.
So, just create one class and inherit it from
RazorViewEngine class. Here is the example implementation.
public class CSharpRazorViewEngine : RazorViewEngine
{
public CSharpRazorViewEngine()
{
AreaViewLocationFormats = new[]
{
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml"
};
AreaMasterLocationFormats = new[]
{
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml"
};
AreaPartialViewLocationFormats =
new[]
{
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml"
};
ViewLocationFormats = new[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml"
};
MasterLocationFormats = new[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml"
};
PartialViewLocationFormats = new[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml"
};
}
}
Now, we have to register the view engine in MVC pipeline. Just modify the Global.asax file accordingly.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
//Remove all view engine
ViewEngines.Engines.Clear();
//Add Custom view Engine Derived from Razor
ViewEngines.Engines.Add(new CSharpRazorViewEngine());
Bootstrapper.Initialise();
}
}
Now, if we run the application, we will see that the custom
view Engine is searching for .cshtml page only.
Fine, we have learned to customize the view engine to
improve performance of MVC application. Now, we will build our own view engine and
we will use the engine in place of existing Web Form view or Razor view.
Implement custom view
engine
To implement our own view engine, we have to implement
IViewEngine in our own class. The IViewEngine contains three methods.
FindPartialView: This method will search for partial view if
there is any partial view call in main view.
FindView : This method will search for main view.
ReleaseView: After execution of view, we can implement
disposing activity of our custom view class.
Here, I have implemented IViewEngine interface in “MyViewEngine”
class. Have a look on below code.
public class MyViewEngine : IViewEngine
{
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
throw new NotImplementedException();
}
public ViewEngineResult FindView(ControllerContext controllerContext,
string viewName, string masterName, bool useCache)
{
if (viewName.Contains("myView"))
{
return new ViewEngineResult(new myCustomView(),this);
}
else
return new ViewEngineResult(new string[] {"No View found, please provide correct name"});
}
public void ReleaseView(ControllerContext controllerContext, IView view)
{
}
}
So, we have built our own view engine, now we have to build
our own view. To build our own view, we have to implement IView interface in
our own class. In this example I have implemented IView interface in myCustomView
class.
The IView contains one and only one method called Render
where we can implement the rendering mechanism. In this example, we are just printing string.
public class myCustomView : IView
{
public void Render(ViewContext viewContext, System.IO.TextWriter writer)
{
writer.Write("Data
from custom view");
}
}
Register the custom
view
This is one obvious process need to follow. We have to
register the custom view in MVC pipeline. Just modify the Global.asax page
accordingly.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
//Remove all view engine
ViewEngines.Engines.Clear();
//Attach custom view in pipeline
ViewEngines.Engines.Add(new MyViewEngine());
Bootstrapper.Initialise();
}
Now, we will implement controller and we will call our custom
view, Here I have specify the action name as myView.
public class TestController : Controller
{
public ActionResult myView()
{
return View();
}
}
And once we run the application and try to hit myView()
action, we will see that the custom string has appear in screen.
Border Line
In this example we have learned to configure view engine in
MVC application and also learned to implement custom view engine, hope this
article will give you better understanding of view execution process in MVC
application.
great
ReplyDelete