View engine and view
In most cases the controller action method returns the Viewresult object, and the MVC built-in action Invoker Controlleractioninvoker is responsible for invoking the controller action method and invoking the view engine to process the viewresut. The Viewresult is converted by the view engine to a Viewengineresult object, and the Viewengineresult object contains the view object that implements the IView interface, and the resulting MVC framework invokes the Render method of the View object to render the output. Here is an example to illustrate the process, first look at the relevant interface and class definition and implementation:
Public interface Iviewengine {viewengineresult Findpartialview (controllercontext controllercontext, string Partialviewname, bool UseCache); Viewengineresult Findview (ControllerContext controllercontext, String viewName, String mastername, bool usecache); void Releaseview (ControllerContext controllercontext, IView view); } public interface IView {void Render (ViewContext viewcontext, TextWriter writer), and public class Viewengineresult { Public Viewengineresult (ienumerable<string> searchedlocations) {if (searchedlocations = = null) {throw NE W ArgumentNullException ("Searchedlocations"); } searchedlocations = Searchedlocations; } public Viewengineresult (IView view, Iviewengine viewengine) {if (view = = null) {throw new ArgumentNullException ( "View");} if (Viewengine = = null) {throw new ArgumentNullException ("Viewengine");} view = view; Viewengine = Viewengine; } public ienumerable<string> searchedlocations {get; private seT Public IView View {get; private set;} Public Iviewengine Viewengine {get; private set;}}
Iviewengine's two Find method finds the requested view return Viewengineresult object, Viewengineresult has two functions, one accepts iview and iviewengine as arguments, The other passed in a series of view file search path lists as parameters.
Start with the custom view class first:
public class Debugdataview:iview {public void Render (ViewContext viewcontext, TextWriter writer) { write (write R, "---Routing Data---"); foreach (string key in ViewContext.RouteData.Values.Keys) { Write (writer, "key: {0}, Value: {1}", key, Viewcontext.routedata.values[key]); } Write (writer, "---View Data---"); foreach (string key in ViewContext.ViewData.Keys) { Write (writer, "key: {0}, Value: {1}", Key, Viewcontext.viewdata[key]); } } private void Write (TextWriter writer, string template, params object[] values) { writer. Write (String. Format (template, values) + "<p/>"); } }
Debugdataview simply outputs some path mappings and view data. Next is the custom view engine:
public class Debugdataviewengine:iviewengine {public viewengineresult Findview (controllercontext ControllerContext, String viewName, String mastername, bool UseCache) { if (ViewName = = "Debugdata") { return new Viewengineresult (New Debugdataview (), this); } else { return new Viewengineresult (new string[] {"No view (Debug Data view Engine)"}) Public Viewengineresult Findpartialview (controllercontext controllercontext,string partialviewname, bool UseCache) { return new Viewengineresult (new string[] {"No view (Debug Data view Engine)"}); public void Releaseview (ControllerContext controllercontext, IView view) { //Does nothing } }
The main thing in Debugdataviewengine is the Findview method, if the current request is a debugdata view, we create a debugdataview directly and build Viewengineresult back with it, In other cases, a viewengineresult with a false search path is returned (real implementation we need to search for template files, etc.). To use the custom view engine we also need to register in App_start:
In an app that can register multiple view engines, the action caller invokes the Findview method of these view engines in turn, and once a search engine returns a viewengineresult result call that contains the IView object, the order of the view engine registration is affected, There may be two view engines that can handle the same view name. If we want to customize the view engine precedence, you can insert it first in the list:
ViewEngines.Engines.Insert (0, New Debugdataviewengine ());
If an action method returns a Debugdata view, such as:
Return View ("Debugdata");
The final result is to invoke the Debugdataview.renderdata output. If we request a view that is not implemented, the results are:
The search path for a series of view templates is displayed incorrectly, including the false path "No View (Debug Data view Engine)" given by Debugdataviewengine. Some of the other paths in the results come from the default razor and ASPX view engines, and you can call ViewEngines.Engines.Clear () to clear the default view engine only after registering the custom view engine.
A simple summary of the above example can be said that the view engine completes the conversion from the view name to the View object, while the view object is responsible for the specific output response.
Razor View Engine
In rare cases where we need to customize the view engine, MVC has provided us with the razor and ASPX engines, Razor introduced in MVC3 to replace the ASPX engine, so the razor engine is recommended. The razor engine handles the. cshtml view file, a simple index.cshtml:
Layout = null; Viewbag.title = "Index"; A list of fruit names: @foreach (string name in Model) {<span><b> @name </b></span>}
After launching the application, the Razor engine converts the cshtml file to the definition of the C # class, which we can C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary in the ASP. NET Files\ Root to find these temporary files, such as the above index.cshtml into C #. cs file It is possible that:
It extends from webviewpage<t>, T is the view data model type, above example string[]. Understanding how Razor handles cshtml can help us understand how HTML helper functions work in the future.
When we request a view such as index, the razor engine follows the Convention rules to find the view file in the following path:
• ~/views/home/index.cshtml ~/views/home/index.vbhtml ~/views/shared/index.cshtml ~/Views/ Shared/index.vbhtml
In fact, Razor is not really searching for these disk files because these templates have been compiled into C # classes. The following properties of Razorviewengine are related to template search:
Property |
|
Default value |
Viewlocationformats Masterlocationformats Partialviewlocationformats |
Search views, partial views, and layout files |
~/views/{1}/{0}.cshtml, ~/views/{1}/{0}.vbhtml, ~/views/shared/{0}.cshtml, ~/views/shared/{0}.vbhtml |
Areaviewlocationformats Areamasterlocationformats Areapartialviewlocationformats |
Area search views, partial views, and layout files |
~/areas/{2}/views/{1}/{0}.cshtml, ~/areas/{2}/views/{1}/{0}.vbhtml, ~/areas/{2}/views/shared/{0}.cshtml, ~/areas/{2}/views/shared/{0}.vbhtml |
Here {0} represents the view name, {1} represents the controller name, and {2} identifies the region name. We can subclass the Razorviewengine after modifying the above property changes Razor search method, of course, must register the sub-Class View engine to the engine list.
Razor template file
Razor template files are mixed with HTML and C # statements, with an example to specifically analyze:
The first line @model Razor.Models.Product specifies the model object type for the view, and we can use @model to refer to the object in the future (note M capitalization). The model object type is not required, there is no such line in the view file, and a view with model type is called a strongly typed view (strong typed).
The second line starts with "@{" a block of razor code, similar to the code block of C #, and ends with "}".
"Layout = null;" Indicates that the view does not use a layout file, the layout file is stored in the View\layouts directory, and can be shared for multiple view files. The layout file name usually begins with an underscore "_", such as _basiclayout.cshtml, which is not returned to the user at the beginning of the underscore, which helps us to distinguish which support files are. The layout file is actually a razor template file, such as:
<! DOCTYPE html> @RenderBody ()
The most important thing here is the @RenderBody () (which we know later as the HTML helper function), which is the function of inserting the rendered result of the view here. After using the layout file, the view can be simplified to:
In fact, we don't need to specify LAYOUT,MVC in each view file to search for a file named _viewstart.cshtml, whose contents are automatically inserted into all view files, so if we want to specify a layout file for all view files, you can Defined in viewstart.cshtml:
Razor syntax
We can easily insert view model data or ViewData data in the view:
@model Razor.Models.Product @{viewbag.title = "Demoexpression";} <table> <thead> <tr><th> property</th><th>value</th></tr> </thead> <tbody> <tr><td>name </td><td>@Model. Name</td></tr> <tr><td>Price</td><td> @Model.Price </td></tr> <tr><td>stock level</td><td>@ Viewbag.productcount
These values can also be easily applied to the tag properties:
You can use conditional statements:
Note the "@:" Line of "@:out of the Stock", which prevents razor from interpreting subsequent statements as code. Switch above to replace if:
Enumerate data:
We use the full namespace when referencing the data type, and we can introduce the namespaces as a C # using:
Add dynamic content to Razor view
In addition to the static HTML, we can embed dynamic content in the view template, dynamic content output at runtime, such as the above inline @if, @Model, etc., can also embed HTML helper functions, such as the layout file used in the @renderbody (). In addition, we can embed sections (Sections), partial views, and child actions.
- Examples of using sections
@model string[]@{ viewbag.title = "Index";} @section Header { <div class= "View" > @foreach (String str in new [] {"Home", "List", "Edit"}) { @Html. Ac Tionlink (str, str, NULL, new {style = "margin:5px"}) } </div>} @section Body { <div class= "View" ; This was a list of fruit names: @foreach (string name in Model) { <span><b> @name </b></span> ; } </div>} @section Footer { <div class= "View" > This is the Footer </div>}
This defines the header, Body, and footer three sections that we can refer to in the layout file:
<! DOCTYPE html>
Note that @rendersection ("scripts", false) has more than one parameter false, which is used to represent the scripts section optional, and does not require output if the scripts section is not defined in the view. If this is not added here, the error is not found in the Razor prompt section.
- Examples of using partial views
The partial view can be selected in the Add View window "Create as partial view" creation-mypartial.cshtml:
We reference it in another view file:
A partial view can also be strongly typed:
Pass in the appropriate model object when referencing:
- Examples of using child actions
A child action is called a control action method, we first define one such action method:
Note that the childactiononly is used to identify this action method, which means that it is only used for invocation and cannot be accessed as a standard action method. It corresponds to a partial view:
We reference it in the view:
If the child action to be called is not the same controller, we also need to specify its controller:
If the child action has parameters, we can also specify parameters when calling:
The above is a summary of the contents of the fourth edition of the Apress Pro ASP. NET MVC 4, as described in the original http://www.apress.com/9781430242369.
ASP. NET MVC 4 (v) view