134

すべての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の記述方法がわかりません...

4

14 に答える 14

202

句の中に好きなものを入れることができます:select

var errorList = (from item in ModelState
        where item.Value.Errors.Any() 
        select item.Value.Errors[0].ErrorMessage).ToList();

編集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();

2番目の編集:あなたは探していますDictionary<string, string[]>

var errorList = ModelState.ToDictionary(
    kvp => kvp.Key,
    kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
);
于 2010-05-16T23:11:08.737 に答える
77

これは、すべての要素をまとめた完全な実装です。

まず、拡張メソッドを作成します。

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());
    }
}
于 2010-05-17T03:25:07.360 に答える
23

ここで使用するのが好きな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."
      ]
   }
}
于 2013-09-04T21:09:27.240 に答える
9

BadRequestこれを行う最も簡単な方法は、ModelState自体でを返すことです。

たとえば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."
    ]
  }
}
于 2015-11-24T08:24:52.950 に答える
8

これを行うには、すべてが機能するさまざまな方法があります。これが今私がやる...

if (ModelState.IsValid)
{
    return Json("Success");
}
else
{
    return Json(ModelState.Values.SelectMany(x => x.Errors));
}
于 2013-11-29T12:11:25.363 に答える
6

組み込みの機能を使用してこれを実現する簡単な方法

[HttpPost]
public IActionResult Post([FromBody]CreateDoctorInput createDoctorInput) {
    if (!ModelState.IsValid) {
        return BadRequest(ModelState);
    }

    //do something
}

JSONの結果は

于 2018-08-15T04:34:23.513 に答える
5

@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;
        }
于 2012-11-25T04:47:51.653 に答える
3

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のアイデアを入手しました

于 2015-10-14T09:01:25.187 に答える
2

ToDictionaryは、System.Web.Extensionsdllhttp : //msdn.microsoft.com/en-us/library/system.linq.enumerable.todictionary.aspxにパッケージ化されているSystem.Linqにある列挙可能な拡張機能です。これが私にとって完全なクラスがどのように見えるかです。

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

    }

}
于 2010-09-10T18:31:01.050 に答える
2

元のオブジェクトをクライアントに返し、ModelStatejQueryを使用して値を読み取ってみませんか。私にはそれははるかに単純に見え、共通のデータ構造(.netのModelState)を使用します

をJsonとして返すにはModelState、それを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);
        }
于 2013-09-20T12:12:22.237 に答える
1

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;
    }
}
于 2013-01-31T16:41:52.800 に答える
1

私は同じハードルに遭遇しました。400BadRequestの出力形式を制御したいのですが、の内臓をシリアル化して手を汚したくありませんでしたModelState。封印された(しかし公開されている、ありがたいことに)SerializableErrorクラスを使用します。

var errorDetails = new SerializableError(ModelState);

var errorResponse = new YourCustomResponseType
{
    ModelValidationErrors = errorDetails,
    LogMessages = new []
    {
        new LogMessage("Error", "Invalid model - see modelValidationErrors for detail")
    }
};
return BadRequest(errorResponse);

YourCustomResponseTypeこのように見える場所:

public class YourCustomResponseType
{
        public LogMessage[] LogMessages { get; set; }
        public Dictionary<string, object> ModelValidationErrors { get; set; }
}

SerializableErrorですDictionary<string, object>ので、これはうまくいきます。応答は次のようになります。

{
    "logMessages": [
        {
            "category": "Error",
            "message": "Invalid model - see modelValidationErrors for detail"
        }
    ],
    "modelValidationErrors": {
        "aSettingsType.someEnumField": [
            "The input was not valid."
        ]
    }
}
于 2020-12-22T18:35:42.540 に答える
0

区切り文字""で文字列を返す拡張機能を作成しました(独自に使用できます):

   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);
    }
于 2018-10-15T06:39:08.700 に答える
-1
  List<ErrorList> Errors = new List<ErrorList>(); 


        //test errors.
        var modelStateErrors = this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors);

        foreach (var x in modelStateErrors)
        {
            var errorInfo = new ErrorList()
            {
                ErrorMessage = x.ErrorMessage
            };
            Errors.Add(errorInfo);

        }

jsonresultを使用する場合は、

return Json(Errors);

または、modelStateErrorsを返すだけで、試したことはありません。私が行ったことは、ErrorsコレクションをViewModelに割り当ててからループすることです。この場合、jsonを介してErrorsを返すことができます。クラス/モデルがあり、ソース/キーを取得したかったのですが、それを理解しようとしています。

    public class ErrorList
{
    public string ErrorMessage;
}
于 2017-02-06T16:16:24.117 に答える