programing

ASP.NET 사용자 지정 오류 페이지 - 서버.GetLastError()가 null입니다.

javajsp 2023. 7. 13. 20:40

ASP.NET 사용자 지정 오류 페이지 - 서버.GetLastError()가 null입니다.

응용 프로그램에 대해 설정된 사용자 지정 오류 페이지가 있습니다.

<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();
    }

오류 페이지(~/http/GeneralError.aspx.cs )에 도착할 때쯤이면 서버.GetLastError()가 null입니다.

Global.asax.cs 이 아닌 오류 페이지에서 예외 세부 정보를 얻을 수 있는 방법이 있습니까?

Vista/IIS7의 ASP.NET 3.5

내 web.config 설정을 더 자세히 보니, 이 게시물의 댓글 중 하나가 매우 도움이 됩니다.

asp.net 3.5 sp1에는 새 매개 변수 redirectMode가 있습니다.

그래서 우리는 수정할 수 있습니다.customErrors이 매개 변수를 추가하려면:

<customErrors mode="RemoteOnly" defaultRedirect="~/errors/GeneralError.aspx" redirectMode="ResponseRewrite" />

ResponseRewrite모드를 사용하면 브라우저를 리디렉션하지 않고 "Error Page"를 로드할 수 있으므로 URL이 동일하게 유지되며, 중요한 것은 예외 정보가 손실되지 않는다는 것입니다.

, 이 게시물을 찾았습니다: http://msdn.microsoft.com/en-us/library/aa479319.aspx

다음과 같은 매우 예시적인 다이어그램을 사용합니다.

diagram
(출처: microsoft.com )

본질적으로, 그러한 예외 세부 정보를 얻으려면 나중에 사용자 정의 오류 페이지에서 검색할 수 있도록 Global.asax에 직접 저장해야 합니다.

가장 좋은 방법은 Global.asax에서 대부분의 작업을 수행하는 것으로 보이며, 사용자 정의 오류 페이지는 논리보다는 유용한 내용을 처리합니다.

Nail It Down과 Victor가 말한 것을 조합한 것입니다.가장 선호되거나 가장 쉬운 방법은 글로벌을 사용하는 것입니다.오류를 저장한 다음 사용자 정의 오류 페이지로 리디렉션하는 축입니다.

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()ErrorPage.aspx.cs 의 경우 다음과 같은 작업을 수행할 수 있습니다.Exception exception = Server.GetLastError().GetBaseException();

Server.Transfer()예외를 유지하고 있는 것 같습니다.

여기에는 몇 가지 좋은 답변이 있지만, 오류 페이지에 시스템 예외 메시지를 표시하는 것은 좋지 않다는 점을 지적해야 합니다.악의적인 사용자에게 원하지 않는 내용을 실수로 노출할 수 있습니다.예를 들어 SQL Server 예외 메시지는 매우 상세하며 오류가 발생할 때 데이터베이스의 사용자 이름, 암호 및 스키마 정보를 제공할 수 있습니다.이러한 정보는 최종 사용자에게 표시되지 않아야 합니다.

여기 제 해결책이 있습니다.

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"); 
    }

Ops.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의 좋은 설명을 찾고 있습니다.global.asax Application_Error와 같은 사용자 지정 오류 페이지에서 GetLastError를 실행합니다.

추신: 먼저 데이터를 잠갔다가 잠금 해제하지 않고 응용프로그램 모음에 데이터를 저장하는 것은 안전하지 않습니다.

저는 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 Folder 더만기들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>
    }
}


이 주소를 입력하는 경우localhost/Error open page Whithout Error



그리고 오류가 발생할 경우 error occurs

오류를 표시하는 대신 변수 'log'를 데이터베이스에 저장할 수 있습니다.


출처: Microsoft ASP.Net

아래 두 가지 주제와 관련하여 GetHtmlErrorMessage와 Session on Error 페이지를 모두 받고 싶습니다.

응답 다시 쓰기 후 세션이 null입니다.

HttpContext는 왜입니까?리디렉션 모드 = 응답 다시 쓰기 시 세션 null

는 필요 .Server.Transfer() or Response.Redirect()

첫 번째: web.config에서 ResponseRewrite를 제거

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

여기에 몇 가지 옵션이 있을 것 같습니다.

마지막 예외를 세션에 저장하고 사용자 지정 오류 페이지에서 검색하거나 Application_error 이벤트 내의 사용자 지정 오류 페이지로 리디렉션할 수 있습니다.후자를 선택할 경우, 서버를 사용해야 합니다.전송 방법.

언급URL : https://stackoverflow.com/questions/343014/asp-net-custom-error-page-server-getlasterror-is-null