ASP.NET MVC 사용자 지정 오류 처리 Application_ErrorGlobal.asax?
MVC 응용 프로그램의 오류를 확인할 수 있는 기본 코드가 있습니다.현재 제 프로젝트에는 다음과 같은 컨트롤러 이름의 컨트롤러가 있습니다.Error
메소드를 HTTPError404()
,HTTPError500()
,그리고.General()
은 모두 매개변수 " " " " " 를 사용합니다." 를 합니다.error
아래 코드를 사용하거나 수정합니다.데이터를 처리하기 위해 오류 컨트롤러에 전달하는 가장 좋은/적절한 방법은 무엇입니까?저는 가능한 한 강력한 해결책을 갖고 싶습니다.
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
Response.Clear();
HttpException httpException = exception as HttpException;
if (httpException != null)
{
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
switch (httpException.GetHttpCode())
{
case 404:
// page not found
routeData.Values.Add("action", "HttpError404");
break;
case 500:
// server error
routeData.Values.Add("action", "HttpError500");
break;
default:
routeData.Values.Add("action", "General");
break;
}
routeData.Values.Add("error", exception);
// clear error on server
Server.ClearError();
// at this point how to properly pass route data to error controller?
}
}
새 경로를 만드는 대신 컨트롤러/작업으로 리디렉션하고 쿼리 문자열을 통해 정보를 전달할 수 있습니다.예를 들어:
protected void Application_Error(object sender, EventArgs e) {
Exception exception = Server.GetLastError();
Response.Clear();
HttpException httpException = exception as HttpException;
if (httpException != null) {
string action;
switch (httpException.GetHttpCode()) {
case 404:
// page not found
action = "HttpError404";
break;
case 500:
// server error
action = "HttpError500";
break;
default:
action = "General";
break;
}
// clear error on server
Server.ClearError();
Response.Redirect(String.Format("~/Error/{0}/?message={1}", action, exception.Message));
}
그러면 컨트롤러는 원하는 모든 것을 받을 수 있습니다.
// GET: /Error/HttpError404
public ActionResult HttpError404(string message) {
return View("SomeView", message);
}
당신의 접근 방식에는 몇 가지 단점이 있습니다.이런 종류의 오류를 처리할 때는 루프를 사용할 때 매우 주의해야 합니다.또 다른 점은 404를 처리하기 위해 asp.net 파이프라인을 통과하기 때문에 모든 히트에 대한 세션 개체를 만들 수 있습니다.이는 많이 사용되는 시스템에서 문제(성능)가 될 수 있습니다.
"루티드 데이터를 오류 컨트롤러에 올바르게 전달하는 방법"이라는 첫 번째 질문에 답하려면 다음과 같이 하십시오.":
IController errorController = new ErrorController();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
그런 다음 ErrorController 클래스에서 다음과 같은 기능을 구현합니다.
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult Error(Exception exception)
{
return View("Error", exception);
}
그러면 예외가 보기로 푸시됩니다.보기 페이지는 다음과 같이 선언되어야 합니다.
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<System.Exception>" %>
오류를 표시하는 코드:
<% if(Model != null) { %> <p><b>Detailed error:</b><br /> <span class="error"><%= Helpers.General.GetErrorMessage((Exception)Model, false) %></span></p> <% } %>
다음은 예외 트리에서 모든 예외 메시지를 수집하는 기능입니다.
public static string GetErrorMessage(Exception ex, bool includeStackTrace)
{
StringBuilder msg = new StringBuilder();
BuildErrorMessage(ex, ref msg);
if (includeStackTrace)
{
msg.Append("\n");
msg.Append(ex.StackTrace);
}
return msg.ToString();
}
private static void BuildErrorMessage(Exception ex, ref StringBuilder msg)
{
if (ex != null)
{
msg.Append(ex.Message);
msg.Append("\n");
if (ex.InnerException != null)
{
BuildErrorMessage(ex.InnerException, ref msg);
}
}
}
Lion_cl에서 언급한 아약스 문제에 대한 해결책을 찾았습니다.
global.asax:
protected void Application_Error()
{
if (HttpContext.Current.Request.IsAjaxRequest())
{
HttpContext ctx = HttpContext.Current;
ctx.Response.Clear();
RequestContext rc = ((MvcHandler)ctx.CurrentHandler).RequestContext;
rc.RouteData.Values["action"] = "AjaxGlobalError";
// TODO: distinguish between 404 and other errors if needed
rc.RouteData.Values["newActionName"] = "WrongRequest";
rc.RouteData.Values["controller"] = "ErrorPages";
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
IController controller = factory.CreateController(rc, "ErrorPages");
controller.Execute(rc);
ctx.Server.ClearError();
}
}
오류 페이지 컨트롤러
public ActionResult AjaxGlobalError(string newActionName)
{
return new AjaxRedirectResult(Url.Action(newActionName), this.ControllerContext);
}
Ajax 리디렉션 결과
public class AjaxRedirectResult : RedirectResult
{
public AjaxRedirectResult(string url, ControllerContext controllerContext)
: base(url)
{
ExecuteResult(controllerContext);
}
public override void ExecuteResult(ControllerContext context)
{
if (context.RequestContext.HttpContext.Request.IsAjaxRequest())
{
JavaScriptResult result = new JavaScriptResult()
{
Script = "try{history.pushState(null,null,window.location.href);}catch(err){}window.location.replace('" + UrlHelper.GenerateContentUrl(this.Url, context.HttpContext) + "');"
};
result.ExecuteResult(context);
}
else
{
base.ExecuteResult(context);
}
}
}
아약스 요청확장
public static class AjaxRequestExtension
{
public static bool IsAjaxRequest(this HttpRequest request)
{
return (request.Headers["X-Requested-With"] != null && request.Headers["X-Requested-With"] == "XMLHttpRequest");
}
}
저는 이전에 MVC 앱에서 글로벌 오류 처리 루틴을 중앙 집중화하는 아이디어로 어려움을 겪었습니다.ASP.NET 포럼에 게시물이 있습니다.
asax의 오류를 없이 하며, 의적으컨없이트러롤 global.asax모응오로 합니다.[HandlerError]
속성, 또는 만지작거리는 것.customErrors
web.config 파일입니다.
MVC에서 오류를 처리하는 더 나은 방법은 HandleError 특성을 컨트롤러나 작업에 적용하고 Shared/Error.aspx 파일을 업데이트하여 원하는 작업을 수행하는 것입니다.해당 페이지의 Model 개체에는 ControllerName 및 ActionName과 함께 Exception 속성이 포함됩니다.
이것은 MVC를 위한 최선의 방법이 아닐 수도 있습니다(https://stackoverflow.com/a/9461386/5869805 ).
아래는 Application_Error에서 뷰를 렌더링하여 http 응답에 쓰는 방법입니다.리디렉션을 사용할 필요가 없습니다.이렇게 하면 서버에 대한 두 번째 요청이 방지되므로 브라우저의 주소 표시줄에 있는 연결은 그대로 유지됩니다.이것은 좋을 수도 있고 나쁠 수도 있습니다. 당신이 원하는 것에 따라 다릅니다.
Global.asax.cs
protected void Application_Error()
{
var exception = Server.GetLastError();
// TODO do whatever you want with exception, such as logging, set errorMessage, etc.
var errorMessage = "SOME FRIENDLY MESSAGE";
// TODO: UPDATE BELOW FOUR PARAMETERS ACCORDING TO YOUR ERROR HANDLING ACTION
var errorArea = "AREA";
var errorController = "CONTROLLER";
var errorAction = "ACTION";
var pathToViewFile = $"~/Areas/{errorArea}/Views/{errorController}/{errorAction}.cshtml"; // THIS SHOULD BE THE PATH IN FILESYSTEM RELATIVE TO WHERE YOUR CSPROJ FILE IS!
var requestControllerName = Convert.ToString(HttpContext.Current.Request.RequestContext?.RouteData?.Values["controller"]);
var requestActionName = Convert.ToString(HttpContext.Current.Request.RequestContext?.RouteData?.Values["action"]);
var controller = new BaseController(); // REPLACE THIS WITH YOUR BASE CONTROLLER CLASS
var routeData = new RouteData { DataTokens = { { "area", errorArea } }, Values = { { "controller", errorController }, {"action", errorAction} } };
var controllerContext = new ControllerContext(new HttpContextWrapper(HttpContext.Current), routeData, controller);
controller.ControllerContext = controllerContext;
var sw = new StringWriter();
var razorView = new RazorView(controller.ControllerContext, pathToViewFile, "", false, null);
var model = new ViewDataDictionary(new HandleErrorInfo(exception, requestControllerName, requestActionName));
var viewContext = new ViewContext(controller.ControllerContext, razorView, model, new TempDataDictionary(), sw);
viewContext.ViewBag.ErrorMessage = errorMessage;
//TODO: add to ViewBag what you need
razorView.Render(viewContext, sw);
HttpContext.Current.Response.Write(sw);
Server.ClearError();
HttpContext.Current.Response.End(); // No more processing needed (ex: by default controller/action routing), flush the response out and raise EndRequest event.
}
보다
@model HandleErrorInfo
@{
ViewBag.Title = "Error";
// TODO: SET YOUR LAYOUT
}
<div class="">
ViewBag.ErrorMessage
</div>
@if(Model != null && HttpContext.Current.IsDebuggingEnabled)
{
<div class="" style="background:khaki">
<p>
<b>Exception:</b> @Model.Exception.Message <br/>
<b>Controller:</b> @Model.ControllerName <br/>
<b>Action:</b> @Model.ActionName <br/>
</p>
<div>
<pre>
@Model.Exception.StackTrace
</pre>
</div>
</div>
}
Application_Ajax 요청에 문제가 있는 동안 오류가 발생했습니다.Ajax가 호출한 Action에서 오류를 처리하면 결과 컨테이너 내부에 오류 보기가 표시됩니다.
Brian, 이 접근 방식은 Ajax가 아닌 요청에 적합하지만 Lion_cl에서 언급했듯이 Ajax 호출 중에 오류가 발생하면 Share/Error.aspx 보기(또는 사용자 지정 오류 페이지 보기)가 Ajax 호출자에게 반환됩니다. 사용자는 오류 페이지로 리디렉션되지 않습니다.
경로 페이지에서 리디렉션할 때 다음 코드를 사용합니다.예외 사용.예외가 아닌 메시지입니다.Coz 예외 쿼리 문자열이 쿼리 문자열 길이를 확장하면 오류가 발생합니다.
routeData.Values.Add("error", exception.Message);
// clear error on server
Server.ClearError();
Response.RedirectToRoute(routeData.Values);
다음과 같은 오류 처리 방법에 문제가 있습니다.web.config의 경우:
<customErrors mode="On"/>
오류 처리기가 오류 보기를 검색하고 있습니다.shtml 및 예외 뒤에만 Application_Error global.asax에 대한 제어 흐름 단계
System.잘못된 작동예외:'Error' 보기 또는 해당 마스터를 찾을 수 없거나 검색된 위치를 지원하는 보기 엔진이 없습니다.검색된 위치는 ~/Views/home/Error.aspx ~/Views/Shared/Error.aspx ~/Views/Home/Error.cshtml ~/Views/Shared/Error.cshtml ~/Views/Error.cml ~/Views/Error.s/Error.s/Error/Vmlash/Vmlash/Vml 시스템에서 검색되었습니다.웹.MVC.결과를 봅니다.FindView(컨트롤러 컨텍스트) ....................
그렇게
Exception exception = Server.GetLastError();
Response.Clear();
HttpException httpException = exception as HttpException;
httpException은 항상 null이고 그 다음에 customErrors mode="On" :( 그러면 오해의 소지가 있습니다.<customErrors mode="Off"/>
또는<customErrors mode="RemoteOnly"/>
사용자에게 customErrors html이 표시되면 customErrors mode="On" 이 코드도 잘못 표시됩니다.
이 코드의 또 다른 문제는
Response.Redirect(String.Format("~/Error/{0}/?message={1}", action, exception.Message));
실제 오류 코드(402,403 등) 대신 코드 302가 포함된 페이지 반환
언급URL : https://stackoverflow.com/questions/1171035/asp-net-mvc-custom-error-handling-application-error-global-asax
'programing' 카테고리의 다른 글
ListBox 항목에 대한 WPF 데이터 템플릿 변경(선택한 경우) (0) | 2023.05.29 |
---|---|
Perl 배열에 특정 값이 포함되어 있는지 확인하려면 어떻게 해야 합니까? (0) | 2023.05.29 |
부울을 사용하는 이유.ToString 출력 "참"이 아닌 "참" (0) | 2023.05.24 |
유형에서 새 개체 인스턴스를 만드는 방법 (0) | 2023.05.24 |
데이터 주석이 있는 DateTime 형식을 할당하시겠습니까? (0) | 2023.05.24 |