IT Share you

ASP.NET MVC의 오류 처리

shareyou 2020. 11. 21. 08:43
반응형

ASP.NET MVC의 오류 처리


ASP.NET MVC의 컨트롤러에서 발생한 예외를 어떻게 올바르게 처리 할 수 ​​있습니까? HandleError속성은 MVC 인프라에서 발생한 예외 만 처리하고 내 코드에서 발생한 예외는 처리하지 않는 것 같습니다.

이 web.config 사용

<customErrors mode="On">
    <error statusCode="401" redirect="/Errors/Http401" />
</customErrors>

다음 코드로

namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            // Force a 401 exception for testing
            throw new HttpException(401, "Unauthorized");
        }
    }
}

내가 원하는 결과를 얻지 못합니다. 대신 실제 오류 정보를 보려면 web.config를 수정하라는 일반적인 ASP.NET 오류 페이지가 표시됩니다. 그러나 예외를 throw하는 대신 잘못된 View를 반환하면 /Shared/Views/Error.aspx 페이지가 표시됩니다.

return View("DoesNotExist");

위에서 한 것처럼 컨트롤러 내에서 예외를 던지는 것은 모든 HandleError기능 을 우회하는 것처럼 보이 므로 오류 페이지를 만드는 올바른 방법은 무엇이며 MVC 인프라를 어떻게 잘 사용할 수 있습니까?


Controller.OnException(ExceptionContext context). 재정의하십시오.

protected override void OnException(ExceptionContext filterContext)
{
    // Bail if we can't do anything; app will crash.
    if (filterContext == null)
        return;
        // since we're handling this, log to elmah

    var ex = filterContext.Exception ?? new Exception("No further information exists.");
    LogException(ex);

    filterContext.ExceptionHandled = true;
    var data = new ErrorPresentation
        {
            ErrorMessage = HttpUtility.HtmlEncode(ex.Message),
            TheException = ex,
            ShowMessage = !(filterContext.Exception == null),
            ShowLink = false
        };
    filterContext.Result = View("ErrorPage", data);
}

kazimanzurrashaid 덕분에 Global.asax.cs에서 내가 한 일이 있습니다.

protected void Application_Error()
{
    Exception unhandledException = Server.GetLastError();
    HttpException httpException = unhandledException as HttpException;
    if (httpException == null)
    {
        Exception innerException = unhandledException.InnerException;
        httpException = innerException as HttpException;
    }

    if (httpException != null)
    {
        int httpCode = httpException.GetHttpCode();
        switch (httpCode)
        {
            case (int) HttpStatusCode.Unauthorized:
                Response.Redirect("/Http/Error401");
                break;
        }
    }
}

지원해야하는 추가 HTTP 오류 코드를 기반으로 HttpContoller에 더 많은 페이지를 추가 할 수 있습니다.


HandleError 속성은 MVC 인프라에서 발생한 예외 만 처리하고 내 코드에서 발생한 예외는 처리하지 않는 것 같습니다.

그건 틀렸어요. 실제로 HandleError는 자신의 코드 나 자신의 코드에서 호출 한 코드에서 발생한 예외 만 "처리"합니다. 즉, 작업이 호출 스택에있는 예외 만 있습니다.

당신이보고있는 행동에 대한 실제 설명은 당신이 던지는 특정 예외입니다. HandleError는 HttpException과 다르게 작동합니다. 소스 코드에서 :

        // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
        // ignore it.
        if (new HttpException(null, exception).GetHttpCode() != 500) {
            return;
        }

I dont think you will be able to show specific ErrorPage based upon the HttpCode with the HandleError Attribute and I would prefer to use an HttpModule for this purpose. Assuming that I have folder "ErrorPages" where diffferent page exists for each specific error and the mapping is specifed in the web.config same as the regular web form application. And the following is the code which is used to show the error page:

public class ErrorHandler : BaseHttpModule{

public override void OnError(HttpContextBase context)
{
    Exception e = context.Server.GetLastError().GetBaseException();
    HttpException httpException = e as HttpException;
    int statusCode = (int) HttpStatusCode.InternalServerError;

    // Skip Page Not Found and Service not unavailable from logging
    if (httpException != null)
    {
        statusCode = httpException.GetHttpCode();

        if ((statusCode != (int) HttpStatusCode.NotFound) && (statusCode != (int) HttpStatusCode.ServiceUnavailable))
        {
            Log.Exception(e);
        }
    }

    string redirectUrl = null;

    if (context.IsCustomErrorEnabled)
    {
        CustomErrorsSection section = IoC.Resolve<IConfigurationManager>().GetSection<CustomErrorsSection>("system.web/customErrors");

        if (section != null)
        {
            redirectUrl = section.DefaultRedirect;

            if (httpException != null)
            {
                if (section.Errors.Count > 0)
                {
                    CustomError item = section.Errors[statusCode.ToString(Constants.CurrentCulture)];

                    if (item != null)
                    {
                        redirectUrl = item.Redirect;
                    }
                }
            }
        }
    }

    context.Response.Clear();
    context.Response.StatusCode = statusCode;
    context.Response.TrySkipIisCustomErrors = true;

    context.ClearError();

    if (!string.IsNullOrEmpty(redirectUrl))
    {
        context.Server.Transfer(redirectUrl);
    }
}

}


One other possibility (not true in your case) that others reading this may be experiencing is that your error page is throwing an error itself, or is not implementing :

 System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>

If this is the case then you will get the default error page (otherwise you'd get an infinite loop because it would keep trying to send itself to your custom error page). This wasn't immediately obvious to me.

This model is the model sent to the error page. If your error page uses the same master page as the rest of your site and requires any other model information then you will need to either create your own [HandleError] type of attribute or override OnException or something.


I chose the Controller.OnException() approach, which to me is the logical choice - since I've chosen ASP.NET MVC, I prefer to stay at the framework-level, and avoid messing with the underlying mechanics, if possible.

I ran into the following problem:

If the exception occurs within the view, the partial output from that view will appear on screen, together with the error-message.

I fixed this by clearing the response, before setting filterContext.Result - like this:

        filterContext.HttpContext.Response.Clear(); // gets rid of any garbage
        filterContext.Result = View("ErrorPage", data);

Hope this saves somebody else some time :-)


     protected override void OnException (ExceptionContext filterContext )
    {
        if (filterContext != null && filterContext.Exception != null)
        {
            filterContext.ExceptionHandled = true;
            this.View("Error").ViewData["Exception"] = filterContext.Exception.Message;
            this.View("Error").ExecuteResult(this.ControllerContext);
        }
    }

Jeff Atwood's User Friendly Exception Handling module works great for MVC. You can configure it entirely in your web.config, with no MVC project source code changes at all. However, it needs a small modification to return the original HTTP status rather than a 200 status. See this related forum post.

Basically, in Handler.vb, you can add something like:

' In the header...
Private _exHttpEx As HttpException = Nothing

' At the top of Public Sub HandleException(ByVal ex As Exception)...
HttpContext.Current.Response.StatusCode = 500
If TypeOf ex Is HttpException Then
    _exHttpEx = CType(ex, HttpException)
    HttpContext.Current.Response.StatusCode = _exHttpEx.GetHttpCode()
End If

참고URL : https://stackoverflow.com/questions/812235/error-handling-in-asp-net-mvc

반응형