MVC executes custom views with extension methods, instead of UIHint

Source: Internet
Author: User

The project uses Bootstrap, so you don't have to write too much CSS, save a lot of things.
But this business system needs a lot of input, each table has more than 100 fields, each page requires a large number of forms.
It is also a headache to write these forms out in bootstrap format.
I think of the template, EditorTemplates UIHint, but UIHint need to use Metadata annotation, one of the addition, is also unrealistic.
There is another way out, that is to extend the htmlhelper.
To use HtmlHelper, we may have thought of Tagbuilder, Tagbuilder basically all hard code, not convenient to adjust the display format.

In the end I used another way:
In the HtmlHelper extension, the views are taken from the defined view, which can be changed at any time without adding UIHint to each field.

1  Public StaticMvchtmlstring Editorblockafor<tmodel, Tproperty> ( ThisHtmlhelper<tmodel> Helper,stringTemplate, Expression<func<tmodel, tproperty>> property,BOOLWithlabel,stringContainerclass ="col-xs-4",ObjectHtmlattributes =NULL) {2 3     varBODY =(memberexpression) property. Body;4     if(BODY = =NULL)5         Throw NewArgumentException ();6 7     varCTX =Helper. ViewContext.Controller.ControllerContext;8     varresult =ViewEngines.Engines.FindPartialView (Helper. ViewContext.Controller.ControllerContext, template);9     if(result.) View! =NULL) {Ten  One         varmetadata =Modelmetadata.fromlambdaexpression (property, helper.) ViewData); A         //var model = metadata. Model; -  -         varAttrs =htmlhelper.anonymousobjecttohtmlattributes (htmlattributes); the  -         using(varwriter =NewStringWriter (CultureInfo.CurrentCulture)) { -             varVctx =NewViewContext (CTX, result.) View, Helper. ViewData, Helper. Viewcontext.tempdata, writer); -Vctx. Viewbag.propertyname =string. Join (".", body. ToString (). Split (New Char[] {'.'}). Skip (1));//body. Member.name; +  -Vctx. Viewbag.containerclass =Containerclass; +Vctx. viewbag.isrequired =metadata. isrequired; AVctx. Viewbag.htmlattributes =attrs; atVctx. Viewbag.withlabel =Withlabel; -  -Vctx. Viewbag.displayname = metadata. DisplayName??metadata. PropertyName; -  - result. View.render (Vctx, writer); -  in             returnMvchtmlstring.create (writer. ToString ()); -         } to}Else { +         Throw NewInvalidOperationException (string. Format ("particle View {0} not found", template)); -     } the}

This is the core, and the other extensions call this method, such as:

1  Public StaticMvchtmlstring Textblockfor<tmodel, Tproperty> ( ThisHtmlhelper<tmodel> Helper, Expression<func<tmodel, Tproperty>> property,stringContainerclass ="col-lg-4 col-md-4 col-xs-4",ObjectHtmlattributes =NULL,BOOLWithlabel =true) {2     returnEditorblockafor (Helper,"TextBlock", property, Withlabel, Containerclass, htmlattributes);3}

In Editorblockafor this method, there is a sentence:
var result = ViewEngines.Engines.FindPartialView (helper. ViewContext.Controller.ControllerContext, template);
This is to find the specified custom view, which is the key to the whole idea.

Custom View textblock.cshtml

@model Object@{     This. Layout =NULL; stringPropertyexpression =Viewbag.propertyname; stringContainerclass =Viewbag.containerclass; RouteValueDictionary htmlattributes=Sharedtemplateshelper.margeclass (VIEWBAG);}<divclass="@containerClass">@SharedTemplatesHelper. Label (ViewBag) @Html. TextBox (Propertyexpression,NULL, Htmlattributes)</div>

Note that the model is object because the type of the model is not determined.

This file needs to be put under Shared, this is a simple structure.

Call:
@Html. textblockfor (M = m.vesselinfo.vessel_name_cn, "Col-lg-2 col-md-2")
It will eventually generate a piece of HTML:

<Divclass= "Col-lg-2 col-md-2">            <spanclass= "Help-block">Chinese name<spanclass= "Red">*</span></span>    <inputclass= "Form-control input-sm"Data-val= "true"Data-val-length= "The field Chinese name must is a string with a maximum length of."Data-val-length-max= "$"data-val-required= "The Chinese name field is required."ID= "VESSELINFO_VESSEL_NAME_CN"name= "VESSELINFO.VESSEL_NAME_CN"type= "text"value="" /></Div>

Look like this:

--------------divider Line is nonsense and interested to know about my crash experience-------------------

Everything was as it was supposed to be, until ....
One day, the colleague said clearly is Required, why did not perform the verification?
I simply looked at it because there was no validation attribute that generated data-xxx. Look at the Action, that is, Return View (); Model to view is not passed.
Declares a model to be passed to the view (return view (XXX);) After that everything is normal.
When I do MVC3, I do not give the Model will output the validation properties, then rush time, did not go deep into why, still think of the new features of MVC 5.

National Day over 7 days pig life, the project also carried out 7788, finally have time to look back.
The latest source of MVC:
Http://aspnetwebstack.codeplex.com/SourceControl/latest
The version number is 5.2.3.0, we use the 5.2.0.0 in the project, the difference is not big.

A new test project was created,
Compiled an MVC DLL, together with the PDB into the project's reference directory, changed the MVC configuration, reference, inputextensions under the breakpoint, but can not break breakpoints.
According to the search on the Internet to debug the MVC source method to do, unfortunately, not a suitable.

Get more than 8 o'clock in the evening, or there is no way to debug into the source. It was a real bust.
We also found a post for the PDB symbol server:
Http://weblogs.asp.net/gunnarpeipman/stepping-into-asp-net-mvc-source-code-with-visual-studio-debugger
But you need to download these symbols, the computer is not shut, go back.

Today according to the instructions of the blog to do, still can not debug into the source code.


Fortunately, I found another article:
Http://blogs.msdn.com/b/micl/archive/2014/06/07/how-to-debug-your-code-with-mvc-fresh-source-code.aspx

before each version of MVC launch, the contribute team always strong name each MVC related assembly by a specified key File 35mssharedlib1024.snk which is located on Tools folder to prevent assembly tamper. But the SNK file, "Get doesn ' t contain private key, that's can only delay signed all assemblies if you compile Di rectly. Unfortunately, Delay signed assembly doesn ' t support debug feature.
A simple translation:
Because we downloaded the MVC source code is signed, the source code provided by the key does not contain the private key, can only be delayed signature. Unfortunately, the delayed answer is not debug.
(I have no experience in this area, do not understand)

According to the blog post, the relevant items are removed from the signature:
System.Web.Helpers
System.Web.Mvc
System.Web.Razor
System.web.WebPages
such as

And then put the System.Web.WebPages under the
The InternalsVisibleTo parameter in AssemblyInfo.cs (under Properties) is replaced with a version number.
[Assembly:internalsvisibleto ("SYSTEM.WEB.MVC")]
[Assembly:internalsvisibleto ("System.Web.Helpers")]

Compile, modify the Web. config for the purpose of the test item, change the version of SYSTEM.WEB.MVC to the compiled version number, delete the original correlation reference, and add the associated DLL that was just compiled
Add breakpoints, run, debug in.

--------------Divider Line-------------------

It's all crap up there.
A turn and found the No. 382 line in ModelMetadata.cs:
Modelmetadata propertymetadata = viewData.ModelMetadata.Properties.Where (p = p.propertyname = = expression). FirstOrDefault ();
The result of PropertyMetadata is null if the property is not matched.
The attribute is clearly there, it is the Metadata without attributes.

When the viewdata.modelmetadata is quickly monitored, the value is there again, indicating that the problem is on this viewdata.modelmetadata.

In ViewDataDictionary.cs, the definition is viewdatadictionary, line 82nd,
if (_modelmetadata = = NULL && _model! = null)
_model is undoubtedly the model to be uploaded into the view.
When _modelmetadata = null and _model is not NULL, the metadata of the model is taken, which explains why the validation attribute is output when the mode is passed to the view.
When the Model is not passed to the view, it returns NULL.

Enter ViewDataDictionaryOfModel.cs
Defined as viewdatadictionary<tmodel>, inherited from Viewdatadictionary
In line 35th, take the modelmetadata of the parent class, because the return is null and go to the model type to fetch Metadata.

Next to the custom view above, textblock.cshtml
@model Object
...
...

The specified model type is object, because it is shared and is not sure of the exact type of the model, so I used the object.
Okay, here's the question, which one is the best digger? To fetch Metadata by object is of course not to be taken!

Turned around and drove me to the original point of dealing with this thing.
Think of the rapid monitoring, you can get the desired results, I put the above extension method to add a sentence:

。。。
var vctx = new ViewContext (CTX, result. View, Helper. ViewData, Helper. Viewcontext.tempdata, writer);
Vctx. Viewdata.modelmetadata = Helper. viewdata.modelmetadata;//////must, adjusted for a long time, positioning the problem on this modelmetadata
。。。

Run, pass!

MVC executes custom views with extension methods, instead of UIHint

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.