ASP.Net MVC modelState에서 모든 오류를 얻는 방법?


453

키 값을 몰라도 modelState에서 모든 오류 메시지를 가져오고 싶습니다. ModelState에 포함 된 모든 오류 메시지를 가져 오기 위해 반복합니다.

어떻게해야합니까?


5
오류 @Html.ValidationSummary()를 표시하는 경우 모든 오류를 면도기에 빠르게 표시 할 수 있습니다.
levininja

11
foreach (var error in ViewData.ModelState.Values.SelectMany(modelState => modelState.Errors)) { DoSomething(error); }
Razvan Dumitru

답변:


531
foreach (ModelState modelState in ViewData.ModelState.Values) {
    foreach (ModelError error in modelState.Errors) {
        DoSomethingWith(error);
    }
}

ASP.NET MVC에서 모델 상태 오류 모음을 얻는 방법을 참조하십시오 . .


22
매우 도움이됩니다. 바인딩 실패 및 잘못된 요청과 같은 일부 시나리오에서는 빈 문자열이있는 ModelState 항목이 Value.ErrorMessage있고 대신에Value.Exception.Message
AaronLS

5
오류는 좋지만 때로는 모델 상태 키 (예 : 필드 이름)를 원할 수도 있습니다. 첫 번째 줄을 this :로 변경하여 얻을 수 있습니다 . foreach (KeyValuePair<string, ModelState> kvp in htmlHelper.ViewData.ModelState) {이 줄을 그 아래에 삽입하십시오 var modelState = kvp.Value;. 키를 얻을 수 있습니다kvp.Key
viggity

534

LINQ 사용 :

IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);

69
오류 메시지만으로 IEnumerable <string>을 반환하도록 수정되었습니다. var allErrors = ModelState.Values.SelectMany (v => v.Errors.Select (b => b.ErrorMessage));
Kieran

6
이것은 훌륭하지만 불행히도 Watch / Immediate 창은 람다를 지원하지 않습니다 :(
AaronLS

3
예! 나는 (당신, 누구든지) "System.Linq; 사용" 상단에. 그렇지 않으면 '값에 다수 선택에 대한 정의가 없습니다'라는 메시지가 표시됩니다. 내 경우에는 누락되었습니다.
Estevez

2
왜 var에서 ????를 사용 하는가 ??? 대신`IEnumerable <ModelError> '를 쓸 수 없었습니까 ???
Hakan Fıstık 2016 년

6
@ hakam-fostok @ jb06 당신 둘 다 맞아. 타자List<string> errors = new List<string>()대신 하는 var errors = new List<string>()것은 시간 낭비이지만 IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);반환 유형이 실제로 명확하지 않은 글쓰기 는 가독성 측면에서 실제로 더 큽니다. (비주얼 스튜디오 마우스를 가져가 당신에게 줄 수있는 경우에도)
aprovent

192

모든 오류 메시지를 하나의 문자열로 결합하려는 경우 LINQ 버전을 기반으로합니다.

string messages = string.Join("; ", ModelState.Values
                                        .SelectMany(x => x.Errors)
                                        .Select(x => x.ErrorMessage));

5
다른 옵션은 다음을 수행하는 것입니다. ModelState.Values.SelectMany (x => x.Errors) .Select (x => x.ErrorMessage) .JoinString ( ";");
Tod Thomson

3
@Tod, IEnumerable.JoinString ()은 자체 확장 방법입니까? 참조 stackoverflow.com/q/4382034/188926
덩크

2
Hey Dunc-그렇습니다. 나는 그 확장 방법을 내 코드베이스에 추가하고 잊어 버렸고 프레임 워크 방법 LOL이라고 생각했습니다 :(
Tod Thomson

5
또는 ... ModelState.Values.SelectMany (O => O.Errors) .Select (O => O.ErrorMessage) .Aggregate ((U, V) => U + ","+ V)
fordareh

2
이것은 웹 API를 사용하고 IHttpActionResult 결과를 반환 할 때 효과적입니다. 그래서 당신은 할 수 있습니다 : return BadRequest (messages); 고마워, 던!
리치 워드

32

약간의 LINQ를 사용하여이 작업을 수행 할 수있었습니다.

public static List<string> GetErrorListFromModelState
                                              (ModelStateDictionary modelState)
{
      var query = from state in modelState.Values
                  from error in state.Errors
                  select error.ErrorMessage;

      var errorList = query.ToList();
      return errorList;
}

위의 메서드는 유효성 검사 오류 목록을 반환합니다.

추가 자료 :

ASP.NET MVC에서 ModelState의 모든 오류를 읽는 방법


17

디버깅하는 동안 모든 ModelState 오류를 표시하기 위해 각 페이지의 맨 아래에 테이블을 배치하는 것이 유용하다는 것을 알았습니다.

<table class="model-state">
    @foreach (var item in ViewContext.ViewData.ModelState) 
    {
        if (item.Value.Errors.Any())
        { 
        <tr>
            <td><b>@item.Key</b></td>
            <td>@((item.Value == null || item.Value.Value == null) ? "<null>" : item.Value.Value.RawValue)</td>
            <td>@(string.Join("; ", item.Value.Errors.Select(x => x.ErrorMessage)))</td>
        </tr>
        }
    }
</table>

<style>
    table.model-state
    {
        border-color: #600;
        border-width: 0 0 1px 1px;
        border-style: solid;
        border-collapse: collapse;
        font-size: .8em;
        font-family: arial;
    }

    table.model-state td
    {
        border-color: #600;
        border-width: 1px 1px 0 0;
        border-style: solid;
        margin: 0;
        padding: .25em .75em;
        background-color: #FFC;
    }
 </style>

여기에 실패한 경우가있는 경우에는 문제를 해결하기 위해 답변을 편집하십시오.
Simon_Weaver

12

지금까지 주어진 답변에서 조언을 따랐다는 것을 알았으므로 오류 메시지를 설정하지 않고 예외가 발생하여 ErrorMessage와 Exception을 얻는 데 실제로 필요한 모든 문제를 잡을 수 있습니다.

String messages = String.Join(Environment.NewLine, ModelState.Values.SelectMany(v => v.Errors)
                                                           .Select( v => v.ErrorMessage + " " + v.Exception));

또는 확장 방법으로

public static IEnumerable<String> GetErrors(this ModelStateDictionary modelState)
{
      return modelState.Values.SelectMany(v => v.Errors)
                              .Select( v => v.ErrorMessage + " " + v.Exception).ToList();

}

왜 모든 오류가있는 문자열을 원하십니까? 뷰에서 무언가를하고 싶을 때 이해가되지 않습니다.리스트의 배열이 훨씬 더 좋습니다
Daniël Tulp

1
디버깅합니다. 내 첫 번째 문제는 내 앱에 어떤 문제가 있는지 알아내는 것이 었습니다. 나는 사용자에게 무엇이 잘못되었는지를 말하려고하지 않았습니다. 또한 문자열 열거를 작성하는 것에서 오류 메시지 및 예외와 같은 다른 것의 열거로 변환하는 것은 사소한 일입니다. 따라서 실제로 유용한 정보는 두 가지 정보가 모두 필요하다는 것을 아는 것입니다.
Alan Macdonald

BTW 두 번째 확장 방법이 큰 단일 문자열뿐만 아니라 IEnumerable <String>을 반환한다는 것을 알고 있습니까?
Alan Macdonald

8

누구나 오류 메시지를 강력한 형식의보기로 바인딩하기 위해 Model 속성 이름을 반환하려는 경우.

List<ErrorResult> Errors = new List<ErrorResult>();
foreach (KeyValuePair<string, ModelState> modelStateDD in ViewData.ModelState)
{
    string key = modelStateDD.Key;
    ModelState modelState = modelStateDD.Value;

    foreach (ModelError error in modelState.Errors)
    {
        ErrorResult er = new ErrorResult();
        er.ErrorMessage = error.ErrorMessage;
        er.Field = key;
        Errors.Add(er);
    }
}

이렇게하면 실제로 오류를 던진 필드와 오류를 묶을 수 있습니다.


7

오류 메시지 자체를 출력하는 것만으로는 충분하지 않았지만 이것은 트릭을 수행했습니다.

var modelQuery = (from kvp in ModelState
                  let field = kvp.Key
                  let state = kvp.Value
                  where state.Errors.Count > 0
                  let val = state.Value?.AttemptedValue ?? "[NULL]"

                  let errors = string.Join(";", state.Errors.Select(err => err.ErrorMessage))
                  select string.Format("{0}:[{1}] (ERRORS: {2})", field, val, errors));

Trace.WriteLine(string.Join(Environment.NewLine, modelQuery));

1
경고로 ModelState의 키 값 쌍에는 NULL 값이 포함될 수 있으므로 여기에 원래 코드에 null-coalesce 연산자 (?.)가 포함 된 귀여운 C # 6 비즈니스가 포함 되었기 때문에 ?? 표현의 끝에서. null 오류로부터 보호해야하는 원래 식은 다음과 같습니다. state.Value.?AttemptedValue ?? "[없는]". 내가 아는 한, state.Value == null 인 경우를 제대로 처리하지 않으면 현재 상태의 코드가 위험합니다.
Josh Sutterfield

5

누군가가 필요로하는 경우를 위해 프로젝트에서 다음 정적 클래스를 만들고 사용합니다.

사용 예 :

if (!ModelState.IsValid)
{
    var errors = ModelState.GetModelErrors();
    return Json(new { errors });
}

사용 :

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using WebGrease.Css.Extensions;

수업:

public static class ModelStateErrorHandler
{
    /// <summary>
    /// Returns a Key/Value pair with all the errors in the model
    /// according to the data annotation properties.
    /// </summary>
    /// <param name="errDictionary"></param>
    /// <returns>
    /// Key: Name of the property
    /// Value: The error message returned from data annotation
    /// </returns>
    public static Dictionary<string, string> GetModelErrors(this ModelStateDictionary errDictionary)
    {
        var errors = new Dictionary<string, string>();
        errDictionary.Where(k => k.Value.Errors.Count > 0).ForEach(i =>
        {
            var er = string.Join(", ", i.Value.Errors.Select(e => e.ErrorMessage).ToArray());
            errors.Add(i.Key, er);
        });
        return errors;
    }

    public static string StringifyModelErrors(this ModelStateDictionary errDictionary)
    {
        var errorsBuilder = new StringBuilder();
        var errors = errDictionary.GetModelErrors();
        errors.ForEach(key => errorsBuilder.AppendFormat("{0}: {1} -", key.Key,key.Value));
        return errorsBuilder.ToString();
    }
}

감사합니다 CodeArtist !! 구현 아래 코드를 약간 변경했습니다.
Alfred Severo

4

그리고 이것은 작동합니다 :

var query = from state in ModelState.Values
    from error in state.Errors
    select error.ErrorMessage;
var errors = query.ToArray(); // ToList() and so on...

@Yasser 토토의 대답을 보셨습니까?
머핀 남자

@TheMuffinMan 예, 있습니다. 어때요?
Yasser Shaikh

@Yasser 가장 좋은 답변입니다. 이것에 아무 문제가 없지만 사용 SelectMany가능할 때 사용할 점 은 없습니다.
머핀 맨

4

Json을 통해 View에 오류 메시지 배열을 전달하는 데 유용합니다.

messageArray = this.ViewData.ModelState.Values.SelectMany(modelState => modelState.Errors, (modelState, error) => error.ErrorMessage).ToArray();

4

이것은 @Dunc의 대답에 따라 확장됩니다. xml 문서 주석 참조

// ReSharper disable CheckNamespace
using System.Linq;
using System.Web.Mvc;


public static class Debugg
{
    /// <summary>
    /// This class is for debugging ModelState errors either in the quick watch 
    /// window or the immediate window.
    /// When the model state contains dozens and dozens of properties, 
    /// it is impossible to inspect why a model state is invalid.
    /// This method will pull up the errors
    /// </summary>
    /// <param name="modelState">modelState</param>
    /// <returns></returns>
    public static ModelError[]  It(ModelStateDictionary modelState)
    {
        var errors = modelState.Values.SelectMany(x => x.Errors).ToArray();
        return errors;            
    }
}

3

또한 ModelState.Values.ErrorMessage비어있을 수 있지만 ModelState.Values.Exception.Message오류를 나타낼 수 있습니다 .


0

구현에서 정적 클래스가 누락되었습니다.

if (!ModelState.IsValid)
{
    var errors =  ModelStateErrorHandler.GetModelErrors(this.ModelState);
    return Json(new { errors });
}

차라리

if (!ModelState.IsValid)
{
    var errors = ModelState.GetModelErrors();
    return Json(new { errors });
}

0

<div class="text-danger" style="direction:rtl" asp-validation-summary="All"></div>

간단히 asp-validation-summary Tag Helper를 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.