在ASP.Net Core中是否可以自动转换视图模型中的驼峰大小写属性名称,以便在使用标记帮助程序时将空格插入相应的标签中?
如果我的视图模型看起来像这样......
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Referral Date")]
public DateTime ReferralDate { get; set; }
似乎有很多额外的配置应用数据注释,如
[显示(姓名="名字")]
只需在单词之间插入空格即可。默认情况下,Tag Helpers会插入空格以避免这种手动配置和潜在的拼写错误。
如果没有,自定义标签帮助器可以在这种情况下提供帮助,如果是这样,它将如何工作?
答案 0 :(得分:2)
您可以通过构建和注册自定义显示元数据提供程序来实现此目的。有些图书馆将进行更精细的人性化和#34;对于属性名称,但是你可以用一些可信的正则表达式来实现非常有用的东西。
public class HumanizerMetadataProvider : IDisplayMetadataProvider
{
public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
{
var propertyAttributes = context.Attributes;
var modelMetadata = context.DisplayMetadata;
var propertyName = context.Key.Name;
if (IsTransformRequired(propertyName, modelMetadata, propertyAttributes))
{
modelMetadata.DisplayName = () => SplitCamelCase(propertyName);
}
}
private static string SplitCamelCase(string str)
{
return Regex.Replace(
Regex.Replace(
str,
@"(\P{Ll})(\P{Ll}\p{Ll})",
"$1 $2"
),
@"(\p{Ll})(\P{Ll})",
"$1 $2"
);
}
private static bool IsTransformRequired(string propertyName, DisplayMetadata modelMetadata, IReadOnlyList<object> propertyAttributes)
{
if (!string.IsNullOrEmpty(modelMetadata.SimpleDisplayProperty))
return false;
if (propertyAttributes.OfType<DisplayNameAttribute>().Any())
return false;
if (propertyAttributes.OfType<DisplayAttribute>().Any())
return false;
if (string.IsNullOrEmpty(propertyName))
return false;
return true;
}
}
IsTransformRequired
方法确保您仍然可以在需要时使用装饰属性覆盖提供程序。
通过AddMvcOptions
上的IMvcBuilder
方法在启动时注册提供商:
builder.AddMvcOptions(m => m.ModelMetadataDetailsProviders.Add(new HumanizerMetadataProvider()));
答案 1 :(得分:2)
如果您只关心 标签 ,则可以轻松覆盖 LabelTagHelper 。
[HtmlTargetElement("label", Attributes = "title-case-for")]
public class TitleCaseTagHelper : LabelTagHelper
{
public TitleCaseTagHelper(IHtmlGenerator generator) : base(generator)
{
}
[HtmlAttributeName("title-case-for")]
public new ModelExpression For { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
throw new ArgumentNullException("context");
if (output == null)
throw new ArgumentNullException("output");
string name = For.ModelExplorer.Metadata.DisplayName ?? For.ModelExplorer.Metadata.PropertyName;
name = name.Humanize(LetterCasing.Title);
TagBuilder tagBuilder = this.Generator.GenerateLabel(
this.ViewContext,
this.For.ModelExplorer,
this.For.Name,
name,
(object) null);
if (tagBuilder == null)
return;
output.MergeAttributes(tagBuilder);
if (output.IsContentModified)
return;
TagHelperContent childContentAsync = await output.GetChildContentAsync();
if (childContentAsync.IsEmptyOrWhiteSpace)
output.Content.SetHtmlContent((IHtmlContent) tagBuilder.InnerHtml);
else
output.Content.SetHtmlContent((IHtmlContent) childContentAsync);
}
}
<label title-case-for="RememberMe" class="col-md-2 control-label"></label>
请确保在 _ViewImports.cshtml中放置 使用声明 和 @addTagHelper 强>
@using YourNameSpace.Helpers
@addTagHelper *, YourNameSpace
我使用Humanizer仅限英语的NuGet包 - Humanizer.Core。它比编写我自己的方法更强大。如果你不喜欢开销,你可以使用正则表达式。
答案 2 :(得分:1)
如何使用自定义属性并覆盖DisplayNameAttribute
public class DisplayWithSpace : DisplayNameAttribute
{
public DisplayWithSpace([System.Runtime.CompilerServices.CallerMemberName] string memberName ="")
{
Regex r = new Regex(@"(?!^)(?=[A-Z])");
DisplayNameValue = r.Replace(memberName, " ");
}
}
,您的财产将是
[DisplayWithSpace]
public string FatherName { get; set; }