Add remaining HTML input helpers
- add `CheckBox[For]()`, `Hidden[For]()`, `Password[For]()`, and
`RadioButton[For]()`
- also make `FormatValue()` visible to users, as it is in legacy MVC
- and spread the boxes out a bit in MyView 😺
This commit is contained in:
parent
b1fd5cc689
commit
f0a97772f5
|
|
@ -79,6 +79,7 @@ namespace MvcSample.Web
|
||||||
Alive = true,
|
Alive = true,
|
||||||
Age = 13,
|
Age = 13,
|
||||||
GPA = 13.37M,
|
GPA = 13.37M,
|
||||||
|
Password = "Secure string",
|
||||||
Dependent = new User()
|
Dependent = new User()
|
||||||
{
|
{
|
||||||
Name = "Dependents name",
|
Name = "Dependents name",
|
||||||
|
|
|
||||||
|
|
@ -12,5 +12,6 @@ namespace MvcSample.Web.Models
|
||||||
public decimal GPA { get; set; }
|
public decimal GPA { get; set; }
|
||||||
public User Dependent { get; set; }
|
public User Dependent { get; set; }
|
||||||
public bool Alive { get; set; }
|
public bool Alive { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -141,6 +141,7 @@
|
||||||
<div style="float: left; border: thick solid lightskyblue; margin-bottom: 10px; margin-top: -180px; padding-right: 10px">
|
<div style="float: left; border: thick solid lightskyblue; margin-bottom: 10px; margin-top: -180px; padding-right: 10px">
|
||||||
@using (Html.BeginForm(controllerName: "Home", actionName: "Hello", method: FormMethod.Post))
|
@using (Html.BeginForm(controllerName: "Home", actionName: "Hello", method: FormMethod.Post))
|
||||||
{
|
{
|
||||||
|
@Html.HiddenFor(m => m.Age)
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -160,13 +161,44 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="submit" value="Save" class="btn btn-default" />
|
<label class="control-label col-md-2">Model.Alive</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.CheckBox("Alive")
|
||||||
|
or
|
||||||
|
@Html.RadioButton("Alive", value: false) False
|
||||||
|
@Html.RadioButton("Alive", value: true) True
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="control-label col-md-2">Model.Dependent.Alive</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.CheckBoxFor(m => m.Dependent.Alive)
|
||||||
|
or
|
||||||
|
@Html.RadioButtonFor(m => m.Dependent.Alive, value: false) False
|
||||||
|
@Html.RadioButtonFor(m => m.Dependent.Alive, value: true) True
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="control-label col-md-2">Model.Password</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.PasswordFor(m => m.Password, htmlAttributes: new { @class = "form-control" })
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="submit" value="Save" class="btn btn-default" style="margin-left: 10px" />
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
}
|
}
|
||||||
@{ Html.BeginForm(method: FormMethod.Post, htmlAttributes: new { someAttribute = "some value", }); }
|
@{ Html.BeginForm(method: FormMethod.Post, htmlAttributes: new { someAttribute = "some value", }); }
|
||||||
|
@Html.Hidden("Anon.Id")
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -211,7 +243,15 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="submit" value="Save" class="btn btn-default" />
|
<label class="control-label col-md-2">Password</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.Password("Password", "some string")
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="submit" value="Save" class="btn btn-default" style="margin-left: 10px" />
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -273,7 +313,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div style="float: left; border: 5px solid green;">
|
<div style="float: left; border: 5px solid green; margin-left: 10px; margin-bottom: 10px; ">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.Contracts;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Abstractions;
|
|
||||||
using Microsoft.AspNet.Mvc.Core;
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Rendering.Expressions;
|
using Microsoft.AspNet.Mvc.Rendering.Expressions;
|
||||||
|
|
@ -50,8 +50,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
|
||||||
public string IdAttributeDotReplacement { get; set; }
|
public string IdAttributeDotReplacement { get; set; }
|
||||||
|
|
||||||
public HttpContext HttpContext { get; private set; }
|
|
||||||
|
|
||||||
public ViewContext ViewContext
|
public ViewContext ViewContext
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -182,6 +180,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
mvcForm.EndForm();
|
mvcForm.EndForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HtmlString CheckBox(string name, bool? isChecked, object htmlAttributes)
|
||||||
|
{
|
||||||
|
return GenerateCheckBox(metadata: null, name: name, isChecked: isChecked, htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
public string Encode(string value)
|
public string Encode(string value)
|
||||||
{
|
{
|
||||||
return (!string.IsNullOrEmpty(value)) ? WebUtility.HtmlEncode(value) : string.Empty;
|
return (!string.IsNullOrEmpty(value)) ? WebUtility.HtmlEncode(value) : string.Empty;
|
||||||
|
|
@ -225,6 +228,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
additionalViewData);
|
additionalViewData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HtmlString Hidden(string name, object value, object htmlAttributes)
|
||||||
|
{
|
||||||
|
return GenerateHidden(metadata: null, name: name, value: value, useViewData: (value == null),
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual HtmlString Name(string name)
|
public virtual HtmlString Name(string name)
|
||||||
{
|
{
|
||||||
var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
|
var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
|
||||||
|
|
@ -287,6 +296,17 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
await viewEngineResult.View.RenderAsync(newViewContext);
|
await viewEngineResult.View.RenderAsync(newViewContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HtmlString Password(string name, object value, object htmlAttributes)
|
||||||
|
{
|
||||||
|
return GeneratePassword(metadata: null, name: name, value: value, htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HtmlString RadioButton(string name, object value, bool? isChecked, object htmlAttributes)
|
||||||
|
{
|
||||||
|
return GenerateRadioButton(metadata: null, name: name, value: value, isChecked: isChecked,
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual HtmlString ValidationSummary(bool excludePropertyErrors, string message, IDictionary<string, object> htmlAttributes)
|
public virtual HtmlString ValidationSummary(bool excludePropertyErrors, string message, IDictionary<string, object> htmlAttributes)
|
||||||
{
|
{
|
||||||
var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
|
var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
|
||||||
|
|
@ -417,6 +437,16 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return new MvcForm(ViewContext);
|
return new MvcForm(ViewContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected bool EvalBoolean(string key)
|
||||||
|
{
|
||||||
|
return Convert.ToBoolean(ViewData.Eval(key), CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string EvalString(string key)
|
||||||
|
{
|
||||||
|
return Convert.ToString(ViewData.Eval(key), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
protected string EvalString(string key, string format)
|
protected string EvalString(string key, string format)
|
||||||
{
|
{
|
||||||
return Convert.ToString(ViewData.Eval(key, format), CultureInfo.CurrentCulture);
|
return Convert.ToString(ViewData.Eval(key, format), CultureInfo.CurrentCulture);
|
||||||
|
|
@ -447,6 +477,54 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return new Dictionary<string, object>();
|
return new Dictionary<string, object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual HtmlString GenerateCheckBox(ModelMetadata metadata, string name, bool? isChecked,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
if (metadata != null)
|
||||||
|
{
|
||||||
|
// CheckBoxFor() case. That API does not support passing isChecked directly.
|
||||||
|
Contract.Assert(!isChecked.HasValue);
|
||||||
|
|
||||||
|
if (metadata.Model != null)
|
||||||
|
{
|
||||||
|
bool modelChecked;
|
||||||
|
if (Boolean.TryParse(metadata.Model.ToString(), out modelChecked))
|
||||||
|
{
|
||||||
|
isChecked = modelChecked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only need a dictionary if htmlAttributes is non-null. TagBuilder.MergeAttributes() is fine with null.
|
||||||
|
IDictionary<string, object> htmlAttributeDictionary = null;
|
||||||
|
if (htmlAttributes != null)
|
||||||
|
{
|
||||||
|
htmlAttributeDictionary = htmlAttributes as IDictionary<string, object>;
|
||||||
|
if (htmlAttributeDictionary == null)
|
||||||
|
{
|
||||||
|
htmlAttributeDictionary = AnonymousObjectToHtmlAttributes(htmlAttributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var explicitValue = isChecked.HasValue;
|
||||||
|
if (explicitValue && htmlAttributeDictionary != null)
|
||||||
|
{
|
||||||
|
// Explicit value must override dictionary
|
||||||
|
htmlAttributeDictionary.Remove("checked");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GenerateInput(InputType.CheckBox,
|
||||||
|
metadata,
|
||||||
|
name,
|
||||||
|
value: "true",
|
||||||
|
useViewData: !explicitValue,
|
||||||
|
isChecked: isChecked ?? false,
|
||||||
|
setId: true,
|
||||||
|
isExplicitValue: false,
|
||||||
|
format: null,
|
||||||
|
htmlAttributes: htmlAttributeDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes an opening <form> tag to the response. When the user submits the form,
|
/// Writes an opening <form> tag to the response. When the user submits the form,
|
||||||
/// the request will be processed by an action method.
|
/// the request will be processed by an action method.
|
||||||
|
|
@ -496,6 +574,38 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return theForm;
|
return theForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual HtmlString GenerateHidden(ModelMetadata metadata, string name, object value, bool useViewData,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
// Only need a dictionary if htmlAttributes is non-null. TagBuilder.MergeAttributes() is fine with null.
|
||||||
|
IDictionary<string, object> htmlAttributeDictionary = null;
|
||||||
|
if (htmlAttributes != null)
|
||||||
|
{
|
||||||
|
htmlAttributeDictionary = htmlAttributes as IDictionary<string, object>;
|
||||||
|
if (htmlAttributeDictionary == null)
|
||||||
|
{
|
||||||
|
htmlAttributeDictionary = AnonymousObjectToHtmlAttributes(htmlAttributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var byteArrayValue = value as byte[];
|
||||||
|
if (byteArrayValue != null)
|
||||||
|
{
|
||||||
|
value = Convert.ToBase64String(byteArrayValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GenerateInput(InputType.Hidden,
|
||||||
|
metadata,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
useViewData,
|
||||||
|
isChecked: false,
|
||||||
|
setId: true,
|
||||||
|
isExplicitValue: true,
|
||||||
|
format: null,
|
||||||
|
htmlAttributes: htmlAttributeDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual HtmlString GenerateLink(
|
protected virtual HtmlString GenerateLink(
|
||||||
[NotNull] string linkText,
|
[NotNull] string linkText,
|
||||||
[NotNull] string url,
|
[NotNull] string url,
|
||||||
|
|
@ -512,6 +622,99 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return tagBuilder.ToHtmlString(TagRenderMode.Normal);
|
return tagBuilder.ToHtmlString(TagRenderMode.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual HtmlString GeneratePassword(ModelMetadata metadata, string name, object value,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
// Only need a dictionary if htmlAttributes is non-null. TagBuilder.MergeAttributes() is fine with null.
|
||||||
|
IDictionary<string, object> htmlAttributeDictionary = null;
|
||||||
|
if (htmlAttributes != null)
|
||||||
|
{
|
||||||
|
htmlAttributeDictionary = htmlAttributes as IDictionary<string, object>;
|
||||||
|
if (htmlAttributeDictionary == null)
|
||||||
|
{
|
||||||
|
htmlAttributeDictionary = AnonymousObjectToHtmlAttributes(htmlAttributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GenerateInput(InputType.Password,
|
||||||
|
metadata,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
useViewData: false,
|
||||||
|
isChecked: false,
|
||||||
|
setId: true,
|
||||||
|
isExplicitValue: true,
|
||||||
|
format: null,
|
||||||
|
htmlAttributes: htmlAttributeDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual HtmlString GenerateRadioButton(ModelMetadata metadata, string name, object value,
|
||||||
|
bool? isChecked, object htmlAttributes)
|
||||||
|
{
|
||||||
|
// Only need a dictionary if htmlAttributes is non-null. TagBuilder.MergeAttributes() is fine with null.
|
||||||
|
IDictionary<string, object> htmlAttributeDictionary = null;
|
||||||
|
if (htmlAttributes != null)
|
||||||
|
{
|
||||||
|
htmlAttributeDictionary = htmlAttributes as IDictionary<string, object>;
|
||||||
|
if (htmlAttributeDictionary == null)
|
||||||
|
{
|
||||||
|
htmlAttributeDictionary = AnonymousObjectToHtmlAttributes(htmlAttributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metadata == null)
|
||||||
|
{
|
||||||
|
// RadioButton() case. Do not override checked attribute if isChecked is implicit.
|
||||||
|
if (!isChecked.HasValue &&
|
||||||
|
(htmlAttributeDictionary == null || !htmlAttributeDictionary.ContainsKey("checked")))
|
||||||
|
{
|
||||||
|
// Note value may be null if isChecked is non-null.
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// isChecked not provided nor found in the given attributes; fall back to view data.
|
||||||
|
var valueString = Convert.ToString(value, CultureInfo.CurrentCulture);
|
||||||
|
isChecked = !string.IsNullOrEmpty(name) &&
|
||||||
|
string.Equals(EvalString(name), valueString, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// RadioButtonFor() case. That API does not support passing isChecked directly.
|
||||||
|
Contract.Assert(!isChecked.HasValue);
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
// Need a value to determine isChecked.
|
||||||
|
throw new ArgumentNullException("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
var model = metadata.Model;
|
||||||
|
var valueString = Convert.ToString(value, CultureInfo.CurrentCulture);
|
||||||
|
isChecked = model != null &&
|
||||||
|
string.Equals(model.ToString(), valueString, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
var explicitValue = isChecked.HasValue;
|
||||||
|
if (explicitValue && htmlAttributeDictionary != null)
|
||||||
|
{
|
||||||
|
// Explicit value must override dictionary
|
||||||
|
htmlAttributeDictionary.Remove("checked");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GenerateInput(InputType.Radio,
|
||||||
|
metadata,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
useViewData: false,
|
||||||
|
isChecked: isChecked ?? false,
|
||||||
|
setId: true,
|
||||||
|
isExplicitValue: true,
|
||||||
|
format: null,
|
||||||
|
htmlAttributes: htmlAttributeDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual HtmlString GenerateTextBox(ModelMetadata metadata, string name, object value, string format,
|
protected virtual HtmlString GenerateTextBox(ModelMetadata metadata, string name, object value, string format,
|
||||||
IDictionary<string, object> htmlAttributes)
|
IDictionary<string, object> htmlAttributes)
|
||||||
{
|
{
|
||||||
|
|
@ -531,8 +734,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, string format,
|
object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, string format,
|
||||||
IDictionary<string, object> htmlAttributes)
|
IDictionary<string, object> htmlAttributes)
|
||||||
{
|
{
|
||||||
// Not valid to use TextBoxForModel() in a top-level view; would end up with an unnamed input elements.
|
// Not valid to use TextBoxForModel() and so on in a top-level view; would end up with an unnamed input
|
||||||
// But we support the *ForModel() methods in any lower-level template, once HtmlFieldPrefix is non-empty.
|
// elements. But we support the *ForModel() methods in any lower-level template, once HtmlFieldPrefix is
|
||||||
|
// non-empty.
|
||||||
var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
|
var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
|
||||||
if (string.IsNullOrEmpty(fullName))
|
if (string.IsNullOrEmpty(fullName))
|
||||||
{
|
{
|
||||||
|
|
@ -545,8 +749,51 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
tagBuilder.MergeAttribute("name", fullName, replaceExisting: true);
|
tagBuilder.MergeAttribute("name", fullName, replaceExisting: true);
|
||||||
|
|
||||||
var valueParameter = FormatValue(value, format);
|
var valueParameter = FormatValue(value, format);
|
||||||
|
var usedModelState = false;
|
||||||
switch (inputType)
|
switch (inputType)
|
||||||
{
|
{
|
||||||
|
case InputType.CheckBox:
|
||||||
|
var modelStateWasChecked = GetModelStateValue(fullName, typeof(bool)) as bool?;
|
||||||
|
if (modelStateWasChecked.HasValue)
|
||||||
|
{
|
||||||
|
isChecked = modelStateWasChecked.Value;
|
||||||
|
usedModelState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto case InputType.Radio;
|
||||||
|
|
||||||
|
case InputType.Radio:
|
||||||
|
if (!usedModelState)
|
||||||
|
{
|
||||||
|
var modelStateValue = GetModelStateValue(fullName, typeof(string)) as string;
|
||||||
|
if (modelStateValue != null)
|
||||||
|
{
|
||||||
|
isChecked = string.Equals(modelStateValue, valueParameter, StringComparison.Ordinal);
|
||||||
|
usedModelState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!usedModelState && useViewData)
|
||||||
|
{
|
||||||
|
isChecked = EvalBoolean(fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isChecked)
|
||||||
|
{
|
||||||
|
tagBuilder.MergeAttribute("checked", "checked");
|
||||||
|
}
|
||||||
|
|
||||||
|
tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputType.Password:
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case InputType.Text:
|
case InputType.Text:
|
||||||
default:
|
default:
|
||||||
var attributeValue = (string)GetModelStateValue(fullName, typeof(string));
|
var attributeValue = (string)GetModelStateValue(fullName, typeof(string));
|
||||||
|
|
@ -573,6 +820,23 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
|
||||||
tagBuilder.MergeAttributes(GetValidationAttributes(name, metadata));
|
tagBuilder.MergeAttributes(GetValidationAttributes(name, metadata));
|
||||||
|
|
||||||
|
if (inputType == InputType.CheckBox)
|
||||||
|
{
|
||||||
|
// Generate an additional <input type="hidden".../> for checkboxes. This
|
||||||
|
// addresses scenarios where unchecked checkboxes are not sent in the request.
|
||||||
|
// Sending a hidden input makes it possible to know that the checkbox was present
|
||||||
|
// on the page when the request was submitted.
|
||||||
|
var inputItemBuilder = new StringBuilder();
|
||||||
|
inputItemBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));
|
||||||
|
|
||||||
|
var hiddenInput = new TagBuilder("input");
|
||||||
|
hiddenInput.MergeAttribute("type", GetInputTypeString(InputType.Hidden));
|
||||||
|
hiddenInput.MergeAttribute("name", fullName);
|
||||||
|
hiddenInput.MergeAttribute("value", "false");
|
||||||
|
inputItemBuilder.Append(hiddenInput.ToString(TagRenderMode.SelfClosing));
|
||||||
|
return new HtmlString(inputItemBuilder.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
return tagBuilder.ToHtmlString(TagRenderMode.SelfClosing);
|
return tagBuilder.ToHtmlString(TagRenderMode.SelfClosing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -611,7 +875,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return new HtmlString(Encode(resolvedValue));
|
return new HtmlString(Encode(resolvedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static string GetInputTypeString(InputType inputType)
|
private static string GetInputTypeString(InputType inputType)
|
||||||
{
|
{
|
||||||
switch (inputType)
|
switch (inputType)
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,16 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
base.Contextualize(viewContext);
|
base.Contextualize(viewContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public HtmlString CheckBoxFor([NotNull] Expression<Func<TModel, bool>> expression,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
var metadata = GetModelMetadata(expression);
|
||||||
|
return GenerateCheckBox(metadata, GetExpressionName(expression), isChecked: null,
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public HtmlString DisplayFor<TValue>([NotNull] Expression<Func<TModel, TValue>> expression,
|
public HtmlString DisplayFor<TValue>([NotNull] Expression<Func<TModel, TValue>> expression,
|
||||||
string templateName,
|
string templateName,
|
||||||
string htmlFieldName,
|
string htmlFieldName,
|
||||||
|
|
@ -63,6 +72,15 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
additionalViewData);
|
additionalViewData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public HtmlString HiddenFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
var metadata = GetModelMetadata(expression);
|
||||||
|
return GenerateHidden(metadata, GetExpressionName(expression), metadata.Model, useViewData: false,
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public HtmlString NameFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression)
|
public HtmlString NameFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression)
|
||||||
{
|
{
|
||||||
|
|
@ -70,6 +88,24 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return Name(expressionName);
|
return Name(expressionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public HtmlString PasswordFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
var metadata = GetModelMetadata(expression);
|
||||||
|
return GeneratePassword(metadata, GetExpressionName(expression), value: null,
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public HtmlString RadioButtonFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
object value, object htmlAttributes)
|
||||||
|
{
|
||||||
|
var metadata = GetModelMetadata(expression);
|
||||||
|
return GenerateRadioButton(metadata, GetExpressionName(expression), value, isChecked: null,
|
||||||
|
htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public HtmlString TextBoxFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression,
|
public HtmlString TextBoxFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
string format, IDictionary<string, object> htmlAttributes)
|
string format, IDictionary<string, object> htmlAttributes)
|
||||||
|
|
@ -95,10 +131,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public HtmlString ValueFor<TProperty>(Expression<Func<TModel, TProperty>> expression, string format)
|
public HtmlString ValueFor<TProperty>(Expression<Func<TModel, TProperty>> expression, string format)
|
||||||
{
|
{
|
||||||
var metadata = GetModelMetadata(expression);
|
var metadata = GetModelMetadata(expression);
|
||||||
return GenerateValue(ExpressionHelper.GetExpressionText(expression), metadata.Model, format, useViewData: false);
|
return GenerateValue(ExpressionHelper.GetExpressionText(expression), metadata.Model, format,
|
||||||
|
useViewData: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,92 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Rendering
|
namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
public static class HtmlHelperInputExtensions
|
public static class HtmlHelperInputExtensions
|
||||||
{
|
{
|
||||||
|
public static HtmlString CheckBox<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name)
|
||||||
|
{
|
||||||
|
return htmlHelper.CheckBox(name, isChecked: null, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString CheckBox<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
bool isChecked)
|
||||||
|
{
|
||||||
|
return htmlHelper.CheckBox(name, isChecked, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString CheckBox<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
object htmlAttributes)
|
||||||
|
{
|
||||||
|
return htmlHelper.CheckBox(name, isChecked: null, htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString CheckBoxFor<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper,
|
||||||
|
[NotNull] Expression<Func<TModel, bool>> expression)
|
||||||
|
{
|
||||||
|
return htmlHelper.CheckBoxFor(expression, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString Hidden<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name)
|
||||||
|
{
|
||||||
|
return htmlHelper.Hidden(name, value: null, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString Hidden<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
object value)
|
||||||
|
{
|
||||||
|
return htmlHelper.Hidden(name, value, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString HiddenFor<TModel, TProperty>([NotNull] this IHtmlHelper<TModel> htmlHelper,
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression)
|
||||||
|
{
|
||||||
|
return htmlHelper.HiddenFor(expression, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString Password<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name)
|
||||||
|
{
|
||||||
|
return htmlHelper.Password(name, value: null, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString Password<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
object value)
|
||||||
|
{
|
||||||
|
return htmlHelper.Password(name, value, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString PasswordFor<TModel, TProperty>([NotNull] this IHtmlHelper<TModel> htmlHelper,
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression)
|
||||||
|
{
|
||||||
|
return htmlHelper.PasswordFor(expression, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString RadioButton<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
object value)
|
||||||
|
{
|
||||||
|
return htmlHelper.RadioButton(name, value, isChecked: null, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString RadioButton<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
object value, object htmlAttributes)
|
||||||
|
{
|
||||||
|
return htmlHelper.RadioButton(name, value, isChecked: null, htmlAttributes: htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString RadioButton<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name,
|
||||||
|
object value, bool isChecked)
|
||||||
|
{
|
||||||
|
return htmlHelper.RadioButton(name, value, isChecked, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HtmlString RadioButtonFor<TModel, TProperty>([NotNull] this IHtmlHelper<TModel> htmlHelper,
|
||||||
|
[NotNull] Expression<Func<TModel, TProperty>> expression, object value)
|
||||||
|
{
|
||||||
|
return htmlHelper.RadioButtonFor(expression, value, htmlAttributes: null);
|
||||||
|
}
|
||||||
|
|
||||||
public static HtmlString TextBox<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name)
|
public static HtmlString TextBox<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper, string name)
|
||||||
{
|
{
|
||||||
return TextBox(htmlHelper, name, value: null);
|
return TextBox(htmlHelper, name, value: null);
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,37 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void EndForm();
|
void EndForm();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render an input element of type "checkbox" with value "true" and an input element of type "hidden" with
|
||||||
|
/// value "false".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">
|
||||||
|
/// Rendered element's name. Also use this name to find value in submitted data or view data. Use view data
|
||||||
|
/// only if value is not in submitted data and <paramref name="value"/> is <c>null</c>.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="isChecked">
|
||||||
|
/// If <c>true</c>, checkbox is initially checked. Ignore if named value is found in submitted data. Finally
|
||||||
|
/// fall back to an existing "checked" value in <paramref name="htmlAttributes"/>.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>New <see cref="HtmlString"/> containing the rendered HTML.</returns>
|
||||||
|
HtmlString CheckBox(string name, bool? isChecked, object htmlAttributes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render an input element of type "checkbox" with value "true" and an input element of type "hidden" with
|
||||||
|
/// value "false".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expression">
|
||||||
|
/// An expression that identifies the object that contains the properties to render.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>New <see cref="HtmlString"/> containing the rendered HTML.</returns>
|
||||||
|
HtmlString CheckBoxFor([NotNull] Expression<Func<TModel, bool>> expression, object htmlAttributes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns HTML markup for each property in the object that is represented by the expression, using the specified
|
/// Returns HTML markup for each property in the object that is represented by the expression, using the specified
|
||||||
/// template, HTML field ID, and additional view data.
|
/// template, HTML field ID, and additional view data.
|
||||||
|
|
@ -158,6 +189,14 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
/// <returns>The HTML-encoded string.</returns>
|
/// <returns>The HTML-encoded string.</returns>
|
||||||
string Encode(string value);
|
string Encode(string value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats the value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
/// <param name="format">The format string.</param>
|
||||||
|
/// <returns>The formatted value.</returns>
|
||||||
|
string FormatValue(object value, string format);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an HTML element ID using the specified element name.
|
/// Creates an HTML element ID using the specified element name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -165,6 +204,35 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
/// <returns>The ID of the HTML element.</returns>
|
/// <returns>The ID of the HTML element.</returns>
|
||||||
string GenerateIdFromName(string name);
|
string GenerateIdFromName(string name);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render an input element of type "hidden".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">
|
||||||
|
/// Rendered element's name. Also use this name to find value in submitted data or view data. Use view data
|
||||||
|
/// only if value is not in submitted data and <paramref name="value"/> is <c>null</c>.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="value">
|
||||||
|
/// If non-<c>null</c>, value to include in the element. Ignore if named value is found in submitted data.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>New <see cref="HtmlString"/> containing the rendered HTML.</returns>
|
||||||
|
HtmlString Hidden(string name, object value, object htmlAttributes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render an input element of type "hidden".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expression">
|
||||||
|
/// An expression that identifies the object that contains the properties to render.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>New <see cref="HtmlString"/> containing the rendered HTML.</returns>
|
||||||
|
HtmlString HiddenFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
object htmlAttributes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the full HTML field name for the given expression <paramref name="name"/>.
|
/// Gets the full HTML field name for the given expression <paramref name="name"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -180,6 +248,76 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
/// <returns>An <see cref="HtmlString"/> that represents HTML markup.</returns>
|
/// <returns>An <see cref="HtmlString"/> that represents HTML markup.</returns>
|
||||||
HtmlString NameFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression);
|
HtmlString NameFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render an input element of type "password".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">
|
||||||
|
/// Rendered element's name. Also use this name to find value in view data. Use view data
|
||||||
|
/// only if value is not in submitted data and <paramref name="value"/> is <c>null</c>.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="value">
|
||||||
|
/// If non-<c>null</c>, value to include in the element.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>New <see cref="HtmlString"/> containing the rendered HTML.</returns>
|
||||||
|
HtmlString Password(string name, object value, object htmlAttributes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render an input element of type "password".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expression">
|
||||||
|
/// An expression that identifies the object that contains the properties to render.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>New <see cref="HtmlString"/> containing the rendered HTML.</returns>
|
||||||
|
HtmlString PasswordFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression,
|
||||||
|
object htmlAttributes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render an input element of type "radio".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">
|
||||||
|
/// Rendered element's name. Also use this name to find value in submitted data or view data. Use view data
|
||||||
|
/// only if value is not in submitted data and <paramref name="value"/> is <c>null</c>.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="value">
|
||||||
|
/// If non-<c>null</c>, value to include in the element. May be <c>null</c> only if
|
||||||
|
/// <paramref name="isChecked"/> is also <c>null</c>. Also compared to value in submitted data or view data to
|
||||||
|
/// determine <paramref name="isChecked"/> if that parameter is <c>null</c>. Ignore if named value is found in
|
||||||
|
/// submitted data.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="isChecked">
|
||||||
|
/// If <c>true</c>, radio button is initially selected. Ignore if named value is found in submitted data. Fall
|
||||||
|
/// back to comparing <paramref name="value"/> with view data if this parameter is <c>null</c>. Finally
|
||||||
|
/// fall back to an existing "checked" value in <paramref name="htmlAttributes"/>.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>New <see cref="HtmlString"/> containing the rendered HTML.</returns>
|
||||||
|
HtmlString RadioButton(string name, object value, bool? isChecked, object htmlAttributes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render an input element of type "radio".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expression">
|
||||||
|
/// An expression that identifies the object that contains the properties to render.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="value">
|
||||||
|
/// If non-<c>null</c>, value to compare with current expression value to determine whether radio button is
|
||||||
|
/// checked.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.
|
||||||
|
/// Alternatively, an <see cref="IDictionary{string, object}"/> instance containing the HTML attributes.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>New <see cref="HtmlString"/> containing the rendered HTML.</returns>
|
||||||
|
HtmlString RadioButtonFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression, object value,
|
||||||
|
object htmlAttributes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wraps HTML markup in an <see cref="HtmlString"/>, which will enable HTML markup to be
|
/// Wraps HTML markup in an <see cref="HtmlString"/>, which will enable HTML markup to be
|
||||||
/// rendered to the output without getting HTML encoded.
|
/// rendered to the output without getting HTML encoded.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue