2012-07-06 10 views
27

मैं This link में सलाह के अनुसार नियंत्रक को कॉल में एक त्रुटि वापस करने का प्रयास कर रहा था ताकि ग्राहक उचित कार्रवाई कर सके। नियंत्रक jquery AJAX के माध्यम से जावास्क्रिप्ट द्वारा बुलाया जाता है। मैं जेसन ऑब्जेक्ट को वापस प्राप्त कर रहा हूं अगर मैं स्थिति को गलती से सेट नहीं करता हूं। यहाँ नमूना कोडत्रुटि स्थिति कोड के साथ JSON लौटें एमवीसी

if (response.errors.Length > 0) 
    Response.StatusCode = (int)HttpStatusCode.BadRequest; 
return Json(response); 

मैं Json मिल अगर मैं statusCode निर्धारित नहीं करते है। यदि मैं स्थिति कोड सेट करता हूं तो मुझे स्थिति कोड वापस मिलता है लेकिन जेसन त्रुटि ऑब्जेक्ट नहीं।

अद्यतन मैं JSON के रूप में एक त्रुटि ऑब्जेक्ट भेजना चाहता हूं ताकि इसे AJAX के त्रुटि कॉलबैक को संभाला जा सके।

उत्तर

26

मैं समाधान पाया here

मैं MVC

यहाँ के डिफ़ॉल्ट व्यवहार को ओवरराइड करने के लिए एक कार्रवाई फिल्टर मेरी अपवाद वर्ग बनाने के लिए

class ValidationException : ApplicationException 
{ 
    public JsonResult exceptionDetails; 
    public ValidationException(JsonResult exceptionDetails) 
    { 
     this.exceptionDetails = exceptionDetails; 
    } 
    public ValidationException(string message) : base(message) { } 
    public ValidationException(string message, Exception inner) : base(message, inner) { } 
    protected ValidationException(
    System.Runtime.Serialization.SerializationInfo info, 
    System.Runtime.Serialization.StreamingContext context) 
     : base(info, context) { } 
} 

ध्यान दें कि मैं निर्माता जो initializes है है था मेरा JSON यहाँ जब त्रुटि कार्रवाई फिल्टर जो लागू करता IExceptionFilter कहा जाता है और मिल फेंक दिया है कि मैं कार्रवाई फिल्टर है, मैं फिल्टर विशेषता

[HandleUIException] 
public JsonResult UpdateName(string objectToUpdate) 
{ 
    var response = myClient.ValidateObject(objectToUpdate); 
    if (response.errors.Length > 0) 
    throw new ValidationException(Json(response)); 
} 

के साथ अपने नियंत्रक को सजाने होगा अब कार्रवाई फिल्टर

public class HandleUIExceptionAttribute : FilterAttribute, IExceptionFilter 
{ 
    public virtual void OnException(ExceptionContext filterContext) 
    { 
     if (filterContext == null) 
     { 
      throw new ArgumentNullException("filterContext"); 
     } 
     if (filterContext.Exception != null) 
     { 
      filterContext.ExceptionHandled = true; 
      filterContext.HttpContext.Response.Clear(); 
      filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 
      filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; 
      filterContext.Result = ((ValidationException)filterContext.Exception).myJsonError; 
     } 
    } 

है मैं त्रुटि कॉलबैक पर क्लाइंट पर जेसन वापस आ गया।

+10

यदि पाठक सोच रहा है कि "क्या यह आवश्यक है?", जवाब "नहीं" है। - मैं @ सारथ के समान स्थिति में था और त्रुटि का वर्णन करने वाले HTTP त्रुटि कोड और कुछ JSON डेटा को वापस करना चाहता था। यह पता चला कि मैं केवल उन लाइनों का उपयोग कर सकता हूं जहां प्रतिक्रिया साफ़ की गई थी, आईआईएस कस्टम त्रुटियों को छोड़ दिया गया है और स्थिति कोड बैठ गया है। मैंने उन 3 लाइनों को अपने कंट्रोलर पर अपने एक्शन में रखा, और उन 3 लाइनों के बाद, मैंने अपना JSON डेटा सामान्य के रूप में वापस कर दिया। एक जादू की तरह काम किया। –

+6

वास्तव में यह सच है, लेकिन पुन: प्रयोज्य होने के लिए आप इसे करना चाहते हैं क्योंकि उत्तर प्रत्येक क्रिया में एक ही कोड की प्रतिलिपि/प्रतिलिपि के बजाय इंगित करता है। – Hades

+0

यदि मैं 'StatusCode = 500' सेट करता हूं तो यह मेरे जेसन रेस्पॉन्स को अनदेखा करता है और इसके बदले" पृष्ठ प्रदर्शित नहीं किया जा सकता क्योंकि आंतरिक सर्वर त्रुटि आई है। "। सुनिश्चित नहीं है कि यह ओविन पाइपलाइन या क्या अंतर में अंतर के कारण है। – AaronLS

4

आप वापस जाने के लिए JSON त्रुटि StatusCode सेट करने के बाद ऑब्जेक्ट को स्वयं, इसलिए की तरह है ...

if (BadRequest) 
{ 
    Dictionary<string, object> error = new Dictionary<string, object>(); 
    error.Add("ErrorCode", -1); 
    error.Add("ErrorMessage", "Something really bad happened"); 
    return Json(error); 
} 

एक और तरीका है एक JsonErrorModel है और पॉप्युलेट यह

public class JsonErrorModel 
{ 
    public int ErrorCode { get; set;} 

    public string ErrorMessage { get; set; } 
} 

public ActionResult SomeMethod() 
{ 

    if (BadRequest) 
    { 
     var error = new JsonErrorModel 
     { 
      ErrorCode = -1, 
      ErrorMessage = "Something really bad happened" 
     }; 

     return Json(error); 
    } 

    //Return valid response 
} 

पर एक नजर डालें करने के लिए है उत्तर here साथ ही

+4

मुझे प्रतिक्रिया ऑब्जेक्ट में पहले से ही त्रुटि है। मुद्दा यह है कि मुझे "खराब अनुरोध" मिलता है, न कि JSON ऑब्जेक्ट। अगर मैं स्थिति निर्धारित नहीं करता हूं तो मुझे JSON त्रुटियों के साथ मिलता है लेकिन क्लाइंट को यह नहीं पता कि यह एक अपवाद स्थिति है। – Sarath

+0

@ सारथ उत्तर में लिंक की जांच करें। आपको JQuery –

+1

में AJAX विधि की त्रुटि विशेषता का उपयोग करने की आवश्यकता है, जिस समस्या का सामना कर रहा हूं वह यह है कि प्रतिक्रिया पर मुझे स्थिति सेट करने पर JSON वापस नहीं मिल रहा है। आपके द्वारा उत्तर दिया गया जवाब यह है कि मैं वास्तव में क्या कर रहा हूं। समस्या यह है कि अगर मैं प्रतिक्रिया की स्थिति निर्धारित करता हूं तो मुझे JSON नहीं मिलता है। – Sarath

4

आपको यह तय करने की आवश्यकता है कि क्या आप "HTTP स्तर त्रुटि" (जो त्रुटि कोड हैं) या "अनुप्रयोग स्तर त्रुटि" (वह डब्ल्यू टोपी आपके कस्टम JSON प्रतिक्रिया के लिए है)।

HTTP का उपयोग करने वाले अधिकांश उच्च स्तरीय ऑब्जेक्ट्स प्रतिक्रिया स्ट्रीम में कभी नहीं देखेंगे यदि त्रुटि कोड 2xx (सफलता सीमा) नहीं है। आपके मामले में आप विफलता में त्रुटि कोड को स्पष्ट रूप से सेट कर रहे हैं (मुझे लगता है कि 403 या 500) और प्रतिक्रिया के शरीर को अनदेखा करने के लिए XMLHttp ऑब्जेक्ट को बल दें।

ठीक करने के लिए - या तो क्लाइंट पक्ष पर त्रुटि स्थितियों को संभाल लें या त्रुटि कोड सेट न करें और त्रुटि जानकारी के साथ JSON लौटाएं (विवरण के लिए Sbossb उत्तर देखें)।

+1

आपकी प्रतिक्रिया के लिए धन्यवाद। क्लाइंट को कैसे पता चलेगा कि एक अपवाद था कि मैं स्टेटस कोड सेट नहीं करता? – Sarath

+0

@ सारथ, वही चेक 'response.errors && response.errors.length> 0' जैसा कि आप सर्वर पक्ष पर कर रहे हैं (जावास्क्रिप्ट क्लाइंट मानते हैं)। –

+2

@Alexi हां। लेकिन मैं स्पष्ट रूप से क्लाइंट को सूचित करना चाहता हूं कि एक त्रुटि हुई है। यही कहना है कि मैं सफलता की कॉलबैक की बजाय AJAX कॉल की विफलता कॉलबैक पर इस स्थिति को संभालना चाहता हूं और फिर त्रुटियों की तलाश करूँगा। – Sarath

17

इस समस्या का एक बहुत ही सुरुचिपूर्ण समाधान है, बस अपनी साइट को वेब के माध्यम से कॉन्फ़िगर करें।config:

<system.webServer> 
    <httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough"/> 
</system.webServer> 

स्रोत: https://serverfault.com/questions/123729/iis-is-overriding-my-response-content-if-i-manually-set-the-response-statuscode

+1

बूम! जवाब मैं देख रहा था। यह स्थानीय रूप से मेरे लिए ठीक काम करता है लेकिन रिमोट सर्वर में नहीं। मुझे पता था कि यह कुछ विन्यास सेटिंग्स के साथ किया जा सकता है। चीयर्स! – ThiagoPXP

+0

यह निश्चित रूप से प्रयास करें यदि यह स्थानीय में काम करता है लेकिन अजीब नहीं है! – Icycool

+0

समस्या के लिए, मुझे स्थानीय (देव) मशीन में स्टेटसकोड और जेसन प्रतिक्रिया मिली थी, लेकिन उत्पादन से इसे चलाने के दौरान मुझे केवल स्टेटसोड मिल रहा था। यह समाधान सबसे आसान है। – Vikneshwar

2

और अगर अपनी आवश्यकताओं सरत के रूप में के रूप में जटिल नहीं हैं आप कुछ और भी आसान के साथ भाग प्राप्त कर सकते हैं:

[MyError] 
public JsonResult Error(string objectToUpdate) 
{ 
    throw new Exception("ERROR!"); 
} 

public class MyErrorAttribute : FilterAttribute, IExceptionFilter 
{ 
    public virtual void OnException(ExceptionContext filterContext) 
    { 
     if (filterContext == null) 
     { 
     throw new ArgumentNullException("filterContext"); 
     } 
     if (filterContext.Exception != null) 
     { 
     filterContext.ExceptionHandled = true; 
     filterContext.HttpContext.Response.Clear(); 
     filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 
     filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; 
     filterContext.Result = new JsonResult() { Data = filterContext.Exception.Message }; 
     } 
    } 
} 
6

neatest समाधान मैंने पाया अपने स्वयं के जेसनआरसल्ट को बनाना है जो मूल कार्यान्वयन को बढ़ाता है और आपको एक एचटीपीस्टैटस कोड निर्दिष्ट करने की अनुमति देता है:

public class JsonHttpStatusResult : JsonResult 
{ 
    private readonly HttpStatusCode _httpStatus; 

    public JsonHttpStatusResult(object data, HttpStatusCode httpStatus) 
    { 
     Data = data; 
     _httpStatus = httpStatus; 
    } 

    public override void ExecuteResult(ControllerContext context) 
    { 
     context.RequestContext.HttpContext.Response.StatusCode = (int)_httpStatus; 
     base.ExecuteResult(context); 
    } 
} 

फिर आप इस अपने नियंत्रक कार्रवाई में इतनी तरह उपयोग कर सकते हैं: रिचर्ड Garside से जवाब पर

if(thereWereErrors) 
{ 
    var errorModel = new { error = "There was an error" }; 
    return new JsonHttpStatusResult(errorModel, HttpStatusCode.InternalServerError); 
} 
3

भवन, यहाँ ASP.Net कोर संस्करण

public class JsonErrorResult : JsonResult 
{ 
    private readonly HttpStatusCode _statusCode; 

    public JsonErrorResult(object json) : this(json, HttpStatusCode.InternalServerError) 
    { 
    } 

    public JsonErrorResult(object json, HttpStatusCode statusCode) : base(json) 
    { 
     _statusCode = statusCode; 
    } 

    public override void ExecuteResult(ActionContext context) 
    { 
     context.HttpContext.Response.StatusCode = (int)_statusCode; 
     base.ExecuteResult(context); 
    } 

    public override Task ExecuteResultAsync(ActionContext context) 
    { 
     context.HttpContext.Response.StatusCode = (int)_statusCode; 
     return base.ExecuteResultAsync(context); 
    } 
} 

फिर अपने नियंत्रक में है, के रूप में वापसी निम्नानुसार है:

// Set a json object to return. The status code defaults to 500 
return new JsonErrorResult(new { message = "Sorry, an internal error occurred."}); 

// Or you can override the status code 
return new JsonErrorResult(new { foo = "bar"}, HttpStatusCode.NotFound); 
+1

इसके लिए धन्यवाद। – aman

संबंधित मुद्दे