【问题标题】:HumanizerMetadataProvider implementation not working for Razor Page modelHumanizerMetadataProvider 实现不适用于 Razor 页面模型
【发布时间】:2020-05-18 12:56:41
【问题描述】:

我希望设置一个 ASP.NET Core 应用程序,以便模型中的属性名称以某种方式自动“人性化”(例如,在属性名称中添加空格)。

例如,这是我的 SystemSettings 模型:

public class SystemSettings : IEntityBase
{
    public int Id { get; set; }

    [Display(Description = "Emails sent from system will be sent from this address.")]
    public string EmailFromAddress { get; set; }

    [Display(Description = "Name of the organisation")]
    public string CompanyName { get; set; }

    [Display(Description = "Name of the web application")]
    public string ProductName { get; set; }
}

我的目标是默认情况下自动设置每个属性的显示名称(但可以覆盖)。例如,“EmailFromAddress”属性默认具有“Email From Address”标签)。

为了达到这个目的,我看到了这样一段 sn-p 代码:

public class HumaniserMetadataProvider : 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;
    }
}

在我看到该代码的地方,他们在 Startup.cs 类中启用了它,如下所示:

services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(new HumaniserMetadataProvider());
    });

但是,当我自己尝试使用 Razor 页面时,标签并没有以任何方式进行转换 - 它仍然是“EmailFromAddress”。为什么这行不通?我还尝试将 Razor Page 转换为 MVC 控制器,但这也没有什么不同。

从我的角度来看,这是一个 sn-p,它指定了“SystemSettings”的模型:

<form method="post">
    @Html.EditorFor(x => x.EmailFromAddress)
    <div class="row m-t-md">
        <div class="col-12">
            <button type="submit" class="btn btn-primary">Submit</button>
        </div>
    </div>
</form>

EditorFor 渲染这个字符串模板:

@model string <div class="form-group">
    <label asp-for="@Model" class="m-b-none"></label>
    <span asp-description-for="@Model" class="help-block m-b-none small m-t-none"></span>
    <div class="input-group">
        <input asp-for="@Model" class="form-control" />
        <vc:text-box></vc:text-box>
        <partial name="_ValidationIcon" />
    </div>
    <span asp-validation-for="@Model" class="validation-message"></span> </div>

【问题讨论】:

    标签: asp.net-core


    【解决方案1】:

    问题是因为 HumanizerMetadataProvider 中的这一行:

    if (propertyAttributes.OfType<DisplayAttribute>().Any())
                return false;
    

    我的模型有一个 [Display] 属性,我在其中指定如下描述:

    [Display(Description = "Emails sent from system will be sent from this address.")]
    public string EmailFromAddress { get; set; }
    

    为了解决这个问题,我检查了 Display 属性的“Name”属性的值是 null 还是空。如果是,那么我允许转换。我修改了 HumanizerMetadataProvider 中的代码,如下所示:

    if (propertyAttributes.OfType<DisplayAttribute>().Any())
    {
        var displayName = modelMetadata.DisplayName?.Invoke();
        return string.IsNullOrEmpty(displayName);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-13
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 2022-01-18
      • 2019-04-27
      • 2021-03-07
      • 1970-01-01
      • 2018-03-18
      相关资源
      最近更新 更多