ASP.Net MVC modelState tüm hatalar almak nasıl?


453

Anahtar değerleri bilmeden model hatalarının tüm hata mesajlarını modelden çıkarmak istiyorum. ModelState'in içerdiği tüm hata mesajlarını almak için döngü yapılıyor.

Bunu nasıl yapabilirim?


5
Sadece hataları görüntülüyorsanız, @Html.ValidationSummary()hepsini usturada görüntülemenin hızlı bir yoludur.
Ocak'ta levininja

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

Yanıtlar:


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

Ayrıca bkz . ASP.NET MVC Model Durumu Hataları koleksiyonunu nasıl alabilirim? .


22
Çok yararlı. Bağlama hataları ve hatalı istekler gibi bazı senaryolarda, Value.ErrorMessagebunun için boş dize içeren ModelState girdileri bulunacağını ve bunun yerine aValue.Exception.Message
AaronLS

5
Hatalar güzel ama bazen model durumunun anahtarını da istersiniz (yani alanın adı). Bu ilk satırını değiştirerek bu alabilirsiniz: foreach (KeyValuePair<string, ModelState> kvp in htmlHelper.ViewData.ModelState) {ve onun altındaki bu satırı ekleyin: var modelState = kvp.Value;. Anahtarı alabilirsinizkvp.Key
viggity

534

LINQ kullanma :

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

69
IEnumerable <string> öğesini yalnızca hata mesajıyla döndürmek için değiştirildi :: var allErrors = ModelState.Values.SelectMany (v => v.Errors.Select (b => b.ErrorMessage));
Kieran

6
Bu harika, ama ne yazık ki İzle / Anında pencereler
lambda'nın

3
Evet! Ben (siz, herkes) "System.Linq kullanarak;" üstte. Aksi takdirde 'Değerler, Çok sayıda için bir tanım içermiyor' iletisini aldınız. Benim durumumda eksikti.
Estevez

2
neden var cehennemde ?????? Bunun yerine `` IEnumerable <ModelError> '' yazamadınız mı ???
Hakan Fıstık

6
@ hakam-fostok @ jb06 ikiniz de haklısınız. List<string> errors = new List<string>()Bunun yerine yazmak var errors = new List<string>()gerçekten zaman kaybıdır, ancak IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);geri dönüş türünün gerçekten net olmadığı yazım , okunabilirlik açısından gerçekten daha büyüktür. (görsel stüdyo fare üzerine geldiğinde bile)
16:46

192

Tüm hata mesajlarını tek bir dizede birleştirmek istiyorsanız, LINQ sürümüne dayanarak:

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

5
Diğer seçenek aşağıdakileri yapmaktır: ModelState.Values.SelectMany (x => x.Errors) .Select (x => x.ErrorMessage) .JoinString (";");
Tod Thomson

3
@Tod, IEnumerable.JoinString () kendi uzantı yönteminiz mi? Bkz. Stackoverflow.com/q/4382034/188926
Dunc

2
Hey Dunc - evet Ben kod tabanına bu uzatma yöntemi ekledim ve bunu unuttum ve sonra bir çerçeve yöntemi olduğunu düşündüm LOL :(
Tod Thomson

5
veya ... ModelState.Values.SelectMany (O => O.Errors). (O => O.ErrorMessage) .Aggregate ((U, V) => U + "," + V)
Ağustos'u unut

2
Web api kullanırken ve bir IHttpActionResult sonucu döndürürken bu harika çalışır. Böylece, şunları yapabilirsiniz: return BadRequest (messages); Teşekkürler Dunc!
Rich Ward

32

Bunu küçük bir LINQ kullanarak yapabildim,

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

Yukarıdaki yöntem, doğrulama hatalarının bir listesini döndürür.

Daha fazla okuma :

ASP.NET MVC ModelState tüm hatalar nasıl okunur


17

Hata ayıklama sırasında tüm ModelState hatalarını göstermek için her bir sayfamın altına bir tablo koymak yararlı buluyorum.

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

burada bunun başarısız olduğu herhangi bir son durum varsa lütfen düzeltmek için cevabı düzenleyin
Simon_Weaver

12

Şimdiye kadar verilen cevaplardaki tavsiyelere uyduğumu keşfettiğim gibi, hata mesajları ayarlanmadan istisnalar alabilirsiniz, böylece tüm sorunları yakalamak için gerçekten ErrorMessage ve İstisna almak gerekir.

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

veya bir uzatma yöntemi olarak

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

}

neden içindeki tüm hataları içeren bir dize istiyorsunuz? görünümde onunla bir şey yapmak istediğinizde mantıklı değil, bir dizi liste daha iyi imho
Daniël Tulp

1
Hata ayıklamak için. İlk sorunum, uygulamamda neyin yanlış gittiğini bulmaktı. Kullanıcıya sadece neyin yanlış gittiğini öğrenmeye çalışmıyordum. Ayrıca, bu örneği, dizelerin numaralandırılmasından başka bir şeyin numaralandırılmasına, örneğin hata mesajı ve istisnaya dönüştürmek çok önemlidir, bu yüzden gerçekten yararlı olan şey, her iki bilgi
Alan Macdonald

BTW ikinci uzantı yöntemi sadece büyük bir tek dize değil, IEnumerable <String> döndürür fark ettiniz mi?
Alan Macdonald

8

Herkesin güçlü bir şekilde yazılan bir görünümde hata iletisini bağlamak için Model özelliğinin adını döndürmek istemesi durumunda.

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

Bu şekilde, hatayı, hataya neden olan alanla ilişkilendirebilirsiniz.


7

Sadece Hata mesajlarını kendileri vermek benim için yeterli değildi, ama bu hile yaptı.

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
Uyarı olarak, ModelState'teki anahtar / değer çiftleri NULL değerleri içerebilir, bu nedenle buradaki orijinal kod, boş birleşme operatörü (?.) İle sevimli C # 6 işlerini içermiştir, bu nedenle? ifadenin sonunda. Boş hatalardan korunması gereken orijinal ifade şuydu: state.Value.?AttemptedValue ?? "[BOŞ]". Bildiğim kadarıyla, state.Value == null olan durumların sinsi bir şekilde ele alınmasına gerek kalmadan mevcut durumdaki kod.
Josh Sutterfield

5

Çünkü birinin ihtiyacı olması halinde projelerimde aşağıdaki statik sınıfı yaptım ve kullanıyorum

Kullanım örneği:

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

usings:

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

Sınıf:

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

Teşekkürler CodeArtist !! Uygulamasının altındaki kodda küçük bir değişiklik yaptım.
Alfred Severo

4

Ve bu da işe yarıyor:

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

@Yasser Toto'nun cevabını gördün mü?
Muffin Adam

@TheMuffinMan evet var. Ne olmuş?
Yasser Shaikh

@Yasser En iyi cevap bu. Bu konuda yanlış bir şey yok, ancak kullanılabilir olduğunda kullanmanın bir anlamı yok SelectMany.
Muffin Adam

4

Belki de Json aracılığıyla View'a hata mesajı dizisi geçirmek için kullanışlıdır:

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

4

Bu @Dunc'un cevabı üzerine genişliyor. Xml doc yorumlarına bakın

// 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

Ayrıca, ModelState.Values.ErrorMessageboş ModelState.Values.Exception.Messageolabilir , ancak bir hata olduğunu gösterebilir.


0

Uygulamanızda statik Sınıf eksik, bu olmalıdır.

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

daha doğrusu

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-özet Etiket Yardımcısı'nı kullanmanız yeterlidir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.