ASP.NET MVC Ajax 오류 처리


117

jquery ajax가 작업을 호출 할 때 컨트롤러에서 throw되는 예외를 어떻게 처리합니까?

예를 들어, 디버그 모드에서 예외 메시지를 표시하거나 정상적인 오류 메시지 만 표시하는 ajax 호출 중에 모든 종류의 서버 예외에서 실행되는 전역 자바 스크립트 코드를 원합니다.

클라이언트 측에서는 ajax 오류에 대한 함수를 호출합니다.

서버 측에서 사용자 지정 작업 필터를 작성해야합니까?


8
좋은 예는 beckelmans 게시물 을 참조하십시오 . 이 게시물에 대한 Darins의 답변은 좋지만 오류에 대한 올바른 상태 코드를 설정하지 않았습니다.
Dan

6
슬프게도 그 링크는 이제 끊어졌습니다
Chris Nevill 2014 년

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 오류 처리기에서 잡을 수 있도록 throw해야하는 특정 방법이 있습니까?
Shawn Mclean 2011 년

1
@Lol coder, 컨트롤러 작업 내에서 예외를 어떻게 던지더라도 서버는 500 상태 코드를 반환하고 error콜백이 실행됩니다.
Darin Dimitrov 2011 년

고마워, 완벽 해. 내가 찾던 바로 그것.
Shawn Mclean 2011 년

1
500의 상태 코드가 틀리지 않습니까? 이 chap을 인용하면 broadcast.oreilly.com/2011/06/… : "4xx 오류는 내가 엉망이되었음을 의미하고 5xx는 당신이 엉망이되었음을 의미한다는 것을 깨닫지 못함"-여기서 내가 클라이언트이고 당신은 서버입니다.
Chris Nevill 2014

이 답변은 최신 버전의 ASPNET에 대해 여전히 유효합니까?
gog

73

인터넷 검색 후 MVC Action Filter를 기반으로 간단한 예외 처리를 작성합니다.

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>

마지막으로 사용자 지정 오류를 켜야합니다. 그리고 그것을 즐기십시오 :)


Firebug에서 오류를 볼 수 있지만 오류 페이지로 리디렉션되지 않습니다.?
user2067567 2013-04-26

1
감사합니다!
Ajax

2
멋진 대답! : D
Leniel Maccaferri 2014 년

1
나는 "Request.IsAjaxRequest ()"가 때때로 그렇게 신뢰할 수 없다고 생각합니다.
윌 황

디버그 구성의 경우 항상 작동하지만 릴리스 구성에서는 항상 작동하지 않으며 대신 html을 반환합니다.
Hitendra

9

불행히도 어떤 답변도 나에게 좋지 않습니다. 놀랍게도 솔루션은 훨씬 간단합니다. 컨트롤러에서 반환 :

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

그리고 원하는대로 클라이언트에서 표준 HTTP 오류로 처리하십시오.



첫 번째 인수를 int. 또한 이렇게하면 결과가 ajax success핸들러가 아닌 핸들러에 전달됩니다 error. 이것이 예상 된 동작입니까?
Jonathan Wood

4

나는 시간이 부족하고 잘 작동했기 때문에 빠른 해결책을 찾았습니다. 더 나은 옵션은 예외 필터를 사용하는 것이라고 생각하지만 간단한 솔루션이 필요한 경우 내 솔루션이 도움이 될 수 있습니다.

나는 다음을했다. 컨트롤러 메서드에서 Data 내부에 "Success"속성이있는 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 호출에서 예외가 있는지 알기 위해이 속성을 요청했습니다.

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

aleho의 응답에 따라 여기에 완전한 예가 있습니다. 그것은 매력처럼 작동하고 매우 간단합니다.

컨트롤러 코드

[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

클라이언트 측에서 ajax 호출의 오류를 처리하기 error위해 ajax 호출 옵션에 함수를 할당합니다 .

기본값을 전역으로 설정하려면 http://api.jquery.com/jQuery.ajaxSetup에 설명 된 함수를 사용할 수 있습니다 .


4 년 전에 제가 한 대답이 갑자기 반대표를 받나요? 누구든지 이유를 알려줄 사람이 있습니까?
Brian Ball

1
SOF에 연락하여 DBA에게 누가 반대표를 주 었는지 질문하십시오. 다음으로, 설명 할 수 있도록 그 개인에게 메시지를 보냅니다. 아무도 이유를 말할 수 없습니다.
JoshYates1980
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.