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(正確にはAssociatedMetadataProviderGetMetadataForPropertiesメソッド)内部にあります。つまり、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異なるインスタンスになるため(ハッシュコードを確認できます)、trans2displaynameは「ShowFOO!」ではなく元のdisplaynameになります。

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 に答える