扩展Html.Editor()

时间:2011-03-26 14:26:57

标签: c# asp.net-mvc-3

我需要扩展Html.Editor(),以便根据模型中的某些属性生成HTML。例如:

public class Person
{
    public string Name { get; set; }

    [DisplayFor(Role.Admin)]
    public string Surname { get; set; }
}

在这种情况下,如果用户与admin不同,生成的HTML将不会显示在View中。

2 个答案:

答案 0 :(得分:2)

这是一个示例实现。假设您已定义以下属性:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class DisplayForAttribute : Attribute
{
    public DisplayForAttribute(string role)
    {
        Role = role;
    }
    public string Role { get; private set; }
}

接下来,您可以编写一个使用此属性的自定义元数据提供程序:

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 displayFor = attributes.OfType<DisplayForAttribute>().FirstOrDefault();
        if (displayFor != null)
        {
            metadata.AdditionalValues.Add("RequiredRole", displayFor.Role);
        }
        return metadata;
    }
}

将在Application_Start注册:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    ModelMetadataProviders.Current = new MyMetadataProvider();
}

最后一部分是为String类型(~/Views/Shared/EditorTemplates/String.cshtml)编写自定义编辑器模板:

@{
    var visible = false;
    if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("RequiredRole"))
    {
        var role = (string)ViewData.ModelMetadata.AdditionalValues["RequiredRole"];
        visible = User.IsInRole(role);
    }
}
@if (visible)
{
    @Html.TextBox(
        "", 
        ViewData.TemplateInfo.FormattedModelValue,
        new { @class = "text-box single-line" }
    )
}

最后使用属性:

public class MyViewModel
{
    [DisplayFor("Admin")]
    public string Name { get; set; }
}

并在视图中:

@using (Html.BeginForm())
{
    @Html.EditorFor(model => model.Name)
    <input type="submit" value="OK" />
}

显然这仅涵盖了字符串编辑器模板,但该示例可以轻松扩展到其他default templates,包括显示模板。

答案 1 :(得分:0)

我的项目中有相同的内容,但代码正在运行。

我为ModelMetadata或/和PropertyInfo

编写了一个扩展方法
public static bool IsVisibleForRole( this PropertyInfo property, User c);

在我的Object.ascx中:

for ( var field in fields ) {
     if(!field.IsVisibleForRole(this.CurrentUser())) continue;
     //...
}

但是,在您的情况下,您可能不会跳过该字段,而是插入<input type="hidden">。但这可能是安全问题。有关详细信息,请查看:http://www.codethinked.com/aspnet-mvc-think-before-you-bind