1

我正在尝试实现一个要求,该要求允许我根据用户角色或其他业务逻辑更改 html 控件的状态。例如,某些用户不应该能够编辑某个模型属性,或者在某些情况下我什至不希望控件呈现到 html DOM。

在 HTML 帮助器中,元数据可以告诉帮助器是否呈现控件,或者它可以使其只读/禁用。我不想在这里重新发明轮子,我只想通过在运行时根据逻辑更改动作过滤器中的元数据来使用已经存在的东西。我不希望这种逻辑出现在我的视图中,如果我不需要的话,我也不想为每个 html 控件创建自定义帮助程序。

我试图做的是创建一个操作过滤器来处理我的业务层中的评估逻辑规则,然后对给定 model.property 的元数据进行更改。

问题是我对元数据的修改似乎并没有出现在视图中。似乎我对操作过滤器中元数据的更改不是通过引用进行的,因此我没有修改用于视图的同一实例?

public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
    var trans = filterContext.Controller.ViewData.ModelMetadata.Properties.Where(e => e.PropertyName == "Transaction").FirstOrDefault();
    trans.DisplayName = "Show FOO!";
}

我究竟做错了什么?

4

2 回答 2

1

您无法更改ModelMetadata.Properties过滤器中的值,事实上您根本无法更改它们。

问题出在内置DataAnnotationsModelMetadataProvider(准​​确地AssociatedMetadataProvider说是GetMetadataForProperties方法)内部ModelMetadata.Properties,即每次迭代它时都会从属性中重新生成。

所以ModelMetadata.Properties集合中的项目是不可变的。

您可以通过调试检查它:

public override void OnResultExecuting(ResultExecutingContext filterContext)
{
     var properties = filterContext.Controller.ViewData.ModelMetadata.Properties
     var trans1 = properties.Where(e => e.PropertyName == "Transaction").First();
     trans1.DisplayName = "Show FOO!";
     var trans2 = properties.Where(e => e.PropertyName == "Transaction").First();
}

trans1和将trans2是不同的实例(您可以检查它们的哈希码),因此trans2显示名称将是原始显示名称而不是“显示 FOO!”。

所以你需要扩展/编写一个新MetadataProvider的来实现你的目标。

于 2012-06-08T17:55:06.380 回答
0

您可以检查用户在视图中的角色并以这种方式进行调整。角色在呈现 html 之前在服务器端进行评估

@if(HttpContext.Current.User.IsInRole("MyRole")) {
   <input type='text' id='txtSomeInput' />
}
于 2012-06-07T17:23:29.977 回答