4

我想在剃刀视图中有一个带有动态标签的模型,该模型在运行时设置,但基于使用字符串格式的资源文件中的字符串。

假设我有一个具有单个属性的简单模型

public class Simple
{
    [Display(ResourceType = (typeof(Global)), Name = "UI_Property1")]
    [Required(ErrorMessageResourceType = (typeof(Global)), ErrorMessageResourceName = "ERROR_Required")]
    [StringLength(40, ErrorMessageResourceType = (typeof(Global)), ErrorMessageResourceName = "ERROR_MaxLength")]
    public string Property1{ get; set; }
}

并且资源文件有以下字符串

UI_Property1       {0}
ERROR_Required     Field {0} is required.
ERROR_MaxLength    Maximum length of {0} is {1}

我想在剃刀视图中做这样的事情

@Html.LabelFor(m => m.Property1, "xyz", new { @class = "control-label col-sm-4" })

结果视图会将字段标签显示为“xyz”,并且值“xyz”也将显示在从服务器模型验证返回的验证消息中。

我一直在寻找各种方法来做到这一点,但没有运气。我已经调查过重写 DisplayAttribute 但这是一个密封类。

我还查看了覆盖 DisplayName 属性,但这并没有通过所需的验证消息正确获取。另外,我不确定如何将动态文本注入到我认为需要在属性构造函数中完成的属性中。

我也看过编写自定义 DataAnnotationsModelMetadataProvider 但看不到使用它来实现我想要的方法。这可能是由于我缺乏编码技能。

'xyz' 字符串将来自 web.config 文件中的设置,不需要在 LabelFor 命令中注入,但如果更有意义,可以在其他地方注入。

如果有人能告诉我如何实现这一目标,那就太好了。

4

1 回答 1

0

我找到了这篇文章

替换DataAnnotationsModelMetadataProvider并操作返回的ModelMetadata是否有效

这使我找到了如下解决方案:

我在我的网络配置中添加了一个自定义部分

  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="labelTranslations" type="AttributeTesting.Config.LabelTranslatorSection" />
    ... other sections here
  </configSections>

  <labelTranslations>
    <labels>
      <add label=":Customer:" translateTo="Customer Name" />
      <add label=":Portfolio:" translateTo="Portfolio Name" />
      <add label=":Site:" translateTo="Site Name" />
    </labels>
  </labelTranslations>

处理自定义部分的类加载要翻译的标签

public class LabelElement : ConfigurationElement
{
    private const string LABEL = "label";
    private const string TRANSLATE_TO = "translateTo";

    [ConfigurationProperty(LABEL, IsKey = true, IsRequired = true)]
    public string Label
    {
        get { return (string)this[LABEL]; }
        set { this[LABEL] = value; }
    }

    [ConfigurationProperty(TRANSLATE_TO, IsRequired = true)]
    public string TranslateTo
    {
        get { return (string)this[TRANSLATE_TO]; }
        set { this[TRANSLATE_TO] = value; }
    }

}

[ConfigurationCollection(typeof(LabelElement))]
public class LabelElementCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new LabelElement();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((LabelElement)element).Label;
    }

    public LabelElement this[string key]
    {
        get
        {
            return this.OfType<LabelElement>().FirstOrDefault(item => item.Label == key);
        }
    }
}

public class LabelTranslatorSection : ConfigurationSection
{
    private const string LABELS = "labels";

    [ConfigurationProperty(LABELS, IsDefaultCollection = true)]
    public LabelElementCollection Labels
    {
        get { return (LabelElementCollection)this[LABELS]; }
        set { this[LABELS] = value; }
    }
}

然后,翻译器使用自定义部分将给定标签翻译成翻译版本(如果存在),否则返回标签

public static class Translator
{
    private readonly static LabelTranslatorSection config =
        ConfigurationManager.GetSection("labelTranslations") as LabelTranslatorSection;

    public static string Translate(string label)
    {
        return config.Labels[label] != null ? config.Labels[label].TranslateTo : label;
    }
}

然后我编写了一个自定义元数据提供程序,它根据翻译版本修改显示名称

public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
                             IEnumerable<Attribute> attributes,
                             Type containerType,
                             Func<object> modelAccessor,
                             Type modelType,
                             string propertyName)
    {

        // Call the base method and obtain a metadata object.
        var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);

        if (containerType != null)
        {
            // Obtain informations to query the translator.
            //var objectName = containerType.FullName;
            var displayName = metadata.GetDisplayName();

            // Update the metadata from the translator
            metadata.DisplayName = Translator.Translate(displayName);
        }

        return metadata;
    }
}

之后一切正常,标签和验证消息都使用了翻译版本。我使用了标准的 LabelFor 助手,没有做任何修改。

资源文件看起来像这样

ERROR_MaxLength   {0} can be no more than {1} characters long   
ERROR_Required    {0} is a required field   
UI_CustomerName   :Customer:    
UI_PortfolioName  :Portfolio:   
UI_SiteName       :Site:    
于 2015-10-19T12:28:30.450 回答