Model metadata and Model template of ASP. net mvc: Template acquisition and execution policies

Source: Internet
Author: User
Tags static class

When we call the HtmlHelper or HtmlHelper <TModel> Template method to present a data member of the entire Model or Model in a certain mode (Display mode or edit mode, you can find the corresponding template by creating a ModelMetadata object that represents the Model metadata. If the template corresponds to a custom segment View, you only need to execute the View. For the default template, you can directly obtain the corresponding HTML. This article focuses on the template acquisition and execution mechanism, but before that, let's take a look at the relationship between DataTypeAttribute and the template. [This article has been synchronized to How ASP. net mvc Works? Medium]

1. What is the relationship between DataTypeAttribute and template?

Through introduction to the definition of Model metadata in Model metadata, we know that the data type set for the target element through the DataTypeAttribute feature will eventually be reflected in the DataTypeName attribute of the ModelMetadata object that represents the Model metadata. In addition, for some set data types, such as Date, Time, Duration, and Currency, a DisplayFormatAttribute will be created and applied to ModelMetadata. How does the DataTypeName attribute of ModelMetadata affect the final presentation of the target element?

In fact, during Template matching, the DataTypeName attribute of ModelMetadata is treated as the template name. Therefore, the following two forms of Model type definition can be considered as equivalent. The only difference between the template name set through the UIHintAttribute feature and the data type set through the DataTypeAttribute feature is that the former has a higher priority. In other words, if you apply both UIHintAttribute and DataTypeAttribute to the same data member, set the template name and data type to ABC and 123 respectively, custom template 123 is used only when the template ABC does not exist.

The code is as follows: Copy code

Public class Model

 {

[DataType (DataType. Html)]

Public string Foo {get; set ;}

  

[DataType (DataType. MultilineText)]

Public string Bar {get; set ;}

  

[DataType (DataType. Url)]

Public string Baz {get; set ;}

 }

 

Public class Model

  {

[UIHint ("Html")]

Public string Foo {get; set ;}

 

[UIHint ("MultilineText")]

Public string Bar {get; set ;}

 

[UIHint ("Url")]

Public string Baz {get; set ;}

 }

 

Example: verify the equivalence between DataTypeName and Template name

To demonstrate how to set the data type through the DataTypeAttribute feature, the data type is considered as the template name during the visualization of the target element, a simple example is provided. In this example, we define A data type Triangle that represents A Triangle. Its attributes A, B, and C are A Point object that represents the coordinates of the three corners.

The code is as follows: Copy code

Public class Triangle

 {

[DataType ("PointInfo")]

Public Point A {get; set ;}

 

[DataType ("PointInfo")]
Public Point B {get; set ;}

 

[DataType ("PointInfo")]

Public Point C {get; set ;}

 }

 

[TypeConverter (typeof (PointTypeConverter)]

Public class Point

 {

Public double X {get; set ;}

Public double Y {get; set ;}
Public Point (double x, double y)

    {

This. X = x;

This. Y = y;
    }

 

Public static Point Parse (string point)

     {

String [] split = point. Split (',');

If (split. Length! = 2)

        {

Throw new FormatException ("Invalid point expression .");

         }

Double x;
Double y;
If (! Double. TryParse (split [0], out x) |! Double. TryParse (split [1], out y ))

         {

Throw new FormatException ("Invalid point expression .");

         }

Return new Point (x, y );

     }

 }
 
Public class PointTypeConverter: TypeConverter

 {
Public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)

     {

Return sourceType = typeof (string );
    }
 

Public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)

     {

If (value is string)

         {

Return Point. Parse (value as string );

         }

Return base. ConvertFrom (context, culture, value );

     }

 }

 

For the definitions of Triangle and Point, there are two points worth noting: first, the DataTypeAttribute feature is applied to the three attributes A, B, and C of the Triangle, and the custom data type is set to PointInfo (not Point). Second, the TypeConverterAttribute feature is applied to the Point type and the TypeConverter type is set to PointTypeConverter. The latter supports conversion of the source string type. With the introduction of the Complex Type, the three attributes of the Triangle are converted from the Complex Type member to the simple Type member. Based on the convenient rules of the Object template on data members described in the premise, the three attributes of Triangle can be finally presented.

Now we create a strong-type branch View with the Model type of Point as the template, and name it PointInfo (consistent with the custom data type specified by the DataTypeAttribute feature ). We only define a display mode template for Point, so we put the View file of this segment in ViewsSharedDisplayTemplates. The following code snippet shows a Point object in the form of (X, Y.

The code is as follows: Copy code

@ Model MvcApp. Models. Point

(@ Model. X, @ Model. Y)

 

Now we create a default HomeCtroller. As shown in the following code snippet, a Triangle object is created in the default Index operation method to present it in the default View.

 

The code is as follows: Copy code

Public class HomeController: Controller

 {

Public ActionResult Index ()

     {

Triangle triangle = new Triangle

        {
A = new Point (1, 2 ),

B = new Point (2, 3 ),

C = new Point (3, 4)

};

Return View (triangle );
     }

 }

 

The following is the definition of the corresponding View. This is a strong View with the Model type of Triangle, we only call the DisplayModel method of HtmlHelper <TModel> to render the Model as a Triangle object in display mode.

The code is as follows: Copy code

1: @ model MvcApp. Models. Triangle

2: @ Html. DisplayForModel ()

 

Running the Web application will display the effect shown in the following figure in the browser, we can see that the coordinates of the three corners represented by the, B, and C attributes of the Triangle object we created are completely presented in the PointInfo template we defined.

 

II. Template acquisition and execution

When we call the HtmlHelper or HtmlHelper <TModel> Template method to present a data member of the entire Model or Model in a certain mode (Display mode or edit mode, you can find the corresponding template by creating a ModelMetadata object that represents the Model metadata. If the template corresponds to a custom segment View, you only need to execute the View. For the default template, you can directly obtain the corresponding HTML.

Parsing the target template based on the Model metadata is the core part of the template method execution process and is also the focus of this article. Let's take the extension method DisplayFor HtmlHelper <TModel> as an example to see how the Model object obtained through expression is displayed in display mode.

The code is as follows: Copy code

Public static class DisplayExtensions
{

Public static MvcHtmlString DisplayFor <TModel, TValue> (this HtmlHelper <TModel> html, Expression <Func <TModel, TValue> expression, string templateName );
}

 

When DisplayFor is called, if the Model expression represented by expression is used to obtain an attribute, the attribute name will be obtained. Then execute the expression to get an object as Model. This object, together with the attribute name (if any), is used to represent the Metadatadata object of the Model metadata. Based on the Metadatadata object, you can obtain a list of View names that represent the partial template. These View names are sorted by priority as follows:

The name of the template passed in as the templateName parameter (if not empty ).

The TemplateHint attribute value of Metadatadata (if not empty ).

The DataTypeName attribute value of Metadatadata (if not empty ).

If the actual type of the Model object is non-null, the type name is used as the template View Name; otherwise, the Underlying (Underlying) type name is used as the template View name (for example, for int? Type, Int32 is used as the template View name ).

If the actual type of the Model object is non-complex, the String template is used (because the non-complex type can be converted to the String type, it can be converted to the String type for rendering ).

If the declared type of the Model is an interface, if the interface inherits from IEnuerable, the Collection template is used.

When the declared type of the Model is interface, the Object template is used.

If the Model declaration type is not an interface type, you can trace the Object type based on its type inheritance relationship and use the type name as the template View name one by one. If the declared type implements the IEnuerable interface, replace the final Object with Collection.

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.