Add `Name()`, `NameFor()`, and `NameForModel()` helper methods

- `Name()` is a `virtual` instance method to allow useful derivation
- `NameFor()` is an instance method to avoid adding `GetExpressionName()`
  to the public surface; either method could be `virtual`
- `NameForModel()` is an extension method because it's not usefully overridden
- use `Name*()` in sample
This commit is contained in:
dougbu 2014-03-27 22:43:34 -07:00
parent aaa30591a8
commit fbbc59b392
5 changed files with 108 additions and 2 deletions

View File

@ -4,6 +4,11 @@
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Home Page";
string nullValue = null;
ViewBag.Anon = new
{
Address = new { Street = "123 Fake St.", City = "Redmond", State = "WA", Country = "USA", },
};
}
@functions {
@ -53,6 +58,46 @@
<p>You can easily find a web hosting company that offers the right mix of features and price for your applications.</p>
<p><a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkId=301867">Learn more &raquo;</a></p>
</div>
</div>
<div class="row">
<div style="float: left; border: 5px solid blue;">
<table>
<tr>
<td>
<label class="control-label col-md-2">ForModel</label>
</td>
<td>
'@Html.NameForModel()'
</td>
</tr>
<tr>
<td>
<label class="control-label col-md-2">Name</label>
</td>
<td>
'@Html.Name("Name")'
</td>
</tr>
<tr>
<td>
<label class="control-label col-md-2">m.Address</label>
</td>
<td>
'@Html.NameFor(m => m.Address)'
</td>
</tr>
<tr>
<td>
<label class="control-label col-md-2">Anon.Address.Street</label>
</td>
<td>
'@Html.Name("Anon.Address.Street")'
</td>
</tr>
</table>
</div>
<div style="float: right; border: 5px solid red;">
@await Component.InvokeAsync("Tags", 15)
</div>

View File

@ -130,6 +130,15 @@ namespace Microsoft.AspNet.Mvc.Rendering
return TagBuilder.CreateSanitizedId(name, IdAttributeDotReplacement);
}
/// <inheritdoc />
[SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames",
MessageId = "1#", Justification = "This is a shipped API.")]
public virtual HtmlString Name(string name)
{
var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
return new HtmlString(Encode(fullName));
}
public async Task<HtmlString> PartialAsync([NotNull] string partialViewName, object model, ViewDataDictionary viewData)
{
using (var writer = new StringWriter(CultureInfo.CurrentCulture))

View File

@ -1,5 +1,7 @@
using System;
using Microsoft.AspNet.Abstractions;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using Microsoft.AspNet.Mvc.Rendering.Expressions;
namespace Microsoft.AspNet.Mvc.Rendering
{
@ -36,5 +38,21 @@ namespace Microsoft.AspNet.Mvc.Rendering
base.Contextualize(viewContext);
}
/// <inheritdoc />
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is an appropriate nesting of generic types")]
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters",
Justification = "Users cannot use anonymous methods with the LambdaExpression type")]
public HtmlString NameFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression)
{
var expressionName = GetExpressionName(expression);
return Name(expressionName);
}
protected string GetExpressionName<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression)
{
return ExpressionHelper.GetExpressionText(expression);
}
}
}

View File

@ -0,0 +1,19 @@

namespace Microsoft.AspNet.Mvc.Rendering
{
/// <summary>
/// Name-related extensions for <see cref="HtmlHelper"/> and <see cref="HtmlHelper{T}"/>.
/// </summary>
public static class HtmlHelperNameExtensions
{
/// <summary>
/// Gets the full HTML field name for the current model.
/// </summary>
/// <param name="htmlHelper">The <see cref="HtmlHelper"/> instance that this method extends.</param>
/// <returns>An <see cref="HtmlString"/> that represents HTML markup.</returns>
public static HtmlString NameForModel<TModel>([NotNull] this IHtmlHelper<TModel> htmlHelper)
{
return htmlHelper.Name(string.Empty);
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.Rendering
@ -50,6 +51,21 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// <returns>The ID of the HTML element.</returns>
string GenerateIdFromName(string name);
/// <summary>
/// Gets the full HTML field name for the given expression <paramref name="name"/>.
/// </summary>
/// <param name="name">Name of an expression, relative to the current model.</param>
/// <returns>An <see cref="HtmlString"/> that represents HTML markup.</returns>
HtmlString Name(string name);
/// <summary>
/// Gets the full HTML field name for the given <paramref name="expression"/>.
/// </summary>
/// <typeparam name="TProperty">The <see cref="Type"/> the <paramref name="expression"/> returns.</typeparam>
/// <param name="expression">An expression, relative to the current model.</param>
/// <returns>An <see cref="HtmlString"/> that represents HTML markup.</returns>
HtmlString NameFor<TProperty>([NotNull] Expression<Func<TModel, TProperty>> expression);
/// <summary>
/// Wraps HTML markup in an <see cref="HtmlString"/>, which will enable HTML markup to be
/// rendered to the output without getting HTML encoded.
@ -66,7 +82,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// <returns>An <see cref="HtmlString"/> that represents HTML markup.</returns>
HtmlString Raw(object value);
/// <summary>
/// Returns a partial view in string format.
/// </summary>