从自定义AdditionalMetadataAttribute访问模型类实例(asp.net mvc 5)

我有以下情况 – 我需要编写一个自定义的附加元数据属性,该属性基于另一个属性值(来自同一模型),向AdditionalValues字典添加一个值。 现在,我的问题是我无法访问属性类中的模型实例。

[AttributeUsage(AttributeTargets.Property)] public class ExtendedAdditionalMetadataAttribute : Attribute, IMetadataAware { #region Private properties private string extraFieldToCheck { get; set; } private string extraFieldValueToCheck { get; set; } private string fieldToBeAdded { get; set; } private string fieldValueToBeAdded { get; set; } #endregion #region Constructor public ExtendedAdditionalMetadataAttribute(string extraFieldToCheck, string extraFieldValueToCheck, string fieldToBeAdded, string fieldValueToBeAdded) { this.extraFieldToCheck = extraFieldToCheck; this.extraFieldValueToCheck = extraFieldValueToCheck; this.fieldToBeAdded = fieldToBeAdded; this.fieldValueToBeAdded = fieldValueToBeAdded; } #endregion public void OnMetadataCreated(ModelMetadata metadata) { // HOW TO GET THE MODEL CLASS INSTANCE??? // metadata.ContainerType is correct by metadata.Container is null. } } 

从代码注释中可以看出,在OnMetadataCreated中我需要访问Model类实例,但是尽管ContainerType是正确的,但Container属性是NULL。

能否通过给我一个关于这个问题的提示来帮助我?

先感谢您!

Evdin

稍后编辑

考虑到我没有给出太多解释,我还将在此处粘贴一个示例,说明我希望如何在模型类上使用此属性:

 ///  /// Gets or sets the IsAccountCreated ///  /// The IsAccountCreated. [UIHint("FormFieldStringTemplate")] [ExtendedAdditionalMetadata("IsExternalAccount", "true", "ReadOnly", "true")] public override Boolean IsAccountCreated { get; set; } ///  /// Gets or sets the IsAccountEnabled ///  /// The IsAccountEnabled. [Display(Name = "Este cont activ?")] [UIHint("FormFieldStringTemplate")] [ExtendedAdditionalMetadata("IsExternalAccount", "true", "ReadOnly", "true")] public override Boolean IsAccountEnabled { get; set; } ///  /// Gets or sets the IsExternalAccount ///  /// The IsExternalAccount. [Display(Name = "Este cont extern?")] [UIHint("FormFieldStringTemplate")] [AdditionalMetadata("ReadOnly", "true")] public override Boolean IsExternalAccount { get; set; } 

稍后和稍后编辑

虽然@ stephen-muecke给出的响应在当前情况下更简单和可接受,但为了编程挑战,我寻找其他选项,我发现了以下可能性:实现自定义DataAnnotationsModelMetadataProvider类。 用几个简单的单词 – 它可以工作,只有当模型类是一个简单的类时我才能获得模型类实例BUT,否则有许多缺点 – 例如,如果你有一个Model类并且你在视图中使用它那么没关系,但是如果你在另一个类(viewmodel中的模型)中有一个类,那么这种方法就不再可用了。

再次感谢@ stephen-muecke!

由于您似乎需要访问模型的多个属性,因此该属性应该以classAttributeTargets.Class )为目标并应用于模型,而不是属性。 这可能意味着您需要添加另一个属性,该属性是您尝试将其应用于的属性的名称。 注意metadata.ContainerType仅为您提供type ,而不是此实例,因此您只能获取其属性的默认值。

编辑

如果需要将属性应用于模型中的多个属性,则无法访问OnMetadataCreated的容器,因为元数据是从最里面的属性创建的,因此尚未创建模型的元数据。

根据OP的评论,更好的解决方案是创建一个自定义的html帮助器。 例如,生成一个只基于另一个属性的值的文本框

 namespace MyHelpers.Html { public static class ReadOnlyHelpers { public static MvcHtmlString ReadOnlyTextBoxIf(this HtmlHelper helper, Expression> expression, bool isReadOnly) { object attributes = isReadOnly ? new { @readonly = "readonly" } : null; return InputExtensions.TextBoxFor(helper, expression, attributes); } } } 

并在您的视图中使用

 @Html.ReadOnlyTextBoxIf(m => m.SomeTextProperty, Model.SomeBooleanValue) 

创建“只读”复选框有点困难,因为readonly属性对checkbox没有影响。 为了防止用户交互,您需要禁用它,但这意味着值不会回发

 public static MvcHtmlString ReadOnlyCheckBoxIf(this HtmlHelper helper, Expression> expression, bool isReadOnly) { if (isReadOnly) { // If you want to 'visually' render a checkbox (otherwise just render a div with "YES" or "NO") ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); StringBuilder html = new StringBuilder(); // Add a hidden input for postback html.Append(InputExtensions.HiddenFor(helper, expression).ToString()); // Add a visual checkbox without name so it does not post back TagBuilder checkbox = new TagBuilder("input"); checkbox.MergeAttribute("type", "checkbox"); checkbox.MergeAttribute("disabled", "disabled"); if ((bool)metaData.Model) { checkbox.MergeAttribute("checked", "checked"); } html.Append(checkbox.ToString()); return MvcHtmlString.Create(html.ToString()); } else { // return normal checkbox return InputExtensions.CheckBoxFor(helper, expression); } } 

并在您的视图中使用

 @Html.ReadOnlyCheckBoxIf(m => m.IsAccountCreated, Model.IsExternalAccount)