Как избежать HttpException при вызове HttpContext.Request?

Итак HttpContext.Request выдает, если вызывается в глобальном запуске

public HttpRequest get_Request()
{
    if (this.HideRequestResponse)
    {
        throw new HttpException(SR.GetString("Request_not_available"));
    }
    return this._request;
}

Это фактически документировано

ASP.NET генерирует исключение, если вы попытаетесь использовать это свойство, когда объект HttpRequest недоступен. Например, это было бы верно в методе Application_Start файла Global.asax или в методе, который вызывается из метода Application_Start. В то время HTTP-запрос еще не создан.

Есть ли способ проверить, находится ли HttpContext.Request в состоянии, которое может быть извлечено без исключения исключения? Эффективно я хочу написать вспомогательный метод TryGetRequest.

  • Отражение не является опцией. Это должен быть открытый API.
  • У меня нет доступа к контексту приложения. это общий код ведения журнала. Поэтому установка некоторого флага при завершении запуска не является вариантом

Ответ 1

Это невозможно без использования отражения

Ответ 2

Как видно из практики, это разумно и на самом деле может быть необходимо полагаться на жизненный цикл приложения ASP.NET, чтобы определить, когда появился текущий HttpRequest. Общий код регистрации, по-видимому, зависит, по крайней мере, от HttpContext.Current или некоторой другой ссылки на текущий экземпляр HttpContext. Если это предположение верно, тогда может быть реализована функция HttpModule, которая хранит флаг в коллекции HttpContext.Items при срабатывании события BeginRequest. Статический TryGetRequest вспомогательный метод может проверить наличие этого флага, чтобы определить, можно ли использовать HttpContext.Request.

Возможно, так:

public class HttpRequestHelper : IHttpModule
{
    private const string HttpRequestIsAvailable = "HttpRequestIsAvailable";

    public static bool TryGetRequest(HttpContext context, out HttpRequest request)
    {
        request = null;
        if (context != null)
        {
            if (context.Items.Contains(HttpRequestIsAvailable))
                request = context.Request;
        }
        return (request != null);
    }

    #region IHttpModule

    public void Dispose()
    {
    }

    public void Init(HttpApplication context)
    {
        context.BeginRequest += context_BeginRequest;
    }

    private void context_BeginRequest(object sender, EventArgs e)
    {
        ((HttpApplication)sender).Context.Items.Add(HttpRequestIsAvailable, true);
    }

    #endregion
}

Модуль должен быть зарегистрирован в web.config(предполагая интегрированный конвейер IIS 7.0):

  <system.webServer>
    <modules>
      <add name="HttpRequestHelper" type="Utility.HttpRequestHelper" />
    </modules>
  </system.webServer>

Код ведения журнала будет использовать вспомогательный метод следующим образом:

HttpRequest request;
if (HttpRequestHelper.TryGetRequest(HttpContext.Current, out request))
    LogWithRequest(request, message);
else
    LogWithoutRequest(message);

Реализация не зависит от частного API или отражения. Он опирается на флаг, но информация о состоянии остается с экземпляром HttpContext и хорошо инкапсулирована.

Ответ 3

Почему бы не перевести вызов на HttpContext.Request с помощью блока try, catch, вы можете поймать исключение и соответствующим образом изменить свое поведение.