ASP.NET MVC Ajax Hata işleme


117

Jquery ajax bir eylem çağırdığında bir denetleyicide atılan istisnaları nasıl idare edebilirim?

Örneğin, bir ajax çağrısı sırasında herhangi bir sunucu istisnasında çalıştırılan ve hata ayıklama modunda veya sadece normal bir hata mesajındaysa istisna mesajını görüntüleyen global bir javascript kodu istiyorum.

İstemci tarafında, ajax hatası için bir fonksiyon çağıracağım.

Sunucu tarafında, özel bir eylem filtresi yazmam gerekir mi?


8
İyi bir örnek için Beckelmans gönderisine bakın . Darins'in bu gönderiye cevabı iyidir, ancak bir hata için doğru durum kodunu ayarlamayın.
Dan

6
Ne yazık ki bu bağlantı artık koptu
Chris Nevill

Yanıtlar:


161

Sunucu, 200'den farklı bir durum kodu gönderirse, hata geri araması yürütülür:

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

ve genel bir hata işleyiciyi kaydetmek için şu $.ajaxSetup()yöntemi kullanabilirsiniz :

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

Başka bir yol da JSON kullanmaktır. Böylece, sunucuda istisnayı yakalayan ve bunları JSON yanıtına dönüştüren özel bir eylem filtresi yazabilirsiniz:

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

ve ardından denetleyici eyleminizi şu öznitelikle süsleyin:

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

ve sonunda onu çağırın:

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

1
Bunun için teşekkürler, ikincisi aradığım şeydi. Öyleyse, asp.net mvc istisnası için, jquery hata işleyicisi tarafından yakalanabilmesi için onu atmamın belirli bir yolu var mı?
Shawn Mclean

1
@Lol coder, denetleyici eylemi içinde nasıl bir istisna atarsanız koyun, sunucu 500 durum kodunu döndürür ve errorgeri arama yürütülür.
Darin Dimitrov

Teşekkürler, mükemmel, tam da aradığım şey.
Shawn Mclean

1
500 Durum kodu yanlış olmaz mıydı? Bu bölümden alıntı yapmak için, broadcast.oreilly.com/2011/06/… : "Bir 4xx hatasının, benim berbat olduğum ve 5xx'in de senin battığın anlamına geldiğinin farkına varmamak" - burada ben müşteri ve siz sunucuyuz.
Chris Nevill

Bu yanıt, ASPNET'in daha yeni sürümleri için hala geçerli mi?
GOG

73

Googling işleminden sonra, MVC Eylem Filtresine dayalı basit bir İstisna işleme yazıyorum:

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

ve global.ascx olarak yazın:

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

ve sonra bu komut dosyasını mizanpaj veya Ana sayfaya yazın:

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

Son olarak, özel hatayı açmalısınız. ve sonra tadını çıkarın :)


Firebug'da hatayı görebiliyorum ama Hata sayfasına yönlendirilmiyor.?
user2067567

1
Bunun için teşekkürler! ajax isteklerinde filtrelemesi olarak yanıt IMO olarak işaretlenmeli ve HandleErrorAttribute'un miras
aldığından

2
Harika cevap! : D
Leniel Maccaferri

1
Bence "Request.IsAjaxRequest ()" bazen o kadar güvenilir değil.
Will Huang

Hata ayıklama yapılandırması için her zaman çalışır, ancak her zaman Sürüm yapılandırmasında çalışmaz ve bunun yerine html döndürür, bunun yerine herhangi birinin böyle bir durum için geçici çözümü var mı?
Hitendra

9

Ne yazık ki, cevapların hiçbiri benim için iyi değil. Şaşırtıcı bir şekilde çözüm çok daha basit. Denetleyiciden dönüş:

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

Ve bunu istemcide istediğiniz gibi standart HTTP hatası olarak ele alın.


@Will Huang: istisna örneğinin adı
schmendrick

İlk argümanı atmam gerekiyor int. Ayrıca, bunu yaptığımda, sonuç ajax successişleyiciye değil, errorişleyiciye iletiliyor. Bu beklenen davranış mı?
Jonathan Wood

4

Hızlı bir çözüm yaptım çünkü zamanım kısaydı ve iyi çalıştı. Daha iyi seçeneğin İstisna Filtresi kullanmak olduğunu düşünmeme rağmen, basit bir çözüme ihtiyaç duyulması durumunda çözümüm yardımcı olabilir.

Ben aşağıdakileri yaptım. Denetleyici yönteminde, Veri içinde "Success" özelliğine sahip bir JsonResult döndürdüm:

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

Daha sonra ajax aramasında, bu mülkün bir istisnam olup olmadığını bilmesini istedim:

$.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.')
    }
});

Bu yardımcı olur umarım. Mutlu kod! : P


4

Aleho'nun cevabına uygun olarak işte tam bir örnek. Bir cazibe gibi çalışır ve süper basittir.

Denetleyici kodu

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

Görünümdeki Javascript kodu

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

Umarım bu başka birine yardımcı olur!


0

İstemci tarafındaki ajax çağrılarından gelen hataları ele almak için error, ajax çağrısının seçeneğine bir işlev atarsınız .

Global olarak bir varsayılan ayarlamak için, burada açıklanan işlevi kullanabilirsiniz: http://api.jquery.com/jQuery.ajaxSetup .


4 yıl önce verdiğim bir cevap aniden olumsuz bir oy mu alıyor? Bir neden vermek isteyen var mı?
Brian Topu

1
SOF ile iletişime geçin ve DBA'dan kimin olumsuz oyu verdiğini sorgulamasını isteyin. Ardından, açıklayabilmeleri için o kişiye mesaj atın. Herkes nedenini açıklayamaz.
JoshYates1980
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.