すべてのModelStateエラーメッセージのリストを取得するにはどうすればよいですか?すべてのキーを取得するためにこのコードを見つけました:( ModelStateエラーのあるキーのリストを返す )
var errorKeys = (from item in ModelState
where item.Value.Errors.Any()
select item.Key).ToList();
しかし、どのようにエラーメッセージをIListまたはIQueryableとして取得できますか?
私は行くことができました:
foreach (var key in errorKeys)
{
string msg = ModelState[error].Errors[0].ErrorMessage;
errorList.Add(msg);
}
しかし、それは手動でそれをしています-確かにLINQを使用してそれを行う方法はありますか? .ErrorMessageプロパティはチェーンをはるかに下回っているため、LINQの記述方法がわかりません...
select
句の中にanythingを入れることができます:
var errorList = (from item in ModelState
where item.Value.Errors.Any()
select item.Value.Errors[0].ErrorMessage).ToList();
[〜#〜] edit [〜#〜]:次のようにfrom
句を追加することで、複数のエラーを個別のリスト項目に抽出できます。
var errorList = (from item in ModelState.Values
from error in item.Errors
select error.ErrorMessage).ToList();
または:
var errorList = ModelState.Values.SelectMany(m => m.Errors)
.Select(e => e.ErrorMessage)
.ToList();
2nd 編集:Dictionary<string, string[]>
を探しています:
var errorList = ModelState.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
);
すべての要素をまとめた完全な実装を次に示します。
最初に拡張メソッドを作成します。
public static class ModelStateHelper
{
public static IEnumerable Errors(this ModelStateDictionary modelState)
{
if (!modelState.IsValid)
{
return modelState.ToDictionary(kvp => kvp.Key,
kvp => kvp.Value.Errors
.Select(e => e.ErrorMessage).ToArray())
.Where(m => m.Value.Any());
}
return null;
}
}
次に、その拡張メソッドを呼び出し、コントローラーアクション(存在する場合)からエラーをjsonとして返します。
if (!ModelState.IsValid)
{
return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet);
}
そして最後に、これらのエラーをクライアント側で表示します(jquery.validationスタイルで、他のスタイルに簡単に変更できます)
function DisplayErrors(errors) {
for (var i = 0; i < errors.length; i++) {
$("<label for='" + errors[i].Key + "' class='error'></label>")
.html(errors[i].Value[0]).appendTo($("input#" + errors[i].Key).parent());
}
}
ここでHashtable
を使用するのが好きなので、プロパティをキーとして、エラーを値として文字列配列の形式でJSONオブジェクトを取得します。
var errors = new Hashtable();
foreach (var pair in ModelState)
{
if (pair.Value.Errors.Count > 0)
{
errors[pair.Key] = pair.Value.Errors.Select(error => error.ErrorMessage).ToList();
}
}
return Json(new { success = false, errors });
これにより、次の応答が得られます。
{
"success":false,
"errors":{
"Phone":[
"The Phone field is required."
]
}
}
これを行うには、すべてが機能するさまざまな方法がたくさんあります。ここで私はそれをしています...
if (ModelState.IsValid)
{
return Json("Success");
}
else
{
return Json(ModelState.Values.SelectMany(x => x.Errors));
}
@JKそれは私を大いに助けましたが、なぜそうではありません:
public class ErrorDetail {
public string fieldName = "";
public string[] messageList = null;
}
if (!modelState.IsValid)
{
var errorListAux = (from m in modelState
where m.Value.Errors.Count() > 0
select
new ErrorDetail
{
fieldName = m.Key,
errorList = (from msg in m.Value.Errors
select msg.ErrorMessage).ToArray()
})
.AsEnumerable()
.ToDictionary(v => v.fieldName, v => v);
return errorListAux;
}
これを行う最も簡単な方法は、ModelState自体でBadRequest
を返すことです。
PUT
の例:
[HttpPut]
public async Task<IHttpActionResult> UpdateAsync(Update update)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// perform the update
return StatusCode(HttpStatusCode.NoContent);
}
たとえば、データ注釈を使用する場合Update
クラスのこのような携帯電話番号:
public class Update {
[StringLength(22, MinimumLength = 8)]
[RegularExpression(@"^\d{8}$|^00\d{6,20}$|^\+\d{6,20}$")]
public string MobileNumber { get; set; }
}
これにより、無効なリクエストで次が返されます。
{
"Message": "The request is invalid.",
"ModelState": {
"update.MobileNumber": [
"The field MobileNumber must match the regular expression '^\\d{8}$|^00\\d{6,20}$|^\\+\\d{6,20}$'.",
"The field MobileNumber must be a string with a minimum length of 8 and a maximum length of 22."
]
}
}
System.Web.Http.Results.OkNegotiatedContentResultを見てください。
投げたものはすべてJSONに変換します。
だから私はこれをやった
var errorList = ModelState.ToDictionary(kvp => kvp.Key.Replace("model.", ""), kvp => kvp.Value.Errors[0].ErrorMessage);
return Ok(errorList);
その結果:
{
"Email":"The Email field is not a valid e-mail address."
}
各フィールドに複数のエラーがあるときに何が起こるかをまだ確認していませんが、ポイントはOkNegoriatedContentResultが素晴らしいことです!
@SLaksからlinq/lambdaアイデアを得ました
組み込みの機能を使用して簡単な方法でこれを達成する
[HttpPost]
public IActionResult Post([FromBody]CreateDoctorInput createDoctorInput) {
if (!ModelState.IsValid) {
return BadRequest(ModelState);
}
//do something
}
ToDictionaryは、System.Web.Extensions dllにパッケージ化されたSystem.LinqにあるEnumerable拡張機能です http://msdn.Microsoft.com/en-us/library/system.linq.enumerable.todictionary.aspx =。私にとって完全なクラスは次のようになります。
using System.Collections;
using System.Web.Mvc;
using System.Linq;
namespace MyNamespace
{
public static class ModelStateExtensions
{
public static IEnumerable Errors(this ModelStateDictionary modelState)
{
if (!modelState.IsValid)
{
return modelState.ToDictionary(kvp => kvp.Key,
kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()).Where(m => m.Value.Count() > 0);
}
return null;
}
}
}
元のModelState
オブジェクトをクライアントに返してから、jQueryを使用して値を読み取ってください。私にはそれははるかに単純に見え、共通のデータ構造(.netのModelState
)を使用します
ModelState
をJsonとして返すには、Jsonクラスコンストラクターに渡します(任意のオブジェクトで動作します)
C#:
return Json(ModelState);
js:
var message = "";
if (e.response.length > 0) {
$.each(e.response, function(i, fieldItem) {
$.each(fieldItem.Value.Errors, function(j, errItem) {
message += errItem.ErrorMessage;
});
message += "\n";
});
alert(message);
}
IEnumerableを返すのではなく、戻り値の型によるバリエーション
public static class ModelStateHelper
{
public static IEnumerable<KeyValuePair<string, string[]>> Errors(this ModelStateDictionary modelState)
{
if (!modelState.IsValid)
{
return modelState
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray())
.Where(m => m.Value.Any());
}
return null;
}
}
セパレーター「」でストリングを返す拡張機能を作成しました(独自の拡張機能を使用できます)。
public static string GetFullErrorMessage(this ModelStateDictionary modelState) {
var messages = new List<string>();
foreach (var entry in modelState) {
foreach (var error in entry.Value.Errors)
messages.Add(error.ErrorMessage);
}
return String.Join(" ", messages);
}