2016-08-09 22 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#のビューモデルとノックアウトのViewModelを持っているということです。あなたがサーバ側のバリデーションを行うときには、このシリアライズしてクライアントに送るキーと値の辞書を取得します。 そして私は、クライアント上でそれにこの関数を呼び出す:

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の カウント値:= 22の 結果ビューをカウント:ビューはあなたが 'FirstApplicant.Firstname' を変更する意味ですかIEnumerableを – xszaboj

+0

を列挙する結果を拡大例えば「名前」? – 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); 
    } 
} 
関連する問題