2013-05-20 2 views
1

오류 페이지로 리디렉션하지 않고 동일한보기에서 표시하는 대신 던진 예외를 표시하는 일반적인 방법을 검색합니다. 나는 이것을 아래에서 시도했다 :동일한보기에서 예외를 표시하는 방법은 무엇입니까?

1) 나는 global.asax에서 사용자 정의 필터를 추가하고 public override void OnException(ExceptionContext filterContext)을 내 Attribute 클래스에서 덮어 씌우는 것으로 먼저 처리하려고 시도했지만 그런 식으로 나는 filterContext.Result를 채울 수 없었다. 보기의 이전 모델에 연결할 수 없기 때문에 오류 페이지로 리디렉션 할 수는 있지만 원하는 것은 아닙니다.

2) 그런 다음 내 BaseController에서 예외를 잡으려고했습니다 (모든 컨트롤러가 그걸 상속받습니다). 다시 내 컨트롤러에서 public override void OnException(ExceptionContext filterContext)을 덮어 쓰고 예외 정보 등을 ViewBag에 넣은 다음 filterContext.HttpContext.Response.Redirect(filterContext.RequestContext.HttpContext.Request.Path);에 의해 동일한보기로 페이지를 리디렉션했습니다. 그러나 다른 방법을 생각할 수 없도록 ViewBag 내용이 리디렉션 된 페이지에서 손실 되었습니까?

어떻게하면됩니까? 내 BaseController에 쓴 코드 샘플은 다음과 같습니다 :

protected override void OnException(ExceptionContext filterContext) { 
    var controllerName = (string)filterContext.RouteData.Values["controller"]; 
    var actionName = (string)filterContext.RouteData.Values["action"]; 

    //filterContext.Result = new ViewResult 
    //{ 
    // ViewName = actionName, 
    // ViewData = new ViewDataDictionary<??>(??), 
    // TempData = filterContext.Controller.TempData, 
    //}; 

    filterContext.ExceptionHandled = true; 
    filterContext.HttpContext.Response.Clear(); 

    filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 
    ModelState.AddModelError("Error", filterContext.Exception.Message); 
    ViewBag.das = "dasd"; 
    filterContext.HttpContext.Response.Redirect(filterContext.RequestContext.HttpContext.Request.Path); 
} 
+0

이봐, 질문을 다시 포맷을 고려하시기 바랍니다. 그것은 당신이 읽는 것을 돕고 싶어하는 사람들에게 어려운 텍스트의 벽처럼 보입니다. 직접 읽어보십시오. –

+0

그것을 다시 포맷했습니다. 답장을위한 Thx – sotn

답변

0

이전에 해결책을 발견하고 다른 사람들을 도울 수 있도록 솔루션을 추가했습니다. 나는 오류를 표시하는 TempData 및 _Layout를 사용

public class ErrorHandlerAttribute : HandleErrorAttribute 
{ 
    private ILog _logger; 

    public ErrorHandlerAttribute() 
    { 
     _logger = Log4NetManager.GetLogger("MyLogger"); 
    } 

    public override void OnException(ExceptionContext filterContext) 
    { 
     if (filterContext.ExceptionHandled) 
     { 
      return; 
     } 

     if (!ExceptionType.IsInstanceOfType(filterContext.Exception)) 
     { 
      return; 
     } 

     // if the request is AJAX return JSON else view. 
     if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest") 
     { 
      filterContext.Result = new JsonResult 
      { 
       JsonRequestBehavior = JsonRequestBehavior.AllowGet, 
       Data = new 
       { 
        error = true, 
        message = filterContext.Exception.Message 
       } 
      }; 
      filterContext.HttpContext.Response.StatusCode = 500; 
     } 

     // log the error using log4net. 
     _logger.Error(filterContext.Exception.Message, filterContext.Exception); 

     filterContext.ExceptionHandled = true; 
     filterContext.HttpContext.Response.Clear(); 

     filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 

     if (filterContext.HttpContext.Request.Headers["X-Requested-With"] != "XMLHttpRequest") 
     { 
      if (filterContext.Controller.TempData["AppError"] != null) 
      { 
       //If there is a loop it will break here. 
       filterContext.Controller.TempData["AppError"] = filterContext.Exception.Message; 
       filterContext.HttpContext.Response.Redirect("/"); 
      } 
      else 
      { 
       int httpCode = new HttpException(null, filterContext.Exception).GetHttpCode(); 

       switch (httpCode) 
       { 
        case 401: 
         filterContext.Controller.TempData["AppError"] = "Not Authorized"; 
         filterContext.HttpContext.Response.Redirect("/"); 
         break; 
        case 404: 
         filterContext.Controller.TempData["AppError"] = "Not Found"; 
         filterContext.HttpContext.Response.Redirect("/"); 
         break; 
        default: 
         filterContext.Controller.TempData["AppError"] = filterContext.Exception.Message; 
         //Redirect to the same page again(If error occurs again, it will break above) 
         filterContext.HttpContext.Response.Redirect(filterContext.RequestContext.HttpContext.Request.RawUrl); 
         break; 
       } 
      } 
     } 
    } 
} 

그리고의 Global.asax에서

:

protected void Application_Error(object sender, EventArgs e) 
    { 
     var httpContext = ((MvcApplication)sender).Context; 
     var ex = Server.GetLastError(); 

     httpContext.ClearError(); 
     httpContext.Response.Clear(); 
     httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500; 
     httpContext.Response.TrySkipIisCustomErrors = true; 

     var routeData = new RouteData(); 
     routeData.Values["controller"] = "ControllerName"; 
     routeData.Values["action"] = "ActionName"; 
     routeData.Values["error"] = "404"; //Handle this url paramater in your action 
     ((IController)new AccountController()).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData)); 
    } 
0

어쩌면 당신이 무엇이든에 컨트롤러 액션이 요청을 처리 설정, 사용하려는 뷰의 이름을 가지고 당신의 BaseController 클래스의 속성을 설정할 수 있습니다 . 그런 다음 OnException()에서 컨트롤러 이름을 나타내는 View을 반환하는 컨트롤러 작업으로 리디렉션되는 메서드가있을 수 있습니까? 각 컨트롤러 동작은 다른 뷰를 수행하기 전에 기본 뷰 이름을 설정해야합니다.이 뷰는 뷰를 호출 할 때 어떤 뷰가 호출되는지, 그리고 어떤 뷰가 호출되었는지를 알고 있기 때문입니다.

BaseController 동작을 새로해야을 반환해야합니다.

경로에 어떤 오류 정보를 표시할지 설정할 수있는 일종의 선택적 매개 변수가 구성에 필요하지 않을 수도 있습니다. 예를 들어, 기본 경로에서 :

routes.MapRoute(RouteNames.Default, 
       "{controller}/{action}/{id}", 
       new {controller = "Home", action = "Index", id = "", errorInfo = UrlParameter.Optional} 

BaseController :

protected ActionResult ErrorHandler() 
{ 
    ViewBag.das = (string)filterContext.RouteData.Values["errorInfo"]; 
    return View(ViewName); 
} 

protected string ViewName { get; set; } 

protected void GoToErrorView(ExceptionContext context, string exceptionData) 
{ 
    var actionName = "ErrorHandler"; 
    var newVals = new RouteValueDictionary(); 
    newVals.Add("errorInfo", exceptionData); 
    this.RedirectToAction(actionName, newVals); 
} 

BaseController.OnException()에서 : 특별히 ViewResultActionResult을 반환하는 BaseController에서 상속 특정 컨트롤러에서

// ... 
    filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 
    ModelState.AddModelError("Error", filterContext.Exception.Message); 
    // anything else you need to do to prepare what you want to display 
    string exceptionData = SomeSortOfDataYouWantToPassIntoTheView; 
    this.GoToErrorView(filterContext, exceptionData); 
} 

:

[HttpGet] 
public ActionResult Index() 
{ 
    ViewName = <set whatever view name you want to here> 
    // code here, including preparing the Model 
    // ... 
    var model = new MyViewModel(); 
    model.SomethingIWantToGiveTheView = someDataThatItNeeds; 
    // ... 

    return View(<model name>, model); 
} 
관련 문제