Asp.net mvc 3を使用してWebアプリを開発していますが、非同期アクション(ajax経由)にPOST 。検証は正常に機能しますが、検証ツールがエラーを返したときに、ビューに表示するためにどのように返すことができるかわかりません(POSTはajaxによって作成されたため)。
私の行動は次のようなものです。
[HttpPost]
public ActionResult SaveCustomer(CustomerViewModel input) {
if (!ModelState.IsValid) { // <-- business validation
return Json(new { success = false, errors = ???});
}
// persist
return Json(new { success = true });
}
ビューでjqueryvalidateを使用してこのエラーを表示するにはどうすればよいですか?サンプルにコードを投稿することが可能であれば...私はそれを感謝します!
みんなありがとう!
エラーの場合にJSONを送信する代わりに、フォームをパーシャル内に配置し、エラーの場合にコントローラーアクションがこのパーシャルを返すようにします。 JSONの問題は、実際にはLINQを使用してModelStateからエラーをフェッチできることですが、ビューにエラーを表示するのはPITAである可能性があります。
そう:
<div id="myform">
@Html.Partial("_MyForm")
</div>
そして内部_MyForm.cshtml
:
@model CustomerViewModel
@using (Html.BeginForm())
{
@Html.EditorFor(x => x.Foo)
@Html.ValidationMessageFor(x => x.Foo)
<br />
@Html.EditorFor(x => x.Bar)
@Html.ValidationMessageFor(x => x.Bar)
<br />
<input type="submit" value="OK" />
}
コントローラーのアクションは次のようになります。
[HttpPost]
public ActionResult SaveCustomer(CustomerViewModel model)
{
if (!ModelState.IsValid)
{
return PartialView("_MyForm", model);
}
return Json(new { success = true });
}
最後のステップは、このフォームをAJAX化することです。これは、別のjavascriptファイルで実行できます。
$(function () {
$('#myform').delegate('form', 'submit', function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result.success) {
// We have a JSON object in case of success
alert('success');
} else {
// We have the partial with errors in case of failure
// so all we have to do is update the DOM
$('#myform').html(result);
}
}
});
return false;
});
});
ModelStateエラーを返す可能性があります。これはテストされていませんが、このようなものは機能するはずです。
return Json(new
{
success = false,
errors = ModelState.Keys.SelectMany(k => ModelState[k].Errors)
.Select(m => m.ErrorMessage).ToArray()
});
編集:ビューにエラーを表示するには、成功したかどうかを確認し、成功しなかった場合は、エラーのリストを繰り返し処理して、エラーが表示されている場所に配置します。
if(!result.success) {
for(var error in result.errors) {
$('#errorMessages').append(error + '<br />');
}
}
ほとんどのプロジェクトでDarinの回答を好みますが、コンシューマーが必ずしも独自のアプリケーションであるとは限りません。その場合、コンシューマーが必要に応じてエラーを表示できるため、エラーのリストを返す方が適切です。
個々のプロパティのModelStateエラーを表すクラスを作成します。
public class ValidationError
{
public string PropertyName = "";
public string[] ErrorList = null;
}
ModelStateに基づいてValidationErrorsのリストを返すメソッドを作成します
public IEnumerable<ValidationError> GetModelStateErrors(ModelStateDictionary modelState)
{
var errors = (from m in modelState
where m.Value.Errors.Count() > 0
select
new ValidationError
{
PropertyName = m.Key,
ErrorList = (from msg in m.Value.Errors
select msg.ErrorMessage).ToArray()
})
.AsEnumerable();
return errors;
}
次に、コントローラーでPostメソッドを実行します。
if (!ModelState.IsValid)
{
return Json(new
{
errors = true,
errorList = GetModelStateErrors(ModelState)
}, JsonRequestBehavior.AllowGet);
}
上記で返されたエラーリストをループするJS関数を作成できます
$.ajax({
cache: false,
async: true,
type: "POST",
url: form.attr('action'),
data: form.serialize(),
success: function (data) {
if (data.errors) {
displayValidationErrors(data.errorList);
}
},
error: function (result) {
console.log("Error");
}
});
function displayValidationErrors(errors) {
$.each(errors, function (idx, validationError) {
$("span[data-valmsg-for='" + validationError.PropertyName + "']").text(validationError. ErrorList[0]);
});
}
上記の例では、「ErrorList」から最初のエラーメッセージのみを取得しています。追加のループを作成して、すべてのメッセージを取得し、検証スパンに追加できます。
このコードを試してください。これはあなたの問題に対する簡単な解決策です。すべてのモデル状態エラーを1つの文字列に結合します。
[HttpPost]
public ActionResult SaveCustomer(CustomerViewModel input) {
if (!ModelState.IsValid) { // <-- business validation
return Json(new { success = false, errors = string.Join("; ", ModelState.Values
.SelectMany(x => x.Errors)
.Select(x => x.ErrorMessage));});
}
// persist
return Json(new { success = true });
}