2016-08-09 4 views
0

그래서 흥미로운 문제점을 발견했습니다. 오류 :asp.net mvc 모델 상태 오류 키

[{ 
Key = FirstApplicant.Firstname 
Value = ["First name is required field"] 
}, 
{ 
Key = FirstApplicant.Surname 
Value = ["Surname name is required field"] 
}]. 
을 모두 괜찮습니다, 나는 모델의 상태를 확인하고 오류가 모델에있을 때 나는 이런 식으로 뭔가를 얻을

public class ApplicantModel 
{ 
    [Display(Name = "Firstname", ResourceType = typeof(Resources))] 
    [MaxLength(50, ErrorMessageResourceName = "FirstName", ErrorMessageResourceType = typeof(Validations), ErrorMessage = null)] 
    [Required(ErrorMessageResourceName = "FirstName", ErrorMessageResourceType = typeof(Validations), ErrorMessage = null)] 
    public string Firstname { get; set; } 

    [Display(Name = "Surname", ResourceType = typeof(Resources))] 
    [MaxLength(50, ErrorMessageResourceName = "Surname", ErrorMessageResourceType = typeof(Validations), ErrorMessage = null)] 
    [Required(ErrorMessageResourceName = "Surname", ErrorMessageResourceType = typeof(Validations), ErrorMessage = null)] 
    public string Surname { get; set; } 
} 

: 나는이 같은 모델을 가지고

그것도 좋습니다.

편집 : 이것은 JSON 개체로 시각화 된 C# ModelState 개체입니다. 실제 객체는 다음과 같습니다 :

ModelState 
{System.Web.Mvc.ModelStateDictionary} 
    Count: 2 
    IsReadOnly: false 
    IsValid: false 
    Keys: Count = 2 
    Values: Count = 2 
    Results View: Expanding the Results View will enumerate the IEnumerable 

그러나 내 질문은. 어떻게 든 열쇠를 바꿀 수 있습니까? 그 열쇠는 객체의 이름으로 생성 된 다음 그 객체의 이름 속성으로 생성된다는 것을 알고 있습니다. 그렇다면이 기본 동작을 변경하는 방법은 무엇입니까? 또는 객체의 이름을 변경해야합니까?

Edit2가이 :

내가 여기 달성하기 위해 시도하고 나는 C#을 뷰 모델을 가지고 뷰 모델을 녹아웃 것입니다. 서버 측 유효성 검사를 수행 할 때이 일련의 키와 값의 사전을 가져와 직렬화하여 클라이언트에 보냅니다.

var errors = @Html.Raw(Json.Encode(Model.Errors)); 
     function showErrors(serializedErrors) { 
      var errors = JSON.parse(serializedErrors); 
      for (var i = 0; i < errors.length; i++) { 
       var error = errors[i]; 
       var key = error.Key; 
       var property = eval("masterModel." + key); 
       property.setError(error.Value.ErrorMessage); 
       property.isModified(true); 
      } 
     } 
     showErrors(errors); 

을 그리고보기 모델 속성 이름은 서버와 클라이언트에 일치하는 경우이 잘 작동 것 : 그리고 나는 클라이언트에에이 함수를 호출합니다. 하지만 예를 들어 서버 쪽에서는 FirstApplicant.FirstName이 있고 클라이언트 쪽에서는 ApplicantOne.firstname입니다. 도움과 의견을 모두 주셔서 감사합니다. 나는 이번에 내 문제를 더 자세히 설명하기를 희망한다.

+0

코드의 부분이 JSON 응답을 만드는 :

그리고 여기가에 대한 시험이다? – Shyju

+0

JSON 코드가 아닙니다. 죄송합니다. 더 자세히 설명해야합니다. ModelState Keys/Values ​​객체입니다. 그러나 JSON 객체로 시각화하는 것이 더 쉬웠습니다. 실제 개체는 다음과 같습니다. ModelState {System.Web.Mvc.ModelStateDictionary} 수 : 22 isReadOnly의 : 거짓 IsValid : 거짓 키 : = 22 개 결과보기 카운트 : 결과보기를 확장하면 IEnumerable을 – xszaboj

+0

는 당신이 'FirstApplicant.Firstname'을 변경하는 뜻 열거한다 = 22 개 값을 카운트 예를 들어 '이름'? – Monah

답변

0

결국이 문제에 대한 해결책을 찾았습니다. 그것은 약간 복잡하지만 작동합니다.

먼저 속성을 만들었습니다. 이 속성은 또한 IMetadataAware

다음 단계를 구현하는

public class ClientNameAttribute : Attribute, IMetadataAware 
{ 
    public ClientNameAttribute(string name) 
    { 
     this.Name = name; 
    } 

    public string Name { get; set; } 

    public void OnMetadataCreated(ModelMetadata metadata) 
    { 
     metadata.AdditionalValues["ClientName"] = this.Name; 
    } 
} 

주의 HTML 헬퍼를 만드는, 그래서 내가보기에이를 호출 할 수 있습니다.

public static class HtmlHelperExtensions 
{ 
    public static string CustomModelState<T>(this HtmlHelper<T> helper) 
    { 
     var errors = helper.ViewData.ModelState.Select(
      m => new { Key = GenerateClientName(m.Key, helper), Value = m.Value.Errors.FirstOrDefault() }).Where(e=> e.Value != null); 

     return Json.Encode(errors); 
    } 

    private static string GenerateClientName<T>(string key, HtmlHelper<T> helper) 
    { 
     StringBuilder builder = new StringBuilder(); 
     int periodIndex = -1; 
     do 
     { 
      periodIndex = key.IndexOf('.', periodIndex + 1); 
      string part = key.Substring(0, periodIndex==-1 ? key.Length : periodIndex); 
      var partMetadata = ModelMetadata.FromStringExpression(part, helper.ViewData); 

      object clientName; 
      if (builder.Length > 0) 
      { 
       builder.Append('.'); 
      } 

      if (partMetadata.AdditionalValues.TryGetValue("ClientName", out clientName)) 
      { 
       builder.Append(clientName); 
      } 
      else 
      { 
       builder.Append(partMetadata.PropertyName); 
      } 
     } 
     while (periodIndex != -1); 

     return builder.ToString(); 
    } 
} 

CustomModelState은 뷰에서 호출하는 방법입니다. 이 같은

는 :

var errors = @Html.Raw(Html.CustomModelState()); 
if (errors.length > 0) { 
    showErrors("masterModel",errors); 
} 

이 속성의 사용자 정의 이름으로 당신에게 잘 형식의 오류를 줄 것이다.

public class TestModel 
{ 
    [Required] 
    public string Normal { get; set; } 
    [ClientName("Other")] 
    [Required] 
    public string Changed { get; set; } 

    [ClientName("Complicated")] 
    public TestModelTwo TestModelTwo { get; set; } 
} 

public class TestModelTwo 
{ 
    public string PropertyOne { get; set; } 

    [ClientName("Two")] 
    public string PropertyTwo{ get; set; } 
} 

[TestClass] 
public class HtmlHelperExtensionsTests 
{ 
    [TestMethod] 
    public void CustomModelStateTests() 
    { 
     var model = new TestModel(); 
     var page = new ViewPage(); 
     page.ViewData.Model = model; 
     page.ViewData.ModelState.AddModelError("Normal", "Error1"); 
     page.ViewData.ModelState.AddModelError("Changed", "Error2"); 
     HtmlHelper<TestModel> helper = new HtmlHelper<TestModel>(new ViewContext(), page); 
     var custom = helper.CustomModelState(); 
     string expectedResult = 
      "[{\"Key\":\"Normal\",\"Value\":{\"Exception\":null,\"ErrorMessage\":\"Error1\"}},{\"Key\":\"Other\",\"Value\":{\"Exception\":null,\"ErrorMessage\":\"Error2\"}}]"; 
     Assert.AreEqual(expectedResult, custom); 
    } 


    [TestMethod] 
    public void CustomModelStateTests_ObjectProperty_With_ClientName() 
    { 
     var model = new TestModel(); 
     model.TestModelTwo = new TestModelTwo(); 
     var page = new ViewPage(); 
     page.ViewData.Model = model; 
     page.ViewData.ModelState.AddModelError("TestModelTwo.PropertyOne", "Error1"); 
     page.ViewData.ModelState.AddModelError("TestModelTwo.PropertyTwo", "Error2"); 
     HtmlHelper<TestModel> helper = new HtmlHelper<TestModel>(new ViewContext(), page); 
     var custom = helper.CustomModelState(); 
     string expectedResult = 
      "[{\"Key\":\"Complicated.PropertyOne\",\"Value\":{\"Exception\":null,\"ErrorMessage\":\"Error1\"}},{\"Key\":\"Complicated.Two\",\"Value\":{\"Exception\":null,\"ErrorMessage\":\"Error2\"}}]"; 
     Assert.AreEqual(expectedResult, custom); 
    } 
}