ASP.NET MVC Ajax त्रुटि से निपटने


117

जब jquery ajax एक कार्रवाई को बुलाता है तो मैं नियंत्रक में फेंके गए अपवादों को कैसे संभाल सकता हूं?

उदाहरण के लिए, मैं एक वैश्विक जावास्क्रिप्ट कोड चाहता हूं, जो किसी भी तरह के सर्वर अपवाद पर अजाक्स कॉल के दौरान निष्पादित हो जाता है जो अपवाद संदेश को डिबग मोड या सिर्फ एक सामान्य त्रुटि संदेश में प्रदर्शित करता है।

क्लाइंट की ओर, मैं ajax त्रुटि पर एक फ़ंक्शन को कॉल करूंगा।

सर्वर साइड पर, क्या मुझे एक कस्टम एक्शनफिल्टर लिखने की आवश्यकता है?


8
एक अच्छे उदाहरण के लिए beckelmans पोस्ट देखें । इस पोस्ट का डारिन्स उत्तर अच्छा है, लेकिन एक त्रुटि के लिए सही स्थिति कोड निर्धारित नहीं करता है।
दान

6
अफसोस की बात है कि यह लिंक अब टूट गया है
क्रिस नेविल

1
: यहाँ वेबैक मशीन पर कड़ी है web.archive.org/web/20111011105139/http://beckelman.net/post/...
BruceHill

जवाबों:


161

यदि सर्वर 200 से अलग कुछ स्टेटस कोड भेजता है, तो त्रुटि कॉलबैक निष्पादित होता है:

$.ajax({
    url: '/foo',
    success: function(result) {
        alert('yeap');
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        alert('oops, something bad happened');
    }
});

और एक वैश्विक त्रुटि हैंडलर को पंजीकृत करने के लिए आप $.ajaxSetup()विधि का उपयोग कर सकते हैं :

$.ajaxSetup({
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        alert('oops, something bad happened');
    }
});

दूसरा तरीका JSON का उपयोग करना है। इसलिए आप सर्वर पर एक कस्टम एक्शन फ़िल्टर लिख सकते हैं जो अपवाद को पकड़ता है और उन्हें JSON प्रतिक्रिया में बदल देता है:

public class MyErrorHandlerAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        filterContext.ExceptionHandled = true;
        filterContext.Result = new JsonResult
        {
            Data = new { success = false, error = filterContext.Exception.ToString() },
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };
    }
}

और फिर इस विशेषता के साथ अपने नियंत्रक कार्रवाई को सजाने:

[MyErrorHandler]
public ActionResult Foo(string id)
{
    if (string.IsNullOrEmpty(id))
    {
        throw new Exception("oh no");
    }
    return Json(new { success = true });
}

और अंत में इसे लागू करें:

$.getJSON('/home/foo', { id: null }, function (result) {
    if (!result.success) {
        alert(result.error);
    } else {
        // handle the success
    }
});

1
इसके लिए धन्यवाद, बाद वाला वही था जिसकी मुझे तलाश थी। तो asp.net mvc अपवाद के लिए, क्या कोई विशिष्ट तरीका है जिसे मुझे इसे फेंकने की आवश्यकता है ताकि इसे jquery त्रुटि हैंडलर द्वारा पकड़ा जा सके?
शॉन म्लेन

1
@Lol कोडर, आप नियंत्रक कार्रवाई के अंदर कोई अपवाद नहीं फेंकते हैं, सर्वर 500 स्थिति कोड लौटाएगा और errorकॉलबैक निष्पादित किया जाएगा।
डारिन दिमित्रोव

धन्यवाद, एकदम सही, मैं जो देख रहा था।
शॉन म्लेन

1
क्या 500 का स्टेटस कोड गलत नहीं होगा? इस चैप ब्रॉडकास्ट को उद्धृत करने के लिए ।oreilly.com/2011/06/… : "यह महसूस करने में असफल कि 4xx त्रुटि का मतलब है कि मैंने गड़बड़ कर दी है और एक 5xx का मतलब है कि आपने गड़बड़ कर दी है" - जहां मैं क्लाइंट हूं और आप सर्वर हैं।
क्रिस नेविल

यह उत्तर अभी भी ASPNET के नए संस्करणों के लिए मान्य है?
गोग

73

Googling के बाद, मैं MVC एक्शन फ़िल्टर पर आधारित एक सरल अपवाद लिखता हूं:

public class HandleExceptionAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
        {
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            filterContext.Result = new JsonResult
            {
                JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                Data = new
                {
                    filterContext.Exception.Message,
                    filterContext.Exception.StackTrace
                }
            };
            filterContext.ExceptionHandled = true;
        }
        else
        {
            base.OnException(filterContext);
        }
    }
}

और global.ascx में लिखें:

 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
      filters.Add(new HandleExceptionAttribute());
 }

और फिर इस स्क्रिप्ट को लेआउट या मास्टर पृष्ठ पर लिखें:

<script type="text/javascript">
      $(document).ajaxError(function (e, jqxhr, settings, exception) {
                       e.stopPropagation();
                       if (jqxhr != null)
                           alert(jqxhr.responseText);
                     });
</script>

अंत में आपको कस्टम एरर को ऑन करना चाहिए। और फिर इसका आनंद लें :)


मैं फायरबग में त्रुटि देख सकता हूं लेकिन यह त्रुटि पृष्ठ पर पुनर्निर्देशित नहीं कर रहा है।
user2067567

1
इसके लिए धन्यवाद! IMO ajax अनुरोध और inherits सही वर्ग पर इसकी छानने के रूप में के बजाय जवाब के रूप में चिह्नित किया जाना चाहिए क्या HandleErrorAttribute inherits
mtbennett

2
अद्भुत जवाब! : डी
लेनियल मैककैफेर्री

1
मुझे लगता है कि "Request.IsAjaxRequest ()" कभी-कभी विश्वसनीय नहीं होता है।
विल हुआंग

डिबग कॉन्फ़िगरेशन के लिए यह हमेशा काम करता है लेकिन रिलीज कॉन्फ़िगरेशन और रिटर्न html में हमेशा काम नहीं करता है, इसके बजाय किसी के पास ऐसे मामले के लिए समाधान है?
हितेंद्र

9

दुर्भाग्य से, दोनों में से कोई भी उत्तर मेरे लिए अच्छा नहीं है। आश्चर्यजनक रूप से समाधान बहुत सरल है। नियंत्रक से वापसी:

return new HttpStatusCodeResult(HttpStatusCode.BadRequest, e.Response.ReasonPhrase);

और इसे क्लाइंट पर मानक HTTP त्रुटि के रूप में आप की तरह संभाल।


@Will हुआंग: अपवाद के नाम
schmendrick

मुझे पहले तर्क देना होगा int। इसके अलावा, जब मैं ऐसा करता हूं, तो परिणाम ajax successहैंडलर के पास जाता है , और errorहैंडलर के पास नहीं । क्या यह अपेक्षित व्यवहार है?
जोनाथन वुड

4

मैंने त्वरित समाधान किया क्योंकि मेरे पास समय कम था और यह ठीक काम कर रहा था। हालांकि मुझे लगता है कि बेहतर विकल्प एक अपवाद फ़िल्टर का उपयोग करता है, शायद मेरा समाधान इस मामले में मदद कर सकता है कि एक सरल समाधान की आवश्यकता है।

मैंने निम्नलिखित किया। नियंत्रक पद्धति में मैंने डेटा के अंदर एक संपत्ति "सफलता" के साथ एक JsonResult लौटाया:

    [HttpPut]
    public JsonResult UpdateEmployeeConfig(EmployeConfig employeToSave) 
    {
        if (!ModelState.IsValid)
        {
            return new JsonResult
            {
                Data = new { ErrorMessage = "Model is not valid", Success = false },
                ContentEncoding = System.Text.Encoding.UTF8,
                JsonRequestBehavior = JsonRequestBehavior.DenyGet
            };
        }
        try
        {
            MyDbContext db = new MyDbContext();

            db.Entry(employeToSave).State = EntityState.Modified;
            db.SaveChanges();

            DTO.EmployeConfig user = (DTO.EmployeConfig)Session["EmployeLoggin"];

            if (employeToSave.Id == user.Id)
            {
                user.Company = employeToSave.Company;
                user.Language = employeToSave.Language;
                user.Money = employeToSave.Money;
                user.CostCenter = employeToSave.CostCenter;

                Session["EmployeLoggin"] = user;
            }
        }
        catch (Exception ex) 
        {
            return new JsonResult
            {
                Data = new { ErrorMessage = ex.Message, Success = false },
                ContentEncoding = System.Text.Encoding.UTF8,
                JsonRequestBehavior = JsonRequestBehavior.DenyGet
            };
        }

        return new JsonResult() { Data = new { Success = true }, };
    }

बाद में अजाक्स कॉल में मैंने सिर्फ इस संपत्ति के लिए पूछा कि क्या मेरे पास अपवाद है?

$.ajax({
    url: 'UpdateEmployeeConfig',
    type: 'PUT',
    data: JSON.stringify(EmployeConfig),
    contentType: "application/json;charset=utf-8",
    success: function (data) {
        if (data.Success) {
            //This is for the example. Please do something prettier for the user, :)
            alert('All was really ok');                                           
        }
        else {
            alert('Oups.. we had errors: ' + data.ErrorMessage);
        }
    },
    error: function (request, status, error) {
       alert('oh, errors here. The call to the server is not working.')
    }
});

उम्मीद है की यह मदद करेगा। खुश कोड! : पी


4

एलेहो की प्रतिक्रिया के साथ यहां एक पूर्ण उदाहरण है। यह एक आकर्षण की तरह काम करता है और सुपर सरल है।

नियंत्रक कोड

[HttpGet]
public async Task<ActionResult> ChildItems()
{
    var client = TranslationDataHttpClient.GetClient();
    HttpResponseMessage response = await client.GetAsync("childItems);

    if (response.IsSuccessStatusCode)
        {
            string content = response.Content.ReadAsStringAsync().Result;
            List<WorkflowItem> parameters = JsonConvert.DeserializeObject<List<WorkflowItem>>(content);
            return Json(content, JsonRequestBehavior.AllowGet);
        }
        else
        {
            return new HttpStatusCodeResult(response.StatusCode, response.ReasonPhrase);
        }
    }
}

दृश्य में जावास्क्रिप्ट कोड

var url = '@Html.Raw(@Url.Action("ChildItems", "WorkflowItemModal")';

$.ajax({
    type: "GET",
    dataType: "json",
    url: url,
    contentType: "application/json; charset=utf-8",
    success: function (data) {
        // Do something with the returned data
    },
    error: function (xhr, status, error) {
        // Handle the error.
    }
});

मनाइए कि यह किसी और के लिए सहायक हो!


0

क्लाइंट पक्ष पर अजाक्स कॉल से त्रुटियों को संभालने के लिए, आप errorअजाक्स कॉल के विकल्प के लिए एक फ़ंक्शन असाइन करते हैं ।

विश्व स्तर पर एक डिफ़ॉल्ट सेट करने के लिए, आप यहां वर्णित फ़ंक्शन का उपयोग कर सकते हैं: http://api.jquery.com/jQuery.ajaxSetup


एक जवाब जो मैंने 4 साल पहले दिया था अचानक एक डाउन वोट मिलता है? किसी को भी एक कारण देने के लिए परवाह है?
ब्रायन बॉल

1
SOF से संपर्क करें और अपने DBA को क्वेरी करने के लिए कहें जिन्होंने डाउन वोट दिया था। अगला, उस व्यक्ति को संदेश दें ताकि वे समझा सकें। बस कोई भी एक कारण नहीं दे सकता है।
जोशिएट्स १
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.