从自定义AdditionalMetadataAttribute(asp.net mvc 5)访问模型类实例
本文关键字:访问 模型 实例 mvc AdditionalMetadataAttribute 自定义 asp net | 更新日期: 2023-09-27 18:27:13
我有以下情况-我需要编写一个自定义的附加元数据属性,该属性基于另一个属性值(来自同一模型),向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
稍后编辑
考虑到我没有给出太多解释,我还将在这里粘贴一个关于如何在模型类上使用此属性的示例:
/// <summary>
/// Gets or sets the IsAccountCreated
/// </summary>
/// <value>The IsAccountCreated.</value>
[UIHint("FormFieldStringTemplate")]
[ExtendedAdditionalMetadata("IsExternalAccount", "true", "ReadOnly", "true")]
public override Boolean IsAccountCreated { get; set; }
/// <summary>
/// Gets or sets the IsAccountEnabled
/// </summary>
/// <value>The IsAccountEnabled.</value>
[Display(Name = "Este cont activ?")]
[UIHint("FormFieldStringTemplate")]
[ExtendedAdditionalMetadata("IsExternalAccount", "true", "ReadOnly", "true")]
public override Boolean IsAccountEnabled { get; set; }
/// <summary>
/// Gets or sets the IsExternalAccount
/// </summary>
/// <value>The IsExternalAccount.</value>
[Display(Name = "Este cont extern?")]
[UIHint("FormFieldStringTemplate")]
[AdditionalMetadata("ReadOnly", "true")]
public override Boolean IsExternalAccount { get; set; }
稍后&后期编辑
尽管@stephen-muecke给出的响应在当前情况下更加简单和可接受,但出于编程挑战的考虑,我已经寻找了其他选项,并发现了以下可能性:实现自定义DataAnnotationsModelMetadataProvider
类。简单地说,它是有效的,我能够获得模型类实例,但只有当模型类是一个简单的类时,否则就会有很多缺点。例如,如果你有一个model类,并且你在视图中使用它,那么它是可以的,但如果你在另一个类中有一个类(视图模型中的模型),这种方法就不再可用了。
再次感谢你@stephen muecke!
由于您似乎需要访问模型的多个属性,因此该属性应该以class
(AttributeTargets.Class
)为目标并应用于模型,而不是属性。这可能意味着您需要添加另一个属性,该属性是您尝试将其应用到的属性的名称。注意,metadata.ContainerType
只提供type
,而不是此实例,因此您只能获得其属性的默认值。
编辑
如果需要将属性应用于模型中的多个属性,则无法访问OnMetadataCreated
中的容器,因为元数据是从最内部的属性创建的,因此尚未创建模型的元数据。
根据OP的评论,更好的解决方案是创建一个自定义的html助手。例如,根据另一个属性的值生成只读文本框
namespace MyHelpers.Html
{
public static class ReadOnlyHelpers
{
public static MvcHtmlString ReadOnlyTextBoxIf<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> 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<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, bool>> 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)