इस संदर्भ में अनुरोध उपलब्ध नहीं है


113

मैं IIS 7 इंटीग्रेटेड मोड चला रहा हूं और मुझे मिल रहा है

इस संदर्भ में अनुरोध उपलब्ध नहीं है

जब मैं इसे Log4Net संबंधित फ़ंक्शन से एक्सेस करने का प्रयास करता हूं जिसे कहा जाता है Application_Start। यह कोड ऑफ़ लाइन I है

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

और एक अपवाद दूसरी तुलना के लिए फेंका जा रहा है।

मैं HttpContext.Current.Request की जाँच करने के अलावा और क्या जाँच कर सकता हूँ ??


एक समान प्रश्न पोस्ट किया गया है @ अनुरोध इस संदर्भ में उपलब्ध नहीं है जब iis7.5 पर runnig mvc

लेकिन कोई प्रासंगिक जवाब भी नहीं है।


2
अगर आप एंड्रयू हरे से लिंक में सुझाए गए अन्य दो समाधान नहीं लेते हैं तो क्या आप लोग मेरे एकमात्र विकल्प के रूप में एक कोशिश-पकड़ ब्लॉक को जोड़ने की सलाह देंगे? like try {if (HttpContext.Current.Request.Headers ["User_info"]! = null) log4net.MDC.Set ("UserInfo", HttpContext .Current.Request.Headers ["User_info"]। ToString ()); } catch () {}
विशाल सेठ

जवाबों:


79

कृपया IIS7 एकीकृत मोड देखें : Application_Start में इस संदर्भ में अपवाद उपलब्ध नहीं है :

"अनुरोध इस संदर्भ में उपलब्ध नहीं है" अपवाद IIS 7.0 पर एकीकृत मोड में ASP.NET अनुप्रयोगों को स्थानांतरित करते समय आपको प्राप्त होने वाली अधिक सामान्य त्रुटियों में से एक है। यदि आप आवेदन शुरू करने वाले अनुरोध के HttpContext तक पहुंचने का प्रयास करते हैं, तो यह अपवाद Global.asax फ़ाइल में Application_Start पद्धति के आपके कार्यान्वयन में होता है।


2
इस स्थिति की अधिक चर्चा यहाँ: stackoverflow.com/questions/1790457/…
jball

6
धन्यवाद। मैंने उस लिंक को पहले देखा था। यह कहता है: "मूल रूप से, यदि आप Application_Start में अनुरोध के संदर्भ को एक्सेस कर रहे हैं, तो आपके पास दो विकल्प हैं: 1) अनुरोध के संदर्भ (अनुशंसित) का उपयोग नहीं करने के लिए अपना एप्लिकेशन कोड बदलें। 2) एप्लिकेशन को क्लासिक मोड में ले जाएं (अनुशंसित नहीं है)। )। " क्या उनके कोई अन्य विकल्प नहीं हैं? मेरा लॉगिंग कोड डीबी में सामान लिखता है जैसे आवेदन शुरू हुआ, अगर उन अनुरोधों के माध्यम से नहीं तो उन क्षेत्रों को पूरी तरह से हटाने के बजाय अपने लॉग स्टेटमेंट को हटाने के लिए सेट किया जाना चाहिए।
विशाल सेठ

मुझे लॉगिंग की आवश्यकता समान है, यदि संदर्भ उपलब्ध है तो इसका उपयोग डेटाबेस को पॉप्युलेट करने के लिए करें, यदि फ़ील्ड रिक्त नहीं है। (मेरे मामले में, एक लॉगिंग टेबल पर रिकॉर्ड न लिखें, लेकिन इससे यह निर्धारित करने में मदद मिलेगी कि क्या यह निर्धारित करने के लिए एक अच्छा तरीका है या उपलब्ध नहीं है।)
ज़ेरेफेथ

2
यह पसंद नहीं आया, लेकिन चेक-कैच में चेक को लपेटना हमारे लॉगिंग कोड (और / या संपूर्ण ऐप) के एक प्रमुख रीफैक्टरिंग के अलावा एकमात्र विकल्प था
Zarepheth

47
क्या यह बताने का कोई तरीका है कि क्या आप ऐसी स्थिति में हैं जहाँ अनुरोध उपलब्ध नहीं होगा? HttpContext की कुछ संपत्ति जो इस बारे में जानती है? यह अन्य गुणों की तरह, केवल कुछ भी नहीं लौटाने के बजाय अपवाद क्यों फेंकता है?
जोशुआ फ्रैंक

50

जब आपके पास कस्टम लॉगिंग लॉजिक होता है, तो यह मजबूर होता है कि या तो application_start लॉग न करें या लॉगर में अपवाद होने दें (भले ही संभाला जाए)।

ऐसा प्रतीत होता है कि Requestउपलब्धता के लिए परीक्षण के बजाय , आप उपलब्धता के लिए परीक्षण कर सकते हैं Handler: जब कोई नहीं होता है Request, तो यह अभी भी अनुरोध हैंडलर के लिए अजीब होगा। और परीक्षण Handlerउस खतरनाक Request is not available in this contextअपवाद को नहीं बढ़ाता है ।

तो आप अपना कोड इसमें बदल सकते हैं:

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

Http मॉड्यूल के संदर्भ में खबरदार, Handlerहालांकि परिभाषित नहीं किया जा सकता है Requestऔर Responseपरिभाषित किया गया है (मैंने देखा है कि BeginRequest घटना में)। इसलिए यदि आपको एक कस्टम http मॉड्यूल में लॉगिंग / रिस्पांस लॉगिंग की आवश्यकता है, तो मेरा उत्तर उपयुक्त नहीं हो सकता है।


1
इसके अलावा कमियां पहले से ही यहां बताई गई हैं, मुझे एहसास हुआ कि यह वास्तव में एक टिप्पणी में ओपी द्वारा बताई गई विशिष्ट आवश्यकताओं के लिए जाने का तरीका नहीं था। इस पृष्ठ पर मेरे अन्य उत्तर देखें।
फ्रेड्रिक

1
इसने मेरे लिए चाल चली, मुझे केवल एक अपवाद को फेंकने के बिना अनुरोध वस्तु की जांच करने की आवश्यकता थी। Ty
ओवरमारर्स

17

यह बहुत ही क्लासिक मामला है: यदि आपके पास http उदाहरण द्वारा प्रदान किए गए किसी भी डेटा की जांच करना है, तो उस कोड को BeginRequestघटना के तहत स्थानांतरित करने पर विचार करें ।

void Application_BeginRequest(Object source, EventArgs e)

यह HTTP हेडर, क्वेरी स्ट्रिंग और आदि के लिए जाँच करने के लिए सही जगह है। यह Application_Startउन सेटिंग्स के लिए है, जो पूरे रन टाइम के लिए आवेदन करती हैं, जैसे रूटिंग, फ़िल्टर, लॉगिंग और इसी तरह।

कृपया, जब तक कि कोड को स्थानांतरित करने का कोई तरीका नहीं है, तब तक किसी भी वर्कअराउंड जैसे स्थैतिक .ctor या क्लासिक मोड पर स्विच करना लागू नStart करें BeginRequest। जो आपके अधिकांश मामलों के लिए उपयुक्त होना चाहिए।


7

चूंकि ऐप शुरू होने के दौरान पाइपलाइन में कोई अनुरोध संदर्भ नहीं है, इसलिए मैं कल्पना नहीं कर सकता कि यह अनुमान लगाने का कोई तरीका है कि अगला वास्तविक अनुरोध किस सर्वर / पोर्ट पर आ सकता है। आपको इसे 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);
}

धन्यवाद, यह इस लक्षण के साथ अचानक नीचे आने के बाद मेरी साइट को फिर से ऊपर और चल रहा है। अजीब तरह से, मैं ऐप के पूल में क्लासिक ASP.NET से नहीं बदला था - मुझे अभी भी त्रुटि मिली है। इस कोड के एक संस्करण को जोड़ने (Interlocked.Exchange (रेफ इंट, इंट) का उपयोग करके) ने समस्या को हल किया।
जॉन कैलन

1
इस उत्तर की पहली पंक्ति (यह एक डुप्लिकेट है ...) को हटाया जाना चाहिए। यह लिंक किए गए पोस्ट का डुप्लिकेट नहीं है, प्रश्न काफी अलग है। वह ऐप स्टार्ट में सर्वर नाम तक पहुंचने के लिए नहीं कह रहा था। वह केवल अपने सामान्य तर्क-वितर्क के लिए तैयार रहना चाहता था ताकि Application_start विशेष मामले में अपवाद न फेंके।
फ्रैडरिक

6

ओपी के आधार पर विस्तृत रूप से टिप्पणियों में बताया गया है , एक अधिक उपयुक्त समाधान मौजूद है। ओपी बताता है कि वह अपने लॉग में कस्टम डेटा को लॉग 4नेट, अनुरोधों से संबंधित डेटा के साथ जोड़ना चाहता है।

प्रत्येक लॉग 4net कॉल को एक कस्टम सेंट्रलाइज्ड लॉग कॉल में लपेटने के बजाय, जो रिलेटेड रिक्वेस्ट रिलेटेड डेटा (प्रत्येक लॉग कॉल पर) को हैंडल करता है, लॉग में 4 अतिरिक्त कस्टम डेटा को सेट करने के लिए log4net फीचर्स डिक्शनरी डिक्लेयर करता है। उन dictionnaries का उपयोग करके आपके अनुरोध लॉग डेटा को शुरुआती अनुरोध पर वर्तमान अनुरोध के लिए रखने की अनुमति देता है, फिर उसे EndRequest इवेंट में खारिज करने के लिए। बीच में कोई भी लॉग उन कस्टम डेटा से लाभान्वित होगा।

और जो चीजें अनुरोध के संदर्भ में नहीं होती हैं, वे अनुरोध उपलब्धता के लिए परीक्षण करने की आवश्यकता को समाप्त करते हुए अनुरोध संबंधी डेटा लॉग करने का प्रयास नहीं करेंगे। यह समाधान उस सिद्धांत से मेल खाता है जो अरमान मैकहिट्रान अपने उत्तर में सुझा रहा था

काम करने के लिए इस समाधान के लिए, आपको अपने कस्टम डेटा को लॉग करने के लिए अपने log4net ऐपेंडर्स पर कुछ अतिरिक्त कॉन्फ़िगरेशन की भी आवश्यकता होगी।

यह समाधान कस्टम लॉग एन्हांसमेंट मॉड्यूल के रूप में आसानी से लागू किया जा सकता है। यहाँ इसके लिए नमूना कोड है:

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+ conf नमूना:

<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>

और उन अतिरिक्त गुणों, नमूना विन्यास को लॉग करने के लिए परिशिष्ट स्थापित करें:

<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>

+1 यह इंगित करने के लिए कि आप HttpContext.Current.Items ["IP"] का उपयोग HttpContext.Request.UserHostAddress के बजाय कर सकते हैं। रिक्त अनुरोध के मामले में यह डेटा लाने के लिए काम करता है - जिसने मुझे बचा लिया :) धन्यवाद।
सिल्लू

2

आप क्लासिक मोड पर स्विच किए बिना समस्या को हल कर सकते हैं और अभी भी 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
   }

किसी कारण से, स्थिर प्रकार इसके HTTPContext में एक अनुरोध के साथ बनाया गया है, जिससे आप इसे स्टोर कर सकते हैं और Application_Start ईवेंट में इसे फिर से उपयोग कर सकते हैं।


मुझे पता नहीं है .. स्थानीय रूप से ऐसा लगता है कि जब मैं उपयोग करने की कोशिश करता हूं तो यह पोर्ट को "नहीं" देखता है: initialRequest.Url.GetLeftPart (UriPartial.Authority); अलग तरीके से देखना पड़ेगा।
justabuzz

बहुत हैकिंग, लेकिन कुछ हताश मामलों में मदद कर सकता है। (मैं डाउन-वोटिंग या अप-वोटिंग के बीच थोड़ा संतुलित हूं, इसलिए मैं सिर्फ वोट नहीं डालता हूं।)
Frédéric

1

मैं "क्लासिक" मोड से "एकीकृत" मोड में स्थानांतरित करके इस समस्या को हल / हैक करने में सक्षम था।


0

यह मेरे लिए काम करता है - यदि आपको Application_Start में लॉग इन करना है, तो संदर्भ को संशोधित करने से पहले इसे करें। आपको लॉग एंट्री मिलेगी, जैसे कोई स्रोत नहीं, जैसे:

2019-03-12 09: 35: 43,659 जानकारी (शून्य) - आवेदन शुरू

मैं आमतौर पर Application_Start और Session_Start दोनों को लॉग करता हूं, इसलिए मुझे अगले संदेश में अधिक विवरण दिखाई देता है

2019-03-12 09: 35: 45,064 जानकारी ~ / बिक्रीसूत्र / बिक्री। - सत्र प्रारंभ (स्थानीय)

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


0

दृश्य स्टूडियो 2012 में, जब मैंने 'डीबग' विकल्प के साथ गलती से समाधान प्रकाशित किया तो मुझे यह अपवाद मिला। 'रिलीज़' विकल्प के साथ यह कभी नहीं हुआ। आशा करता हूँ की ये काम करेगा।


-3

आप निम्नलिखित का उपयोग कर सकते हैं:

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

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

-4

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

एक जादू की तरह काम करता है। यह है। Context.Request वहाँ है ...

यह.सामान्य रूप से एक ध्वज के आधार पर अपवाद फेंकता है


5
-1: प्रश्न पढ़ें: यह वही है जो विफल हो रहा है (IIS> = 7 और एकीकृत मोड के साथ)
रिचर्ड

यह तब होता है जब समुद्री डाकू अपनी नौकरी को ढीला कर देते हैं और खुद को प्रोग्रामिंग में आज़माते हैं :) कोई अपराध नहीं; मनुष्य;)
अरमान मैकहिटेरियन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.