>

나는 많은 사람들처럼 오류에 대한 리디렉션의 기본 ASP.NET 접근 방식을 피합니다. 깨끗한 AJAX 코드와 SEO가 그 이유 중 하나입니다.

그러나 다음 방법을 사용하여 HttpContext.Current.Items 를 잃을 수 있습니다.  양도 중?

<httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="401" />
    <remove statusCode="403" />
    <remove statusCode="404" />
    <remove statusCode="500" />
    <error statusCode="401" responseMode="ExecuteURL" path="/Account/SignIn" />
    <error statusCode="403" responseMode="ExecuteURL" path="/Site/Forbidden" />
    <error statusCode="404" responseMode="ExecuteURL" path="/Site/NotFound" />
    <error statusCode="500" responseMode="ExecuteURL" path="/Site/Error" />
</httpErrors>

난 그냥 Server.Transfer() 를 수행 가정  내가 이해하고있는 표지 아래에서 Items 를 보존합니다. . HttpContext.Current.Items의 범위 및 http://weblog.west-wind.com/posts/2010/Jan/20/HttpContextItems-and-ServerTransferExecute )

그러나 나는 또한 Items 에서 무언가를 캡처하고있다  "ExecuteURL"이전에, 그리고 전송 후 (또는 무엇이든) 검색/출력하면 사라지는 것 같습니다. 나는 그것이 Items 에 들어가는 것을 보았다  수집, 나는 Count 를 참조하십시오  5로 올린 다음 값을 검색하면 컬렉션에 2 개의 항목 만 있습니다.

무엇이 진행됩니까?

<시간>

내가하는 일에 대해 더 많이 이해하고 대체 구현을 추천하고 싶다면 개방적입니다. 나는 이것을 사용하여 경쟁 조건이없는 방식으로 ELMAH 오류 Id를 ViewModel에 푸시합니다. (즉, 대체하려는 일반적인 해결 방법은 가장 최근의 오류 만 표시하는 것입니다.) 다음은 내 코드입니다.

Global.asax

protected void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args) {
    ElmahSupplement.CurrentId = args.Entry.Id;
}
void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs e) {
    if (ElmahSupplement.IsNotFound(e.Exception)) {
        ElmahSupplement.LogNotFound((e.Context as HttpContext).Request);
        e.Dismiss();
    }
}

SiteController.cs

public virtual ActionResult Error() {
    Response.StatusCode = 500;
    return View(MVC.Site.Views.Error, ElmahSupplement.CurrentId);
}

ElmahSupplement.cs

public class ElmahSupplement {
    // TODO: This is a rather fragile way to access this info
    private static readonly Guid contextId = new Guid("A41A67AA-8966-4205-B6C1-14128A653F21");
    public static string CurrentId {
        get { 
            return
                // Elmah 1.2 will fail to log when enumerating form values that raise RequestValidationException (angle brackets)
                // https://code.google.com/p/elmah/issues/detail?id=217
                // So this id could technically be empty here
                (HttpContext.Current.Items[contextId] as string);
        }
        set {
            HttpContext.Current.Items[contextId] = value;
        }
    }
    public static void LogNotFound(HttpRequest request) {
        var context = RepositoryProxy.Context;
        context.NotFoundErrors.Add(new NotFoundError {
            RecordedOn = DateTime.UtcNow,
            Url = request.Url.ToString(),
            ClientAddress = request.UserHostAddress,
            Referrer = request.UrlReferrer == null ? "" : request.UrlReferrer.ToString()
        });
        context.SaveChanges();
    }
    public static bool IsNotFound(Exception e) {
        HttpException he = e as HttpException;
        return he != null && he.GetHttpCode() == 404;
    }
}

  • 답변 # 1

    여기에 설명 된 것처럼 ExecuteURL은 두 가지 요청을 생성합니다. 첫 번째 요청은 예외를 발생시키고 두 번째 요청은 오류 응답을 생성합니다.

    Context.Items는 요청 사이에 지워지기 때문에 코드는 항상 두 번째 요청이 생성되어 항목 사이에 차이가 발생합니다.

    게시물에서 sugestion을 시도하십시오. 대신 redirectMode = "ResponseRewrite"와 함께 system.web>customErrors를 사용하십시오.

  • 답변 # 2

    추적을 따라 다음을 결정했습니다. 일부는 느슨하게 추론됩니다.

    IIS 모듈 스택에있는 CustomErrorModule은 SEND_RESPONSE 알림을받습니다.

    HttpStatus는 500이므로 컨텍스트를 복제하고 일치하는 사용자 정의 오류 규칙에 따라 새 URL을 설정하고이 컨텍스트에서 요청을 실행합니다 (ExecuteRequest 참조).

    HttpContext.Items 의 목적  문서 당 :

    와이즈 비즈

    이 함수 정의를 비판적으로 보는 것은 물론 "HTTP 요청"만 있습니다. 그러나

    Gets a key/value collection that can be used to organize and share data between an IHttpModule interface and an IHttpHandler interface during an HTTP request.

    는  dictionary 자체는 HttpContext를 기반으로하는 사전에있는 항목이며,이 실행 하위 요청에서 고유 한 (복제 된) 참조입니다. 추적 결과이 Items 에 대해 실행중인 전체 파이프 라인 (모든 모듈, 예 : 중복 인증)이 표시됩니다. 따라서이 고립 된 상황은 물론 필요합니다.

    관리되지 않는 코드에서 GetParentContext는 쉽지 않습니다. 그러나 관리 코드에서이 계층 구조를 사용할 수 없습니다. 그래서 나는 원래 ExecuteURL 를 검색 할 수있는 방법이 없어 .

    대체 솔루션으로 테스트 결과 Items 를 공유하는 자식 요청이 표시되었으므로 Global.asax 변수를 활용하는 것이 기능적 일 수 있습니다. , 그러나 이것에 대한 클라이언트 액세스가 반드시 순차적인지는 확실하지 않습니다.

    또 다른 더 나은 방법은 전체 파이프 라인을 다시 실행하지 않는 것입니다. MVC 핸들러를 종료하지 않으려면 (예 : ApplicationInstance  및 TransferToAction). 그러나 이렇게하면 오류 페이지 구성에 대해 Single-Point-of-Truth를 구현할 수 없습니다. 오류는 MVC의 인식 범위 밖에서도 발생할 수 있기 때문입니다.

    Controller.OnException

  • 이전 apache - DOS 공격으로 인해 Plesk Admin에 액세스 할 수없고 SSH를 통해 IP 주소를 차단합니까?
  • 다음 PostgreSQL의 배열에서 NULL 값 바꾸기