ASP.NET 사용자 정의 오류 페이지 -Server.GetLasterRor () IS NULL
-
19-08-2019 - |
문제
내 응용 프로그램에 맞는 사용자 정의 오류 페이지가 있습니다.
<customErrors mode="On" defaultRedirect="~/errors/GeneralError.aspx"
/>
Global.asax에서 Application_error ()에서 다음 코드는 예외 세부 사항을 얻기 위해 작동합니다.
Exception ex = Server.GetLastError();
if (ex != null)
{
if (ex.GetBaseException() != null)
ex = ex.GetBaseException();
}
오류 페이지에 도달 할 때 (~/errors/generalerror.aspx.cs), server.getLasterror ()가 null입니다.
Global.asax.cs보다 오류 페이지에서 예외 세부 정보를 얻을 수있는 방법이 있습니까?
Vista/IIS7의 ASP.NET 3.5
해결책
내 web.config 설정에서 더 자세히 살펴보면 주석 중 하나 이 게시물은 매우 도움이됩니다
ASP.NET 3.5 SP1에는 새로운 매개 변수 리디렉션 모드가 있습니다.
그래서 우리는 수정할 수 있습니다 customErrors
이 매개 변수를 추가하려면 :
<customErrors mode="RemoteOnly" defaultRedirect="~/errors/GeneralError.aspx" redirectMode="ResponseRewrite" />
그만큼 ResponseRewrite
모드를 사용하면 브라우저를 리디렉션하지 않고«오류 페이지»를로드 할 수 있으므로 URL은 동일하게 유지되며 중요한 것은 예외 정보가 손실되지 않습니다.
다른 팁
좋아,이 게시물을 찾았습니다.http://msdn.microsoft.com/en-us/library/aa479319.aspx
이 매우 예시적인 다이어그램으로 :
(원천: Microsoft.com)
본질적으로, 이러한 예외 세부 정보를 얻으려면 나중에 사용자 정의 오류 페이지에서 검색하려면 Global.asax에 직접 저장해야합니다.
가장 좋은 방법은 Global.asax에서 대부분의 작업을 수행하는 것 같습니다. 사용자 정의 오류 페이지는 논리가 아닌 유용한 콘텐츠를 처리합니다.
Nailitdown과 Victor가 말한 것의 조합. 선호하는/가장 쉬운 방법은 Global.asax를 사용하여 오류를 저장 한 다음 사용자 정의 오류 페이지로 리디렉션하는 것입니다.
Global.asax:
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
Exception ex = Server.GetLastError();
Application["TheException"] = ex; //store the error for later
Server.ClearError(); //clear the error so we can continue onwards
Response.Redirect("~/myErrorPage.aspx"); //direct user to error page
}
또한 설정해야합니다 web.config:
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="~/myErrorPage.aspx">
</customErrors>
</system.web>
그리고 마지막으로, 당신이 저장 한 예외로 필요한 모든 것을하십시오. 오류 페이지:
protected void Page_Load(object sender, EventArgs e)
{
// ... do stuff ...
//we caught an exception in our Global.asax, do stuff with it.
Exception caughtException = (Exception)Application["TheException"];
//... do stuff ...
}
같은 것을 사용해보십시오 Server.Transfer("~/ErrorPage.aspx");
내에서 Application_Error()
Global.asax.cs의 방법
그런 다음 내부에서 Page_Load()
Of ErrorPage.aspx.cs 당신은 다음과 같은 일을해도 괜찮을 것입니다. Exception exception = Server.GetLastError().GetBaseException();
Server.Transfer()
예외가 계속 매달려있는 것 같습니다.
여기에는 몇 가지 좋은 답변이 있지만 오류 페이지에 시스템 예외 메시지를 표시하는 것이 좋지 않다는 점을 지적해야합니다. 악의적 인 사용자에게 그렇게하고 싶지 않은 일을 실수로 공개 할 수 있습니다. 예를 들어 SQL Server Exception 메시지는 매우 장점이며 오류가 발생하면 데이터베이스의 사용자 이름, 암호 및 스키마 정보를 제공 할 수 있습니다. 해당 정보를 최종 사용자에게 표시해서는 안됩니다.
여기 내 해결책이 있습니다 ..
Global.aspx에서 :
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
//direct user to error page
Server.Transfer("~/ErrorPages/Oops.aspx");
}
에서 oops.aspx :
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadError(Server.GetLastError());
}
protected void LoadError(Exception objError)
{
if (objError != null)
{
StringBuilder lasterror = new StringBuilder();
if (objError.Message != null)
{
lasterror.AppendLine("Message:");
lasterror.AppendLine(objError.Message);
lasterror.AppendLine();
}
if (objError.InnerException != null)
{
lasterror.AppendLine("InnerException:");
lasterror.AppendLine(objError.InnerException.ToString());
lasterror.AppendLine();
}
if (objError.Source != null)
{
lasterror.AppendLine("Source:");
lasterror.AppendLine(objError.Source);
lasterror.AppendLine();
}
if (objError.StackTrace != null)
{
lasterror.AppendLine("StackTrace:");
lasterror.AppendLine(objError.StackTrace);
lasterror.AppendLine();
}
ViewState.Add("LastError", lasterror.ToString());
}
}
protected void btnReportError_Click(object sender, EventArgs e)
{
SendEmail();
}
public void SendEmail()
{
try
{
MailMessage msg = new MailMessage("webteam", "webteam");
StringBuilder body = new StringBuilder();
body.AppendLine("An unexcepted error has occurred.");
body.AppendLine();
body.AppendLine(ViewState["LastError"].ToString());
msg.Subject = "Error";
msg.Body = body.ToString();
msg.IsBodyHtml = false;
SmtpClient smtp = new SmtpClient("exchangeserver");
smtp.Send(msg);
}
catch (Exception ex)
{
lblException.Text = ex.Message;
}
}
여기에 모두가 누락되었다고 생각한다는 중요한 고려 사항은로드 밸런싱 (웹 팜) 시나리오입니다. Global.asax를 실행하는 서버가 사용자 정의 오류 페이지 실행에 관한 서버와 다를 수 있으므로 응용 프로그램에서 예외 객체를 보관하는 것은 신뢰할 수 없습니다.
나는 여전히 웹 팜 구성 에서이 문제에 대한 신뢰할 수있는 솔루션을 찾고 있으며/또는 MS의 좋은 설명이 Server.getLasterror를 사용하여 사용자 정의 오류 페이지에서 예외를 선택할 수없는 이유에 대한 좋은 설명을 찾고 있습니다. Global.asax Application_error에서.
추신 : 먼저 잠금을 잠금하고 잠금 해제하지 않고 응용 프로그램 컬렉션에 데이터를 저장하는 것은 안전하지 않습니다.
이것은 아래의 두 가지 주제와 관련하여 오류 페이지에서 gethtmlerrormessage와 세션을 모두 원합니다.
responseerewrite 후 세션은 null입니다
httpcontext.session null이 redirectMode = responseereWrite가있는 이유는 무엇입니까?
나는 필요없는 해결책을 시도하고 보았다 Server.Transfer() or Response.Redirect()
먼저 : web.config에서 responseerewrite를 제거하십시오
web.config
<customErrors defaultRedirect="errorHandler.aspx" mode="On" />
그런 다음 global.asax
void Application_Error(object sender, EventArgs e)
{
if(Context.IsCustomErrorEnabled)
{
Exception ex = Server.GetLastError();
Application["TheException"] = ex; //store the error for later
}
}
그런 다음 ErrorHandler.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
string htmlErrorMessage = string.Empty ;
Exception ex = (Exception)Application["TheException"];
string yourSessionValue = HttpContext.Current.Session["YourSessionId"].ToString();
//continue with ex to get htmlErrorMessage
if(ex.GetHtmlErrorMessage() != null){
htmlErrorMessage = ex.GetHtmlErrorMessage();
}
// continue your code
}
참고 문헌
http://www.developer.com/net/asp/article.php/3299641/servertransfer-vs-responseredirect.htm
그것은 나를 위해 일했다. MVC 5
안에 ~\Global.asax
void Application_Error(object sender, EventArgs e)
{
FTools.LogException();
Response.Redirect("/Error");
}
안에 ~\Controllers
만들다 ErrorController.cs
using System.Web.Mvc;
namespace MVC_WebApp.Controllers
{
public class ErrorController : Controller
{
// GET: Error
public ActionResult Index()
{
return View("Error");
}
}
}
안에 ~\Models
만들다 FunctionTools.cs
using System;
using System.Web;
namespace MVC_WebApp.Models
{
public static class FTools
{
private static string _error;
private static bool _isError;
public static string GetLastError
{
get
{
string cashe = _error;
HttpContext.Current.Server.ClearError();
_error = null;
_isError = false;
return cashe;
}
}
public static bool ThereIsError => _isError;
public static void LogException()
{
Exception exc = HttpContext.Current.Server.GetLastError();
if (exc == null) return;
string errLog = "";
errLog += "**********" + DateTime.Now + "**********\n";
if (exc.InnerException != null)
{
errLog += "Inner Exception Type: ";
errLog += exc.InnerException.GetType() + "\n";
errLog += "Inner Exception: ";
errLog += exc.InnerException.Message + "\n";
errLog += "Inner Source: ";
errLog += exc.InnerException.Source + "\n";
if (exc.InnerException.StackTrace != null)
{
errLog += "\nInner Stack Trace: " + "\n";
errLog += exc.InnerException.StackTrace + "\n";
}
}
errLog += "Exception Type: ";
errLog += exc.GetType().ToString() + "\n";
errLog += "Exception: " + exc.Message + "\n";
errLog += "\nStack Trace: " + "\n";
if (exc.StackTrace != null)
{
errLog += exc.StackTrace + "\n";
}
_error = errLog;
_isError = true;
}
}
}
안에 ~\Views
폴더를 만듭니다 Error
그리고에서 ~\Views\Error
만들다 Error.cshtml
@using MVC_WebApp.Models
@{
ViewBag.Title = "Error";
if (FTools.ThereIsError == false)
{
if (Server.GetLastError() != null)
{
FTools.LogException();
}
}
if (FTools.ThereIsError == false)
{
<br />
<h1>No Problem!</h1>
}
else
{
string log = FTools.GetLastError;
<div>@Html.Raw(log.Replace("\n", "<br />"))</div>
}
}
오류를 표시하는 대신 데이터베이스에 저장할 변수 '로그'
여기에 몇 가지 옵션이 있다고 생각합니다.
세션에 마지막 예외를 저장하고 사용자 정의 오류 페이지에서 검색 할 수 있습니다. 또는 application_error 이벤트 내에서 사용자 정의 오류 페이지로 리디렉션 할 수 있습니다. 후자를 선택하면 Server.Transfer 메소드를 사용해야합니다.