This chapter introduces how to use helper in MVC4.
Starting from sample
Prepare controller and Action
public class TestController : Controller { public ActionResult Index() { ViewBag.Fruits = new[] { "Apple", "Orange","Pear" }; ViewBag.Cities = new[] { "New York", "London","Paris" }; string message = "This is an HTML element: "; return View("List",(object)message); } }
Code Description: A TestController is prepared, which includes an Index Action (default Action). Some stringarrays are stored in ViewBag and a string (including htmltag) is returned ).
Prepare View
IndexHere are the fruits:@foreach (string str in (string[])ViewBag.Fruits) {@str }Here are the cities:@foreach (string str in (string[])ViewBag.Cities) {@str }Here is the message:@Model
Code Description: prints two string arrays in Viewbag and sends a message.
Test:
As you can see, the View prints a string array, and the htmltag is recognized as a string.
Next, create an inline helper
Now we want to encapsulate the code in the View that prints the string array, so that we can control this part of the print.
So the implementation is given:
@helper ListArrayItems(string[] items) {foreach(string str in items) {@str }}
During printing, you can call it just like calling the C # function. input the Array in ViewBag:
Here are the fruits:@ListArrayItems(ViewBag.Fruits)Here are the cities:@ListArrayItems(ViewBag.Cities)
The benefits of using helper are obvious, but they are actually the benefits of encapsulation. We can control behavior in a centralized manner. For example, to display the list as a list, we only need to change helper:
@helper ListArrayItems(string[] items) {
@foreach(string str in items) {
- @str
}
}
Test:
Implement ExternalHelper method
If you do not want to write code coding in View and want to write it in C # for management, you can consider implementing an External version:
Step 1: implement a customizehelper
Public static class MyHelpers { public staticMvcHtmlString ListArrayItems(this HtmlHelper html, string[] list) { var tag =new TagBuilder("ul"); foreach(var str in list) { var itemTag = new TagBuilder("li"); itemTag.SetInnerText(str); tag.InnerHtml += itemTag.ToString(); } return new MvcHtmlString(tag.ToString()); }}
As you can see, it is actually an extension of HtmlHelper, receives a stringarray parameter, print
List, which uses TagBuilder and returns MvcHtmlString.
1. comment the previous inline version in the View and apply the implementation of the external version:
@*@helper ListArrayItems(string[] items) {
@foreach(string str in items) {
- @str
}
} *@@using MVCHelperStudy.CustomizeHelper
2. Call
Here are the fruits:@Html.ListArrayItems((string[])ViewBag.Fruits)Here are the cities:@Html.ListArrayItems((string[])ViewBag.Cities)
Common Properties in HtmlHelper:
RouteCollection |
Application-defined route |
ViewBag |
ViewBag uploaded from the called Controller/Action |
ViewContext |
Including request information, Controller, View, etc. |
Common Properties in ViewContext
Controller |
Controller called by the current request |
HelperContext |
Contains the details of the current Request (Request, Reponse, etc) |
IsChildAction |
Whether the call is from ChildAction |
RouteData |
Route information of the current request |
View |
Call the view of the current helper |
Common TagBuilder Functions
InnerHtml |
Set the internal html of the control |
SetInnerText (string) |
Set the text contained in the control |
AddCssClass (string) |
Set the css class of the control. |
MergeAttribute (string, string, bool) |
Set attribute to specify whether to overwrite the old value |
Partial View, Child Action, Helper Method
We have discussed PartialView and ChildAction in the previous chapter. This article also demonstrates the usage of Helper. When can we use it?
In general, Helper will encapsulate more Html. If you want to encapsulate some html display methods, you can consider helper, which generally uses the inline format, I personally think that the helper of the back-end write external version of mvc is poor.
If a request is sent and action is found, and the action is expected to stay in the current view and complete a local refresh (ajaxcall), you can consider partialview as the most suitable scenario, select view only when action receives a request.
If it is more complex, callaction must be set in the view, and the model must be operated. render a view, so childaction is considered. However, generally, partialview is sufficient to cover most scenarios where ajax needs to be applied. If not, for special pages, such as SPA (singlepage application ), so js template + JsonResult is also a good solution.
String Encoding
For the above example, the string returned by the Action contains"", If you want mvc to automatically recognize it as an input box, what should we do?
Prepare a helper
public static MvcHtmlStringDisplayMessage(this HtmlHelper html, string msg) { string result =String.Format("This is the message: {0}
", msg); return new MvcHtmlString(result); }
Unlike the model (string type) that is directly displayed, we construct an MvcHtmlString object with a layer encapsulated and threw it to the mvcframework. This way, it will be recognized as an html output to the browser.
Modify the view
Delete the View code and add the following code:
@model string@using MVCHelperStudy.CustomizeHelper
Index This is the contentfrom the view:
Here is the message:@Model
This is the content from the helper method:
@Html.DisplayMessage(Model)
Code Description: We printed two strings. One is directly @ Model, and the other is to call the new helper (Wrap is the MvcHtmlString object)
Test
We can see that our html string is recognized by mvcframework as the control render on the browser.
Now let's change it. If we want mvcframework to recognize my html string as a string, how can we write the helper statement and simply return the string:
Public static string DisplayMessage(this HtmlHelper html, string msg) {return String.Format("This is the message:{0}
", msg);}
Method 2
When Html. Encode is used, MvcHtmlString is still returned:
Public static MvcHtmlString DisplayEncodeMessage(this HtmlHelper html, string msg) { String encodedMessage = html.Encode(msg); string result = String.Format("This is the message: {0}
", encodedMessage); return new MvcHtmlString(result); }
View:
Remove all code to add this line, @ Html. DisplayEncodeMessage (@ Model)
Test:
Use the built-in helper to construct a form
The Mvc framework provides many built-in html generation methods for us to generate forms.
Starting from an example,
Add the Person class to the Model folder.
public class Person { public int PersonId { get;set; } public string FirstName {get; set; } public string LastName {get; set; } public DateTime BirthDate {get; set; } public Address HomeAddress{ get; set; } public bool IsApproved {get; set; } public Role Role { get;set; } } public class Address { public string Line1 { get;set; } public string Line2 { get;set; } public string City { get;set; } public string PostalCode {get; set; } public string Country {get; set; } } public enum Role { Admin, User, Guest}
There are three classes in total: person, address, and role.
Prepare a Controller and code
public class PersonController : Controller { public ActionResult CreatePerson() { return View(new Person()); } [HttpPost] public ActionResult CreatePerson(Person person) { return View(person); } }
Code Description:
Prepare two actions, one with no data, mainly for the first visit to this page; the other is for receiving data and for submitting forms, http post is used to restrict access requests.
View implementation
@model MVCHelperStudy.Models.Person@{ViewBag.Title = "CreatePerson";}CreatePerson
Code Description:
Without using any html helper function, manually coding a form, the form points to Person/CreatePerson, and the method is post.
Test
1. Visit this page for the first time. You can see that the View has an empty Person object.
2. Fill this form:
3. submit the form
The author sets a breakpoint in the Action. to verify that the request is successfully routed to the CreatePersonAction in The post version.
Note: We manually set the name attribute for each input, which is very important because mvcFramework matches and assigns values with the name attribute of input when submitting a form, what if I remove the name? When the form is submitted, the input value cannot be taken to the action. For example, remove the name attribute of lastName:
Then, submit the form according to the previous process,
View the value of LastName In the debugging status:
We can see that the values of FirstName and Id are included, but the value of LastName cannot be matched because the name attribute is not set. Therefore, the data is not correctly assigned, causing binding failure. For modelbinding, this will be discussed later.
Use Html. BeginForm and Html. EndForm to generate Form Controls
As the name suggests, this function is generated
Result:
1. form labels are generated as expected (based on Route configuration)
2. htmlhelper generates input, each of which has a name, which is the name we passed in.
For Html. TextBox (""), mvcframework searches for the specified property name from ViewData, ViewBag, and @ Model. DataValue respectively. if the first one is found, it returns the result directly to complete the matching.
Forced form
If you are not satisfied with the use of Html. TextBox ("name") to pass a string, you can use Html. TextBoxFor to pass a Member expression:
Common methods for generating html controls with strong types
CheckBox |
Html. CheckBoxFor (x => x. IsApproved) |
|
HiddenField |
Html. HiddenFor (x => x. FirstName) |
|
RadioButton |
Html. RadioButtonFor (x => x. IsApproved, "val ") |
|
Password |
Html. PasswordFor (x => x. Password) |
|
Text Area |
Html. TextAreaFor (x => x. Bio, 5, 20, new {}) |
Bio value |
Text Box |
Html. TextBoxFor (x => x. FirstName) |
|
Almost similar to the string version, the difference is that the signature has a For parameter while the received parameter is a MemberExpression.
Use a strong version to reconstruct our View:
@using(Html.BeginRouteForm("FormRoute",new {}, FormMethod.Post,new { @class = "personClass",data_formType="person"})) {PersonId@Html.TextBoxFor(m => m.PersonId)First Name@Html.TextBoxFor(m => m.FirstName)Last Name@Html.TextBoxFor(m => m.LastName)}
Verify that the html generated by the browser is what we hope:
As you can see, mvcframework generates the expected html for us.
DropDownList
The previous example didn't mention Dropdown. We want to use it as a special example to demonstrate the display of strong types.
1. Let's take a look at the built-in methods for generating drop-down in html.
Html. DropDownList ("myList", new SelectList (new [] {"A", "B"}), "Choose ") |
ChooseAB |
Html. DropDownListFor (x => x. Gender, new SelectList (new [] {"M", "F "})) |
M F |
Html. ListBox ("myList", new MultiSelectList (new [] {"A", "B "})) |
A B |
Html. ListBoxFor (x => x. Vals, new MultiSelectList (new [] {"A", "B "})) |
A B |
As you can see, the mvc framework provides different loads. We can generate multiselect and select.
Generate a form with a role and modify the View code:
@using(Html.BeginRouteForm("FormRoute", new {},FormMethod.Post,new {@class = "personClass", data_formType="person"})) {PersonId@Html.TextBoxFor(m=> m.PersonId)FirstName@Html.TextBoxFor(m=> m.FirstName)LastName@Html.TextBoxFor(m=> m.LastName)Role@Html.DropDownListFor(m=> m.Role,new SelectList(Enum.GetNames(typeof(MVCHelperStudy.Models.Role))))}
This time we added the Role. We used the static method of Enum to obtain all values of the specified Enum type. Member Expression and string array are passed to mvcframework.
Test:
Select tag generated by the browser
RoleAdminUserGuest