[英]How to access C# model attribute within EditorFor
我有一个如下模型:
public class CreateStockcheckJobModel
{
[Engineer(true)]
public EngineerModel Engineer { get; set; }
}
我使用Html.EditorFor(m => m.Engineer, "EngineerEditor")
在View<CreateStockcheckJobModel>
渲染Engineer
属性。
如何从局部视图( EngineerEditor.ascx
)中的代码中访问Engineer
属性中的值(在本例中为true
)?
下面是我的编辑器代码
<%@ Control Language="C#" Inherits="ViewUserControl<EngineerModel>" %>
<% if (PropertyImRenderingHasAttributeWithTrueBooleanValue) // What goes here?
{ %>
<p>Render one thing</p>
<% }
else
{ %>
<p>Render another thing</p>
<% } %>
我知道反射,但是我不确定如何使用它,因为属性没有添加到EngineerModel
类,它被添加到CreateStockcheckJobModel
类的Engineer
属性中。 如果我可以从编辑器代码获取我正在渲染的PropertyInfo
,那么我将被排序,但我不知道如何获取该信息。 如果我在CreateStockcheckJobModel
类中列举所有属性的路径,那么如果我有多个EngineerModel
属性(一个可能具有True
属性,另一个可能有False
),我将会遇到问题。
通过在自定义EngineerAttribute
上实现IMetadataAware
接口,可以在ASP.NET MVC 3及更高版本中轻松完成此操作:
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;
}
}
然后在模板内:
<%@ 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>
<% } %>
不幸的是,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;
}
}
您将在Application_Start
中注册以替换默认值:
ModelMetadataProviders.Current = new MyMetadataProvider();
现在,您可以使用ViewData.ModelMetadata.AdditionalValues["IsFoo"]
以与之前显示的方式相同的方式访问模板中的元数据。 显然,你可以在AdditionalValues
属性中放置一个任意复杂的对象,而不仅仅是布尔值。
您也可能会发现以下文章对元数据有用。
注意 :下面是一种可能的方法,但使用接受的答案中描述的IMetadataAware
是一种更好的方法。 如果可以的话,通常最好避免反射。
你只能通过反思来做到这一点。 这是关于如何为方法属性执行此操作的一个很好的示例 。
在属性Engineer
上获取EngineerAttribute
值的代码示例:
PropertyInfo pi = Model.GetType().GetProperty("Engineer");
EngineerAttribute a =
System.Attribute.GetCustomAttribute(pi, typeof(EngineerAttribute));
获取具有[Engineer(true)]
属性的所有属性的代码示例:
var t = Model.GetType();
var engineerProperties =
from p in t.GetProperties()
let ca = System.Attribute.GetCustomAttribute(p, typeof(EngineerAttribute))
where ca != null && ca.BooleanProperty == true
select p;
当您拥有这些属性时,您可以使用EditorFor
的重载,它允许您指定其他视图数据,然后您可以在子视图中使用它们:
Html.EditorFor(m => m.Engineer, new { IsEngineer = isEngineer });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.