2011-03-26 6 views
1

Html.Editor()을 확장해야하므로 HTML에서 생성 할 수있는 일부 특성을 기반으로합니다. 예 : 사용자가 관리자 다른 경우 생성 된 HTML이 View에 표시되지 않습니다이 경우Extend Html.Editor()

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

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

.

답변

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 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(); 
} 

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

다음이 속성을 사용하는 사용자 정의 메타 데이터 공급자를 작성할 수의 사용자가 다음과 같은 속성을 정의했다고 가정하자

이고 마지막 부분은 문자열 유형 (~/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에는 디스플레이 템플릿도 포함됩니다.

+0

굉장한 구조와 구현! – nttakr

+0

@Darin,이 작업을 수행 할 수 없습니다. 'return metadata' 문에 중단 점을 두는 것으로 모든 것이 훌륭해 보입니다. 메타 데이터에 대한 모든 추가 값과 기타 조정 사항이 있습니다. 그러나 View가로드 될 때까지 ViewModel.ModelMetaData에는 내 CustomProvider MetaData가 포함되어 있지 않습니다. –

+0

@Doug Chamberlain, 당신은'DisplayForAttribute' 속성으로 장식 된 속성을위한 편집기 템플릿 안에서 이것을하고 있습니까? 예제에서와 같이, 기본'String.cshtml' 편집기 템플릿을 오버라이드하고 있습니다. –

0

나는 내 프로젝트에서 같은 것을 가지고 있지만 코드는 작동 중이다.

나는 나의 Object.ascx에서 ModelMetadata 및/또는 PropertyInfo

public static bool IsVisibleForRole(this PropertyInfo property, User c); 

에 대한 확장 방법을 썼습니다 :

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

비록, 귀하의 경우, 당신은 필드를 건너 뛸 수 있지만 삽입 <input type="hidden"> 대신 그러나 이것은 보안 문제 일 수 있습니다. 자세한 내용은 다음을 참조하십시오. http://www.codethinked.com/aspnet-mvc-think-before-you-bind

관련 문제