prosource

이 컨텍스트에서는 요청을 사용할 수 없습니다.

probook 2023. 5. 23. 22:00
반응형

이 컨텍스트에서는 요청을 사용할 수 없습니다.

IIS 7 통합 모드를 실행하고 있으며 다음과 같은 메시지가 표시됩니다.

이 컨텍스트에서는 요청을 사용할 수 없습니다.

Log4Net에서 할Application_Start이것이 제가 가지고 있는 코드 라인입니다.

if (HttpContext.Current != null && HttpContext.Current.Request != null)

그리고 두 번째 비교를 위해 예외가 던져지고 있습니다.

HttpContext를 확인하는 것 외에 제가 확인할 수 있는 것은 무엇입니까?현재의.null 요청?


iis7.5에서 nig mvc를 실행할 때 이 컨텍스트 예외에서 요청을 사용할 수 없다는 유사한 질문이 게시됨

하지만 거기에도 관련된 대답은 없습니다.

자세한 내용은 IIS7 통합 모드: Application_Start:의 이 컨텍스트 예외에서 요청을 사용할 수 없습니다.

"Request is not available in this context" 예외는 IIS 7.0에서 ASP.NET 응용프로그램을 통합 모드로 이동할 때 발생할 수 있는 일반적인 오류 중 하나입니다.응용 프로그램을 시작한 요청의 HttpContext에 액세스하려고 할 경우 global.asax 파일에서 Application_Start 메서드를 구현할 때 이 예외가 발생합니다.

사용자 지정 로깅 논리가 있는 경우 application_start를 로깅하지 않도록 강제하거나 로거에서 예외가 발생하도록 허용해야 하는 것이 오히려 귀찮습니다.

테스트를 하기보다는Request 가성가, 트능스에 할 수 있습니다.Handler가: 가 없는 경우Request여전히 요청 처리기가 있는 것은 이상할 것입니다. 테트대에 대한 .Handler그렇게 두려운 것은 아닙니다.Request is not available in this context예외.

코드를 다음으로 변경할 수 있습니다.

var currContext = HttpContext.Current;
if (currContext != null && currContext.Handler != null)

, 모듈의 http 모듈, http 모듈,Handler하지만 정의되지 않을 수 있습니다.Request그리고.Response정의됩니다(BeginRequest 이벤트에서 확인했습니다).따라서 사용자 지정 http 모듈에서 요청/응답 로깅이 필요한 경우 제 답변이 적합하지 않을 수 있습니다.

이것은 매우 전형적인 경우입니다., 그를 " " " " " http " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " 으로 하는 것을 해 보십시오.BeginRequest이벤트

void Application_BeginRequest(Object source, EventArgs e)

http 헤더, 쿼리 문자열 등을 확인할 수 있는 올바른 위치입니다. Application_Start라우팅, 필터, 로깅 등과 같이 전체 런타임에 응용 프로그램에 적용되는 설정입니다.

에서 코드를 이동할 방법이 없는 경우에는 static.ctor 또는 Classic 모드로 전환과 같은 해결 방법을 적용하지 마십시오.StartBeginRequest당신 사건의 대부분에 대해 할 수 있습니다.

앱을 시작하는 동안 더 이상 파이프라인에 요청 컨텍스트가 없기 때문에 다음에 실제 요청이 들어올 서버/포트를 추측할 방법이 없습니다.Begin_Session에서 그렇게 해야 합니다.

클래식 모드가 아닐 때 사용하는 것은 다음과 같습니다.간접비는 무시해도 될 정도입니다.

/// <summary>
/// Class is called only on the first request
/// </summary>
private class AppStart
{
    static bool _init = false;
    private static Object _lock = new Object();

    /// <summary>
    /// Does nothing after first request
    /// </summary>
    /// <param name="context"></param>
    public static void Start(HttpContext context)
    {
        if (_init)
        {
            return;
        }
        //create class level lock in case multiple sessions start simultaneously
        lock (_lock)
        {
            if (!_init)
            {
                string server = context.Request.ServerVariables["SERVER_NAME"];
                string port = context.Request.ServerVariables["SERVER_PORT"];
                HttpRuntime.Cache.Insert("basePath", "http://" + server + ":" + port + "/");
                _init = true;
            }
        }
    }
}

protected void Session_Start(object sender, EventArgs e)
{
    //initializes Cache on first request
    AppStart.Start(HttpContext.Current);
}

코멘트에 설명된 OP 상세 니즈를 바탕으로 보다 적절한 솔루션이 존재합니다.OP는 요청과 관련된 데이터인 log4net과 함께 로그에 사용자 지정 데이터를 추가하기를 원한다고 말합니다.

log4net은 요청 관련 데이터 검색을 처리하는 사용자 지정 중앙 집중식 로그 호출로 각 log4net 호출을 래핑하는 대신 로그할 사용자 지정 추가 데이터를 설정하기 위한 컨텍스트 사전을 제공합니다.이러한 사전을 사용하면 BeginRequest 이벤트에서 현재 요청에 대한 요청 로그 데이터를 배치한 다음 EndRequest 이벤트에서 이를 해제할 수 있습니다.이러한 사용자 지정 데이터를 사용하여 로그인할 수 있습니다.

또한 요청 컨텍스트에서 발생하지 않는 작업은 요청 관련 데이터를 기록하지 않으므로 요청 가용성을 테스트할 필요가 없습니다.이 해결책은 Arman McHitaryan이 답변에서 제안한 원칙과 일치합니다.

이 솔루션이 작동하려면 log4net appenders가 사용자 지정 데이터를 기록할 수 있도록 추가 구성이 필요합니다.

이 솔루션은 사용자 지정 로그 향상 모듈로 쉽게 구현할 수 있습니다.다음은 몇 가지 샘플 코드입니다.

using System;
using System.Web;
using log4net;
using log4net.Core;

namespace YourNameSpace
{
    public class LogHttpModule : IHttpModule
    {
        public void Dispose()
        {
            // nothing to free
        }

        private const string _ipKey = "IP";
        private const string _urlKey = "URL";
        private const string _refererKey = "Referer";
        private const string _userAgentKey = "UserAgent";
        private const string _userNameKey = "userName";

        public void Init(HttpApplication context)
        {
            context.BeginRequest += WebAppli_BeginRequest;
            context.PostAuthenticateRequest += WebAppli_PostAuthenticateRequest;
            // All custom properties must be initialized, otherwise log4net will not get
            // them from HttpContext.
            InitValueProviders(_ipKey, _urlKey, _refererKey, _userAgentKey,
                _userNameKey);
        }

        private void InitValueProviders(params string[] valueKeys)
        {
            if (valueKeys == null)
                return;
            foreach(var key in valueKeys)
            {
                GlobalContext.Properties[key] = new HttpContextValueProvider(key);
            }
        }

        private void WebAppli_BeginRequest(object sender, EventArgs e)
        {
            var currContext = HttpContext.Current;
            currContext.Items[_ipKey] = currContext.Request.UserHostAddress;
            currContext.Items[_urlKey] = currContext.Request.Url.AbsoluteUri;
            currContext.Items[_refererKey] = currContext.Request.UrlReferrer != null ? 
                currContext.Request.UrlReferrer.AbsoluteUri : null;
            currContext.Items[_userAgentKey] = currContext.Request.UserAgent;
        }

        private void WebAppli_PostAuthenticateRequest(object sender, EventArgs e)
        {
            var currContext = HttpContext.Current;
            // log4net doc states that %identity is "extremely slow":
            // http://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout.html
            // So here is some custom retrieval logic for it, so bad, especialy since I
            // tend to think this is a missed copy/paste in that documentation.
            // Indeed, we can find by inspection in default properties fetch by log4net a
            // log4net:Identity property with the data, but it looks undocumented...
            currContext.Items[_userNameKey] = currContext.User.Identity.Name;
        }
    }

    // General idea coming from 
    // http://piers7.blogspot.fr/2005/12/log4net-context-problems-with-aspnet.html
    // We can not use log4net ThreadContext or LogicalThreadContext with asp.net, since
    // asp.net may switch thread while serving a request, and reset the call context
    // in the process.
    public class HttpContextValueProvider : IFixingRequired
    {
        private string _contextKey;
        public HttpContextValueProvider(string contextKey)
        {
            _contextKey = contextKey;
        }

        public override string ToString()
        {
            var currContext = HttpContext.Current;
            if (currContext == null)
                return null;
            var value = currContext.Items[_contextKey];
            if (value == null)
                return null;
            return value.ToString();
        }

        object IFixingRequired.GetFixedObject()
        {
            return ToString();
        }
    }
}

사이트, IIS 7+ 구성 샘플에 추가합니다.

<system.webServer>
  <!-- other stuff removed ... -->
  <modules>
    <!-- other stuff removed ... -->
    <add name="LogEnhancer" type="YourNameSpace.LogHttpModule, YourAssemblyName" preCondition="managedHandler" />
    <!-- other stuff removed ... -->
  </modules>
  <!-- other stuff removed ... -->
</system.webServer>

추가 속성 샘플 구성을 기록하도록 appender를 설정합니다.

<log4net>
  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <!-- other stuff removed ... -->
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %-5level %logger - %message - %property%newline%exception" />
    </layout>
  </appender>
  <appender name="SqlAppender" type="log4net.Appender.AdoNetAppender">
    <!-- other stuff removed ... -->
    <commandText value="INSERT INTO YourLogTable ([Date],[Thread],[Level],[Logger],[UserName],[Message],[Exception],[Ip],[Url],[Referer],[UserAgent]) VALUES (@log_date, @thread, @log_level, @logger, @userName, @message, @exception, @Ip, @Url, @Referer, @UserAgent)" />
    <!-- other parameters removed ... -->
    <parameter>
      <parameterName value="@userName" />
      <dbType value="String" />
      <size value="255" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%property{userName}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@Ip"/>
      <dbType value="String" />
      <size value="255" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%property{Ip}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@Url"/>
      <dbType value="String" />
      <size value="255" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%property{Url}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@Referer"/>
      <dbType value="String" />
      <size value="255" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%property{Referer}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@UserAgent"/>
      <dbType value="String" />
      <size value="255" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%property{UserAgent}" />
      </layout>
    </parameter>
  </appender>
  <!-- other stuff removed ... -->
</log4net>

클래식 모드로 전환하지 않고도 문제를 해결할 수 있으며 Application_Start를 사용할 수 있습니다.

public class Global : HttpApplication
{
   private static HttpRequest initialRequest;

   static Global()
   {
      initialRequest = HttpContext.Current.Request;       
   }

   void Application_Start(object sender, EventArgs e)
   {
      //access the initial request here
   }

어떤 이유에서인지 정적 유형은 HTTP 컨텍스트의 요청으로 생성되므로 이를 저장하고 Application_Start 이벤트에서 즉시 재사용할 수 있습니다.

"통합" 모드에서 "클래식" 모드로 전환하여 이 문제를 해결하고 해결할 수 있었습니다.

애플리케이션 풀을 .NET v4.5 Classic으로 설정

Application_Start에 로그인해야 하는 경우 컨텍스트를 수정하기 전에 로그인하십시오.다음과 같은 소스가 없는 로그 항목을 얻을 수 있습니다.

2019-03-120 09:35:43,659 INFO (null) - 신청 시작

일반적으로 Application_Start와 Session_Start를 모두 기록하므로 다음 메시지에서 자세한 내용을 확인할 수 있습니다.

2019-03-120 09:35:45,064 INFO ~/Leads/Leads.aspx - 세션 시작(로컬)

        protected void Application_Start(object sender, EventArgs e)
        {
            log4net.Config.XmlConfigurator.Configure();
            log.Info("Application Started");
            GlobalContext.Properties["page"] = new GetCurrentPage();
        }

        protected void Session_Start(object sender, EventArgs e)
        {
            Globals._Environment = WebAppConfig.getEnvironment(Request.Url.AbsoluteUri, Properties.Settings.Default.LocalOverride);
            log.Info(string.Format("Session Started ({0})", Globals._Environment));
        }


visual studio 2012에서 'debug' 옵션으로 잘못 솔루션을 게시했을 때 이 예외가 발생했습니다.'release' 옵션을 사용하는 경우에는 발생하지 않았습니다.도움이 되길 바랍니다.

public bool StartVideo(바이트 채널) { try {CommandObject 명령 = new CommandObject(명령).START_VIDEO, 새 바이트[] {channel}, 채널);

            m_ResponseEvent.Reset();

            lock (m_Commands)
            {
                m_Commands.Enqueue(command);
            }

            if (m_ResponseEvent.WaitOne(5000, true))
            {
                return m_Response == null ? false : true;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        return false;
    }

다음을 사용할 수 있습니다.

    protected void Application_Start(object sender, EventArgs e)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(StartMySystem));
    }

    private void StartMySystem(object state)
    {
        Log(HttpContext.Current.Request.ToString());
    }

global.asax.cs 에서 이 작업을 수행합니다.

protected void Application_Start()
{
  //string ServerSoftware = Context.Request.ServerVariables["SERVER_SOFTWARE"];
  string server = Context.Request.ServerVariables["SERVER_NAME"];
  string port = Context.Request.ServerVariables["SERVER_PORT"];
  HttpRuntime.Cache.Insert("basePath", "http://" + server + ":" + port + "/");
  // ...
}

아주 잘 작동합니다.이거. 문맥.요청이 있습니다...

이.요청은 플래그를 기반으로 의도적으로 예외를 던집니다.

언급URL : https://stackoverflow.com/questions/2518057/request-is-not-available-in-this-context

반응형