如何在EditorFor中访问C#模型属性

Geo*_*ett 5 c# partial-views asp.net-mvc-2

我有一个如下模型:

public class CreateStockcheckJobModel
{
    [Engineer(true)]
    public EngineerModel Engineer { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我呈现Engineer在财产View<CreateStockcheckJobModel>使用Html.EditorFor(m => m.Engineer, "EngineerEditor").

如何从局部视图()中的代码中访问Engineer属性中的值(在本例trueEngineerEditor.ascx)?


下面是我的编辑器代码

<%@ Control Language="C#" Inherits="ViewUserControl<EngineerModel>" %>
<% if (PropertyImRenderingHasAttributeWithTrueBooleanValue) // What goes here?
   { %>
<p>Render one thing</p>
<% }
   else
   { %>
<p>Render another thing</p>
<% } %>
Run Code Online (Sandbox Code Playgroud)

我知道反射,但是我不确定如何使用它,因为属性没有添加到EngineerModel它添加到类的Engineer属性的CreateStockcheckJobModel类中.如果我可以PropertyInfo从编辑器代码中获取我正在渲染的内容,那么我将进行排序,但我不知道如何获取该信息.如果我沿着列举枚举CreateStockcheckJobModel类中所有属性的路线,那么如果我有多个EngineerModel属性(一个可能有属性True,另一个可能有False),我将会遇到问题.

Dar*_*rov 7

这可以通过IMetadataAware在自定义上实现接口在ASP.NET MVC 3及更高版本中轻松完成EngineerAttribute:

public class EngineerAttribute : Attribute, IMetadataAware
{
    public EngineerAttribute(bool isFoo)
    {
        IsFoo = isFoo;
    }

    public bool IsFoo { get; private set; }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["IsFoo"] = IsFoo;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在模板内:

<%@ Control Language="C#" Inherits="ViewUserControl<EngineerModel>" %>
<%
    var isFoo = (bool)ViewData.ModelMetadata.AdditionalValues["IsFoo"];
%>
<% if (isFoo) { %>
    <p>Render one thing</p>
<% } else { %>
    <p>Render another thing</p>
<% } %>
Run Code Online (Sandbox Code Playgroud)

不幸的是,ASP.NET MVC 2中不存在此接口.要实现相同的功能,您可以编写自定义元数据提供程序:

public class MyMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes, 
        Type containerType, 
        Func<object> modelAccessor, 
        Type modelType, 
        string propertyName
    )
    {
        var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        var engineer = attributes.OfType<EngineerAttribute>().FirstOrDefault();
        if (engineer != null)
        {
            metadata.AdditionalValues["IsFoo"] = engineer.IsFoo;
        }
        return metadata;
    }
}
Run Code Online (Sandbox Code Playgroud)

你将在你的注册,Application_Start以取代默认的:

ModelMetadataProviders.Current = new MyMetadataProvider();
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用与之前显示的方式相同的方式在模板中访问此元数据ViewData.ModelMetadata.AdditionalValues["IsFoo"].显然你可以在AdditionalValues属性中放置一个任意复杂的对象,而不仅仅是布尔值.

您也可能会发现以下文章对元数据有用.