![](/img/trans.png)
[英]Using ASP.NET MVC 5, how do I get the localized DisplayAttribute string for an Enum value in a View?
[英]How do I display the DisplayAttribute.Description attribute value?
我有一個 model class,具有這樣的屬性:
[Display(Name = "Phone", Description="Hello World!")]
public string Phone1 { get; set; }
顯示 label 並在我的視圖中呈現文本框以供輸入非常容易:
@Html.LabelFor(model => model.Organization.Phone1)
@Html.EditorFor(model => model.Organization.Phone1)
@Html.ValidationMessageFor(model => model.Organization.Phone1)
但是如何渲染Description annotation 屬性的值,即“Hello World?”?
我最終得到了這樣的助手:
using System;
using System.Linq.Expressions;
using System.Web.Mvc;
public static class MvcHtmlHelpers
{
public static MvcHtmlString DescriptionFor<TModel, TValue>(this HtmlHelper<TModel> self, Expression<Func<TModel, TValue>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
var description = metadata.Description;
return MvcHtmlString.Create(string.Format(@"<span>{0}</span>", description));
}
}
感謝那些帶領我走向正確方向的人。 :)
使用本文中關於如何為表單中的字段顯示視覺提示的技術,您可以通過以下方式訪問該值:
@Html.TextBoxFor(
model => model.Email ,
new { title = ModelMetadata.FromLambdaExpression<RegisterModel , string>(
model => model.Email , ViewData ).Description } )
我正要使用接受的答案,但它不適用於 ASP.NET Core 1/2(又名 MVC 6),因為ModelMetadata.FromLambdaExpression
不再存在並已移至ExpressionMetadataProvider
(用法也略有改變)。
這是您可以與ASP.NET Core 1.1 & 2一起使用的更新擴展方法:
using System;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
public static class HtmlExtensions
{
public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
if (html == null) throw new ArgumentNullException(nameof(html));
if (expression == null) throw new ArgumentNullException(nameof(expression));
var modelExplorer = ExpressionMetadataProvider.FromLambdaExpression(expression, html.ViewData, html.MetadataProvider);
if (modelExplorer == null) throw new InvalidOperationException($"Failed to get model explorer for {ExpressionHelper.GetExpressionText(expression)}");
return new HtmlString(modelExplorer.Metadata.Description);
}
}
ASP.NET 核心1
對於 ASP.NET Core 1,相同的代碼可以工作,但您需要不同的命名空間usings
:
using System;
using System.Linq.Expressions;
using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc.ViewFeatures;
用法
@Html.DescriptionFor(model => model.Phone1)
在 ASP.NET MVC 核心中,您可以使用新的標記幫助程序,這使您的 HTML 看起來像...... HTML :)
像這樣:
<div class="form-group row">
<label asp-for="Name" class="col-md-2 form-control-label"></label>
<div class="col-md-10">
<input asp-for="Name" class="form-control" aria-describedby="Name-description" />
<span asp-description-for="Name" class="form-text text-muted" />
<span asp-validation-for="Name" class="text-danger" />
</div>
</div>
注意 1:您可以在 input 元素中使用aria-describedby
屬性,因為該 id 將在帶有asp-description-for
屬性的 span 元素中自動創建。
注意 2:在 Bootstrap 4 中,類form-text
和text-muted
替換了 v3 help-block
class 以獲得塊級幫助文本。
要讓這個魔法發生,你只需要創建一個新的 Tag Helper:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
/// <summary>
/// <see cref="ITagHelper"/> implementation targeting <span> elements with an <c>asp-description-for</c> attribute.
/// Adds an <c>id</c> attribute and sets the content of the <span> with the Description property from the model data annotation DisplayAttribute.
/// </summary>
[HtmlTargetElement("span", Attributes = DescriptionForAttributeName)]
public class SpanDescriptionTagHelper : TagHelper
{
private const string DescriptionForAttributeName = "asp-description-for";
/// <summary>
/// Creates a new <see cref="SpanDescriptionTagHelper"/>.
/// </summary>
/// <param name="generator">The <see cref="IHtmlGenerator"/>.</param>
public SpanDescriptionTagHelper(IHtmlGenerator generator)
{
Generator = generator;
}
/// <inheritdoc />
public override int Order
{
get
{
return -1000;
}
}
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
protected IHtmlGenerator Generator { get; }
/// <summary>
/// An expression to be evaluated against the current model.
/// </summary>
[HtmlAttributeName(DescriptionForAttributeName)]
public ModelExpression DescriptionFor { get; set; }
/// <inheritdoc />
/// <remarks>Does nothing if <see cref="DescriptionFor"/> is <c>null</c>.</remarks>
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (output == null)
{
throw new ArgumentNullException(nameof(output));
}
var metadata = DescriptionFor.Metadata;
if (metadata == null)
{
throw new InvalidOperationException(string.Format("No provided metadata ({0})", DescriptionForAttributeName));
}
output.Attributes.SetAttribute("id", metadata.PropertyName + "-description");
if( !string.IsNullOrWhiteSpace( metadata.Description))
{
output.Content.SetContent(metadata.Description);
output.TagMode = TagMode.StartTagAndEndTag;
}
}
}
並使您的標簽助手可用於我們所有的 Razor 視圖。 將 addTagHelper 指令添加到Views/_ViewImports.cshtml
文件中:
@addTagHelper "*, YourAssemblyName"
注意 1:將YourAssemblyName
替換為項目的程序集名稱。
注意 2:您只需為所有標簽助手執行此操作!
此處有關標記幫助程序的更多信息:https://docs.asp.net/en/latest/mvc/views/tag-helpers/intro.html
而已! 使用新的標簽助手玩得開心!
如果有人想知道如何使用接受的答案
1-例如在您的解決方案資源管理器中 > 添加新文件夾 > 將其命名為“Helpers”
2- 添加一個新的 class,例如將其命名為“CustomHtmlHelpers”
3-粘貼代碼:
public static class MvcHtmlHelpers
{
public static string DescriptionFor<TModel, TValue>(this HtmlHelper<TModel> self, Expression<Func<TModel, TValue>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
var description = metadata.Description;
return string.IsNullOrWhiteSpace(description) ? "" : description;
}
}
4- 在您的 model 或 viewModel 中使用它:
[Display(Name = "User Name", Description = "Enter your User Name")]
public string FullName { get; set; }
5- 在您的 Razor 視圖中,在 @model 之后,鍵入此行
@using YOUR_PROJECT.Helpers
6-顯示如下描述:
@Html.DescriptionFor(m => m.FullName)
7-您可能希望使用描述在輸入占位符中顯示文本:
@Html.DisplayNameFor(m => m.FullName)
@Html.TextBoxFor(m => m.FullName, new { @class = "form-control", placeholder = Html.DescriptionFor(m => m.FullName) })
謝謝
var attrib = (DisplayAttribute)Attribute.GetCustomAttribute(
member, typeof(DisplayAttribute));
var desc = attrib == null ? "" : attrib.GetDescription()
@ViewData.ModelMetadata.Properties
.Where(m => m.PropertyName == "Phone1").FirstOrDefault().Description
因此,如果您使用的是引導程序,例如
<div class="form-group col-sm-6">
@Html.LabelFor(m => m.Organization.Phone1)
@Html.EditorFor(m => m.Organization.Phone1)
<p class="help-block">
@ViewData.ModelMetadata.Properties
.Where(m => m.PropertyName == "DayCount").FirstOrDefault().Description
</p>
</div>
這是 ASP.NET Core 3.1 和 5 的更新版本:
public static class HtmlExtensions
{
public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
if (html == null) throw new ArgumentNullException(nameof(html));
if (expression == null) throw new ArgumentNullException(nameof(expression));
var expressionProvider = html.ViewContext?.HttpContext?.RequestServices?.GetService<ModelExpressionProvider>()
?? new ModelExpressionProvider(html.MetadataProvider);
var modelExpression = expressionProvider.CreateModelExpression(html.ViewData, expression);
return new HtmlString(modelExpression.Metadata.Description);
}
}
由於ExpressionMetadataProvider
被標記為內部,我們必須通過ModelExpressionProvider
到 go。
ModelExpressionProvider.CreateModelExpression()
無論如何都會在內部調用ExpressionMetadataProvider.FromLambdaExpression()
:
...如果您希望將描述作為 label 形式的工具提示,請添加如下標簽助手:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
/// <summary>
/// <see cref="ITagHelper"/> implementation targeting <label> elements with an <c>asp-for</c> attribute.
/// Adds a <c>title</c> attribute to the <label> with the Description property from the model data annotation DisplayAttribute.
/// </summary>
[HtmlTargetElement("label", Attributes = ForAttributeName)]
public class LabelTitleTagHelper : TagHelper
{
private const string ForAttributeName = "asp-for";
/// <summary>
/// Creates a new <see cref="LabelTitleTagHelper"/>.
/// </summary>
/// <param name="generator">The <see cref="IHtmlGenerator"/>.</param>
public LabelTitleTagHelper(IHtmlGenerator generator)
{
Generator = generator;
}
/// <inheritdoc />
public override int Order
{
get
{
return -1000;
}
}
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
protected IHtmlGenerator Generator { get; }
/// <summary>
/// An expression to be evaluated against the current model.
/// </summary>
[HtmlAttributeName(ForAttributeName)]
public ModelExpression TitleFor { get; set; }
/// <inheritdoc />
/// <remarks>Does nothing if <see cref="TitleFor"/> is <c>null</c>.</remarks>
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (output == null)
{
throw new ArgumentNullException(nameof(output));
}
var metadata = TitleFor.Metadata;
if (metadata == null)
{
throw new InvalidOperationException(string.Format("No provided metadata ({0})", ForAttributeName));
}
if (!string.IsNullOrWhiteSpace(metadata.Description))
output.Attributes.SetAttribute("title", metadata.Description);
}
}
這將使用模型的數據注釋DisplayAttribute
中的Description
屬性創建一個新的title
屬性。
美麗的部分是您不需要觸摸生成的腳手架視圖! 因為這個標簽助手的目標是已經存在的label
元素的asp-for
屬性!
您必須編寫一個自定義幫助程序來反映您的 model 以提供 Description 屬性值。
除了 Jakob Gade'一個很好的答案:
如果您需要支持DescriptionAttribute
而不是DisplayAttribute
,如果我們覆蓋 MetadataProvider,他的出色解決方案仍然有效:
public class ExtendedModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<System.Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
//Possible Multiple Enumerations on IEnumerable fix
var attributeList = attributes as IList<System.Attribute> ?? attributes.ToList();
//Default behavior
var data = base.CreateMetadata(attributeList, containerType, modelAccessor, modelType, propertyName);
//Bind DescriptionAttribute
var description = attributeList.SingleOrDefault(a => typeof(DescriptionAttribute) == a.GetType());
if (description != null)
{
data.Description = ((DescriptionAttribute)description).Description;
}
return data;
}
}
這需要在Global.asax.cs
的Application_Start
方法中注冊:
ModelMetadataProviders.Current = new ExtendedModelMetadataProvider();
HANDL 的答案,針對 ASP.NET Core 2.0 更新
using System;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
public static class HtmlExtensions
{
public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
if (html == null) throw new ArgumentNullException(nameof(html));
if (expression == null) throw new ArgumentNullException(nameof(expression));
var modelExplorer = ExpressionMetadataProvider.FromLambdaExpression(expression, html.ViewData, html.MetadataProvider);
if (modelExplorer == null) throw new InvalidOperationException($"Failed to get model explorer for {ExpressionHelper.GetExpressionText(expression)}");
return new HtmlString(modelExplorer.Metadata.Description);
}
}
您始終可以像這樣創建自己的自定義擴展:
public static MvcHtmlString ToolTipLabel (string resourceKey, string text, bool isRequired, string labelFor = "", string labelId = "",string className="")
{
string tooltip = string.Empty;
StringBuilder sb = new StringBuilder();
if (!string.IsNullOrEmpty(resourceKey))
{
var resources = GetAllResourceValues();
if (resources.ContainsKey(resourceKey))
{
tooltip = resources[resourceKey].Value;
}
}
sb.Append("<label");
if (!string.IsNullOrEmpty(labelFor))
{
sb.AppendFormat(" for=\"{0}\"", labelFor);
}
if (!string.IsNullOrEmpty(labelId))
{
sb.AppendFormat(" Id=\"{0}\"", labelId);
}
if (!string.IsNullOrEmpty(className))
{
sb.AppendFormat(" class=\"{0}\"", className);
}
if (!string.IsNullOrEmpty(tooltip))
{
sb.AppendFormat(" data-toggle='tooltip' data-placement='auto left' title=\"{0}\"",tooltip);
}
if (isRequired)
{
sb.AppendFormat("><em class='required'>*</em> {0} </label></br>", text);
}
else
{
sb.AppendFormat(">{0}</label></br>", text);
}
return MvcHtmlString.Create(sb.ToString());
}
並且可以像這樣看到它:
@HtmlExtension.ToolTipLabel(" "," ",true," "," "," ")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.