【问题标题】:Is there a way to reuse custom data annotation code across editor templates?有没有办法跨编辑器模板重用自定义数据注释代码?
【发布时间】:2016-02-23 02:04:35
【问题描述】:

我有几个自定义数据注释可用于编辑 ViewModel。

因为它们可以应用于任何类型的表单控件,所以我在每个EditorTemplate 中都对它们进行了测试。

任何人都可以推荐一种在 MVC 中重用这样的共享视图代码的方法吗?

我正在考虑使用 HtmlHelper 或 AppCode/Helper 类。不知道哪个最好,我对两者都有点新手。

@{
    var htmlAttributesFromView = ViewData["htmlAttributes"] ?? new { };
    var htmlAttributes = Html.MergeHtmlAttributes(htmlAttributesFromView, new { @class = "form-control" });


    bool isDisplayInfoOnIconClickAttribute = false;
    string title = "";
    string description = "";

    var infoOnClickAttributes = (ViewData.ModelMetadata).ContainerType.GetProperty(ViewData.ModelMetadata.PropertyName).GetCustomAttributes(typeof(DisplayInfoOnIconClickAttribute), false);
    if (infoOnClickAttributes.Length > 0)
    {
        DisplayInfoOnIconClickAttribute attribute = infoOnClickAttributes[0] as DisplayInfoOnIconClickAttribute;
        isDisplayInfoOnIconClickAttribute = true;
        title = attribute.Title;
        description = attribute.Description;
    }


    bool isDisplayTextInfoAttribute = false;
    string info = "";

    var textInfoAttributes = (ViewData.ModelMetadata).ContainerType.GetProperty(ViewData.ModelMetadata.PropertyName).GetCustomAttributes(typeof(DisplayTextInfoAttribute), false);
    if (textInfoAttributes.Length > 0)
    {
        DisplayTextInfoAttribute attribute = textInfoAttributes[0] as DisplayTextInfoAttribute;
        isDisplayTextInfoAttribute = true;
        info = attribute.Info;
    }
}



<div class="form-group">
    @Html.LabelFor(model => model, htmlAttributes: new { @class = "control-label col-md-3 text-right-md" })
    <div class="col-md-8">

        @Html.TextBoxFor(model => model, htmlAttributes)
        @Html.ValidationMessageFor(model => model)
    </div>
    <a class="infoonclick col-md-1" title="@Html.DisplayNameFor(model => model)" data-content="@Html.DescriptionFor(model => model)">
        <span class="fa fa-info-circle"></span>
    </a>
</div>

【问题讨论】:

  • 要放入 EditorTemplate 的代码非常多,而且有点不清楚 isDisplayInfoOnIconClickAttributetitledescription 等所有变量的用途 - 你不要似乎从来没有使用过它们。通常,如果您想基于属性生成一些 html,则该属性会实现 IMetadataAware,它将值添加到 ModelMetadata.AdditionalValues,然后您创建自己的 HtmlHelper 扩展方法来输出 html。
  • 太棒了,谢谢。这听起来更像。我需要在IMetadataAware.OnMetadataCreated() 中输入任何内容还是可以将其留空?你有没有机会提供一个简短的例子来说明我如何将ModelMetadata.AdditionalValues 变成HtmlHelper?这将定义为 anwser :)
  • 它有点不清楚你想要实现什么,但refer this answer 是一个使用实现IMetadataAware 的属性的示例。然后是根据链接创建HtmlHelper 扩展方法,还是只是读取EditorTemplate 中的ViewData.ModelMetadata.AdditionalProperties 值实际上取决于其他因素。
  • 完美,非常感谢。我添加了一个修改后的代码示例,希望现在更清楚了。代码现在已经被简化了,我认为HtmlHelper 会有点矫枉过正。
  • 建议您将您的编辑移动到一个自我回答中并接受它,以便您可以关闭它。

标签: asp.net-mvc data-annotations mvc-editor-templates


【解决方案1】:

感谢 Stephens 的建议,我整理了一个修改后的代码提议。

我已经避免使用HtmlHelper,因为它似乎对这个要求有点过分了。

型号

public class Car : DbEntity, IDbEntity
{
    public virtual string Model { get; set; }

    [DisplayTextInfo("E.g. pink, yellow or green. For more colours please <a href='http://hslpicker.com/'>click here</a>.")]
    public virtual string Colour { get; set; }
}   

数据注释

public class DisplayTextInfoAttribute : Attribute, IMetadataAware
{
    public DisplayTextInfoAttribute(string info)
    {
        Info = info;
    }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        if (Info != null)
        {
            metadata.AdditionalValues["DisplayTextInfo"] = Info;
        }
    }
    public string Info { get; set; }
}

编辑器模板

<div class="form-group">
    @Html.LabelFor(model => model)

    @Html.TextBoxFor(model => model, htmlAttributes)
    @Html.ValidationMessageFor(model => model)

    @if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("DisplayTextInfo"))
    {
        <p class="help-block">@Html.Raw(ViewData.ModelMetadata.AdditionalValues["DisplayTextInfo"].ToString())</p>
    }
</div> 

【讨论】:

  • 这么多神奇的字符串!此外,如果您使用 MvcHtmlString 而不是字符串作为 Info,那么您就不必使用 Html.Raw()。
  • 谢谢埃里克。我会改变它。你会如何建议我减少魔术字符串的数量?据我所知,您不能在数据注释内容中使用变量。我想我可以将DisplayTextInfo 键移到AppSetting 中。我错过了什么……?
  • 一般来说,你有两个不同的源代码源,它们使用一个特殊的字符串,可能会输入错误等等。如果我必须使用魔法字符串,我更喜欢放一个公共常量(在这种情况下)在 DisplayTextInfoAttribute 上,例如 public const string Key = "DisplayTextInfo" 然后引用 DisplayTextInfoAttribute.Key 而不是实际的字符串。
猜你喜欢
  • 2013-11-13
  • 1970-01-01
  • 2020-02-14
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
  • 1970-01-01
  • 2011-08-02
相关资源
最近更新 更多