【问题标题】:How to customize Display and Required attributes at run-time in MVC如何在 MVC 运行时自定义 Display 和 Required 属性
【发布时间】:2016-01-12 18:44:16
【问题描述】:

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

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

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 命令中注入,但如果更有意义,可以在其他地方注入。

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

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4 model-view-controller razor displayattribute


    【解决方案1】:

    我找到了这篇文章

    Is it valid to replace DataAnnotationsModelMetadataProvider and manipulate the returned 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:    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-16
      • 2012-12-29
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      相关资源
      最近更新 更多