サンプル実装があります。
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には、表示テンプレートも含まれています。
素晴らしい構造と実装! – nttakr
@ダーリン、私はこれを動作させることはできません。 'return metadata'ステートメントにブレークポイントを置くことで、すべてが素晴らしいように見えます。メタデータへの私の付加価値やその他の調整はすべてそこにあります。しかし、Viewが何らかの方法でロードされる頃に、ViewModel.ModelMetaDataには私のCustomProviderメタデータが含まれていませんか? –
@Doug Chamberlain、あなたは 'DisplayForAttribute'属性で修飾されたプロパティのエディタテンプレートの中でこれをしていますか?私の例では、デフォルトの 'String.cshtml'エディタテンプレートをオーバーライドしています。 –