ASP. net mvc: implement our own view Engine

Source: Internet
Author: User

In MvcContrib, an open-source project of ASP. net mvc, several view engines are provided for us, such as NVelocity, Brail, NHaml, and XSLT. So what should we do if we want to implement our own view engine in ASP. net mvc?

We know that the rendering view is implemented in the Controller by passing the view name and data to the RenderView () method. Okay, let's start from here. Let's take a look at the source code of ASP. net mvc and see how the RenderView () method is implemented:

Reference content is as follows:

Protected virtual void RenderView (string viewName, string
MasterName, object viewData ){
ViewContext viewContext = new ViewContext (
ControllerContext, viewName, masterName, viewData, TempData );
ViewEngine. RenderView (viewContext );
}//

This is the source code of P2. P3 is slightly different and the principle is similar. From the code above, we can see that the RenderView () method in Controller mainly involves ControllerContext, viewName, masterName, viewData, tempData is encapsulated into ViewContext and passed to ViewEngine. renderView (viewContext ). Well, that's right. Here we want to implement the RenderView () method of ViewEngine.

ASP. net mvc provides a default view engine called WebFormsViewEngine. we can see from the name that this view engine uses ASP. NET web forms. Here, the template used by the view engine is implemented using HTML files. The simple template sample code is as follows:

Reference content is as follows:

<! DOCTYPE html PUBLIC "-// W3C // dtd xhtml 1.0 Transitional // EN"
Http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>
<Html xmlns = "" http://www.w3.org/1999/xhtml "">
Http://www.w3.org/1999/xhtml>
<Head>
<Title> Custom view engine example </title>
</Head>
<Body>
<H1 >{$ ViewData. Title} <P >{$ ViewData. Message} </p>
<P> The following fruit is part of a string array: {$ ViewData. FruitStrings [1]} </p>
<P> The following fruit is part of an object array: {$ ViewData. FruitObjects [1]. Name} </p>
<P> Here's an undefined variable: {$ UNDEFINED} </p>
</Body>
<Ml>

 
Next we will start our implementation. First of all, there is no doubt that we need to create a ViewEngine and name it SimpleViewEngine. Note that ViewEngine must implement the IViewEngine interface:

Reference content is as follows:

Public class SimpleViewEngine: IViewEngine
{
# Region Private members

IViewLocator _ viewLocator = null;

# Endregion

# Region IViewEngine Members: RenderView ()

Public void RenderView (ViewContext viewContext)
{
String viewLocation = ViewLocator. GetViewLocation
(ViewContext, viewContext. ViewName );
If (string. IsNullOrEmpty (viewLocation ))
{
Throw new InvalidOperationException (string. Format
("View {0} cocould not be found.", viewContext. ViewName ));
}

String viewPath = viewContext. HttpContext. Request. MapPath (viewLocation );
String viewTemplate = File. ReadAllText (viewPath );

// Template Parsing is as follows
IRenderer renderer = new PrintRenderer ();
ViewTemplate = renderer. Render (viewTemplate, viewContext );

ViewContext. HttpContext. Response. Write (viewTemplate );
}

# Endregion

# Region Public properties: ViewLocator

Public IViewLocator ViewLocator
{
Get
{
If (this. _ viewLocator = null)
{
This. _ viewLocator = new SimpleViewLocator ();
}
Return this. _ viewLocator;
}
Set
{
This. _ viewLocator = value;
}
}

# Endregion
}

The RenderView () method provided by the IViewEngine interface is implemented here, and a ViewLocator attribute is provided here. ViewLocator is mainly used to locate the view based on the view name in the controller. In the RenderView () method, first obtain the view path, then read the view template, and finally parse the template and output it.

Let's take a look at how ViewLocator is implemented. It is of the IViewLocator type, that is, SimpleViewLocator implements the IViewLocator interface. The implementation code of SimpleViewLocator is as follows:

 


      public class SimpleViewLocator : ViewLocator            {            public SimpleViewLocator()            {            base.ViewLocationFormats = new string[] { "~ iews/{1}/{0}.htm",            "~ iews/{1}/{0}.html",            "~ iews d/{0}.htm",            "~ iews d/{0}.html"            };            base.MasterLocationFormats = new string[] { "" };            }            }

SimpleViewLocator inherits from the ViewLocator class of ASP. net mvc, while ViewLocator implements the IViewLocator interface. Because ViewLocator has completed all the work, we only need to modify its ViewLocationFormats to use our own template file.

Let's take a look at the class diagram, which makes it clearer:

 


Note: Some code about template parsing will not be mentioned here. If you are not in the scope of the discussion, you can download the code by yourself. Now we have basically completed our view engine. How can we prevent ASP. net mvc from using the default web forms view engine, but using our custom view engine? In ASP. net mvc, all requests use a factory class to create a Controller instance. This factory class must implement the IControllerFactory interface. The default factory class implementing this interface is DefaultControllerFactory. This factory class is the entry point for modifying the default view engine as our view engine. For convenience, we create a SimpleControllerFactory inherited from DefaultControllerFactory:

 


      Public class SimpleControllerFactory: DefaultControllerFactory {protected override IController CreateController (RequestContext requestContext, string controllerName) {Controller controller Controller = (Controller) base. createController (requestContext, controllerName); controller. viewEngine = new SimpleViewEngine (); // modify the default view engine to return controller for the view engine we just created ;}}

Here, you only need to modify controller. ViewEngine as our custom ViewEngine. The final class diagram is as follows:

 



To make the Controller factory class SimpleControllerFactory we created become the default controller factory class, we must add the following in the Application_Start event in Global. asax. cs:

Code: ControllerBuilder. Current. SetControllerFactory (typeof (SimpleControllerFactory); here, we have completed our own view engine. It is very easy to implement a custom view engine in ASP. net mvc. The difficulty lies in template parsing. For details, you can study the code of the four view engines in MvcContrib. I am going to study the template engine recently. You may have any other excellent, mature, and open-source template engine. I 'd like to recommend it to my younger brother. Thank you first.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.