ASP.NET MVC मॉडलस्टैट त्रुटियों को कैसे JSON में परिवर्तित करें


127

आपको सभी ModelState त्रुटि संदेशों की एक सूची कैसे मिलती है? मुझे सभी कुंजी प्राप्त करने के लिए यह कोड मिला: ( ModelState त्रुटियों के साथ कुंजियों की सूची लौटाते हुए )

var errorKeys = (from item in ModelState
        where item.Value.Errors.Any() 
        select item.Key).ToList();

लेकिन मुझे आईएलएस या आईक्यूएबल के रूप में त्रुटि संदेश कैसे मिलेगा?

मैं जा सकता था:

foreach (var key in errorKeys)
{
    string msg = ModelState[error].Errors[0].ErrorMessage;
    errorList.Add(msg);
}

लेकिन यह मैन्युअल रूप से कर रहे हैं - निश्चित रूप से LINQ का उपयोग करने का एक तरीका है? .ErrorMessage प्रॉपर्टी की श्रृंखला इतनी नीचे है कि मुझे नहीं पता कि LINQ कैसे लिखा जाता है ...

जवाबों:


192

आप क्लॉज़ के अंदर कुछ भी डाल सकते हैं 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 एनडी EDIT : आप एक के लिए देख रहे हैं Dictionary<string, string[]>:

var errorList = ModelState.ToDictionary(
    kvp => kvp.Key,
    kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
);

एक त्वरित जवाब :)! अरे यह अच्छा लग रहा है, लेकिन क्या होगा अगर ModelState [item.Key] में 1 से अधिक त्रुटि है? त्रुटियां [0] केवल एक त्रुटि संदेश के लिए काम करती है
जेके।

आप उन्हें कैसे संयोजित करना चाहते हैं?
SLaks

धन्यवाद thats लगभग यह - लेकिन इसकी हर कुंजी का चयन भले ही इसमें कोई त्रुटि न हो - हम बिना किसी त्रुटि के चाबियों को कैसे फ़िल्टर कर सकते हैं?
जे.के.

4
जोड़ें.Where(kvp => kvp.Value.Errors.Count > 0)
SLaks

3
उसी तरह का आउटपुट प्राप्त करने के लिए Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);आपको उपयोग करना चाहिए var errorList = modelState.Where(elem => elem.Value.Errors.Any()) .ToDictionary( kvp => kvp.Key, kvp => kvp.Value.Errors.Select(e => string.IsNullOrEmpty(e.ErrorMessage) ? e.Exception.Message : e.ErrorMessage).ToArray());अन्यथा आपके पास ExceptionMessages नहीं होंगे
Silvos

74

यहाँ सभी टुकड़ों को एक साथ रखा गया है:

पहले एक विस्तार विधि बनाएं:

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

फिर उस एक्सटेंशन विधि को कॉल करें और त्रुटियों को नियंत्रक क्रिया (यदि कोई हो) से वापस लौटाएँ

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

यह एक दिलचस्प विधि की तरह लग रहा है, हालांकि सहायक वर्ग मेरे लिए काम नहीं कर रहा है। क्या यह एमवीसी 2 के साथ बदलाव के कारण है? मुझे एक त्रुटि मिल रही है कि मॉडलटाइट पर टोबोर्ड विधि मौजूद नहीं है।
साइमन

@Cymen क्या आप System.Linq का संदर्भ लेना भूल रहे हैं? To मंद () एक LINQ एक्सटेंशन विधि है।
नाथन टेलर

8
अपनी प्राथमिकताओं के अधीन .Where(m => m.Value.Count() > 0)भी लिखा जा सकता है .Where(m => m.Value.Any())
मैनफ्रेड

इसे उसी तरह से इस्तेमाल किया जा सकता है जैसे कि मॉडलस्टैट.टोडाटा स्रोत () (Kendo.Mvc) से ग्रिड में त्रुटियों को वापस करने और संपादन में त्रुटि संदेश प्रदर्शित करने के लिए।
मालनोज़ा

22

मैं 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."
      ]
   }
}

8

ऐसा करने के लिए बहुत सारे अलग-अलग तरीके हैं जो सभी काम करते हैं। यहाँ अब मैं यह कर रहा हूँ ...

if (ModelState.IsValid)
{
    return Json("Success");
}
else
{
    return Json(ModelState.Values.SelectMany(x => x.Errors));
}

2
आप भी लौट सकते हैं BadRequest(ModelState)और यह आपके लिए JSON में क्रमबद्ध होगा।
फ्रेड

6

ऐसा करने का सबसे आसान तरीका सिर्फ एक रिटर्न है 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."
    ]
  }
}

1
BadRequest WebAPI विशिष्ट है और यह प्रश्न MVC के बारे में है।
rgripper

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

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 विचार मिला


3

सरल तरीका बिल्ट-इन कार्यक्षमता का उपयोग करके इसे प्राप्त करते हैं

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

    //do something
}

JSON परिणाम होगा


2

टाउबर्ड एक Enumerable एक्सटेंशन है जो System.Linq में System.Web.Extensions dll http://msdn.microsoft.com/en-us/library/system.linq.enumerable.todfox.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;
        }

    }

}

2

ModelStateक्लाइंट को मूल ऑब्जेक्ट क्यों नहीं लौटाया जाए , और फिर मूल्यों को पढ़ने के लिए jQuery का उपयोग करें। मेरे लिए यह बहुत सरल दिखता है, और सामान्य डेटा संरचना (.net's) का उपयोग करता हैModelState )

लौटने के लिए ModelStateजसन रूप में , बस इसे जसन क्लास कंस्ट्रक्टर (किसी भी वस्तु के साथ काम करता है) के लिए पास करें

सी#:

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

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

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

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

या आप बस मॉडलस्ट्रेटर को वापस कर सकते हैं, मैंने कोशिश की थी। मैंने जो किया है वह मेरे ViewModel में त्रुटियाँ संग्रह को असाइन करता है और फिर इसे लूप करता है..इस मामले में मैं अपने त्रुटियों को json के माध्यम से वापस कर सकता हूं। मेरे पास एक वर्ग / मॉडल है, मैं स्रोत / कुंजी प्राप्त करना चाहता था लेकिन मैं अभी भी यह पता लगाने की कोशिश कर रहा हूं।

    public class ErrorList
{
    public string ErrorMessage;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.