Як перетворити HttpRequestBase в об'єкт HttpRequest?


87

всередині мого контролера ASP.NET MVC, у мене є метод, який вимагає HttpRequestоб'єкта. Все, до чого я маю доступ - це HttpRequestBaseоб’єкт.

Чи можу я якось це перетворити?

Що я можу / повинен робити ??


4
Примітка: «навпаки» це питання тут stackoverflow.com/questions/15275370 / ...
Simon_Weaver

Відповіді:


50

Це ваш метод, щоб ви могли переписати його, щоб взяти HttpRequestBase? Якщо немає, то ви завжди можете отримати струм HttpRequestвід HttpContext.Current.HttpRequestпройти далі. Однак я часто обгортаю доступ до HttpContext всередині класу, як це згадується в ASP.NET: Видалення залежностей System.Web для кращої підтримки модульного тестування.


4
Невтішно, я теж думав про це, і це не працює. HttpContext - це контекст MVC .., тому в ньому немає властивості "Current". Я не знаю, як отримати доступ до "oldschool" HttpContext.Current ... ???
Pure.Krome

48
Щоб переконатися, що ви захоплюєте клас HttpContext замість елемента контролера, спробуйте використати System.Web.HttpContext.Current.
Кевін Хакансон,

1
Мені потрібно було використовувати повний простір імен, оскільки він приймав поточну властивість простору імен MVC. ура. Зверніть увагу іншим: не робіть те, що я роблю. це VeryBadThing (tm).
Pure.Krome

Посилання мертве; Термін дії домену developmentalmadness.com закінчився, сторінка заповнення GoDaddy зараз
Кріс Москіні

2
System.Web.HttpContext.Current.Request
Дженні О'Райлі

72

Ви завжди повинні використовувати HttpRequestBase та HttpResponseBase у своєму додатку, на відміну від конкретних версій, які неможливо перевірити (без typemock чи іншої магії).

Просто використовуйте клас HttpRequestWrapper для перетворення, як показано нижче.

var httpRequestBase = new HttpRequestWrapper(Context.Request);

2
Ще одна примітка про те, що, не тільки використовувати, HttpRequestBaseа HttpResponseBase, також HttpContextBase. :)
Junle Li

30

Ви можете просто використовувати

System.Web.HttpContext.Current.Request

Ключовим тут є те, що вам потрібен повний простір імен, щоб дістатися до "правильного" HttpContext.

Я знаю, що минуло 4 роки з того моменту, як було поставлено це питання, але якщо це комусь допоможе, то ось вам!

(Редагувати: Я бачу, що Кевін Хакансон вже дав цю відповідь ... тому, сподіваюся, моя відповідь допоможе тим людям, які просто читають відповіді, а не коментують.) :)


9

Спробуйте використати / створити HttpRequestWrapper за допомогою вашого HttpRequestBase.


8

Щоб отримати HttpRequest в ASP.NET MVC4 .NET 4.5, ви можете зробити наступне:

this.HttpContext.ApplicationInstance.Context.Request

4

Як правило, коли вам потрібен доступ до HttpContextвластивості під дією контролера, є щось, що ви можете зробити кращим у мудрому дизайні.

Наприклад, якщо вам потрібен доступ до поточного користувача, вкажіть для вашого методу дії параметр типу IPrincipal, який ви заповнюєте знаком Attributeі макет, як хочете під час тестування. Короткий приклад того, як це, дивіться у цьому дописі в блозі , а саме в пункті 7


Повністю згоден! проблема полягає в тому, що я не можу змінити поточну бібліотеку класів, яку ми повинні використовувати .. тому це мені не надто допомагає :(
Pure.Krome

2

Немає можливості конвертувати між цими типами.

У нас був подібний випадок. Ми переписали наші класи / методи веб-служб, щоб вони використовували HttpContextBase, HttpApplicationStateBase, HttpServerUtilityBase, HttpSessionStateBase ... замість типів близького імені без суфікса "Base" (HttpContext, ... HttpSessionState). З ними набагато легше впоратися із саморобними знущаннями.

Мені шкода, що ви не змогли цього зробити.


1
Неправда.var httpRequest = Context.Request; var httpRequestBase = новий HttpRequestWrapper (Context.Request);
CountZero

2

Це ASP.Net MVC 3.0 AsyncController, який приймає запити, перетворює вхідний об'єкт HttpRequestBase MVC в System.Web.HttpWebRequest. Потім він надсилає запит асинхронно. Коли відповідь повертається, він перетворює System.Web.HttpWebResponse назад в об'єкт MVC HttpResponseBase, який можна повернути через контролер MVC.

Щоб відповісти на це питання явно, я думаю, вас зацікавила б лише функція BuildWebRequest (). Однак він демонструє, як рухатися по всьому конвеєру - перетворюючи з BaseRequest> Request, а потім Response> BaseResponse. Я вважав, що спільне використання обох буде корисним.

За допомогою цих класів ви можете мати сервер MVC, який виконує роль веб-проксі.

Сподіваюся, це допомагає!

Контролер:

[HandleError]
public class MyProxy : AsyncController
{
    [HttpGet]
    public void RedirectAsync()
    {
        AsyncManager.OutstandingOperations.Increment();

        var hubBroker = new RequestBroker();
        hubBroker.BrokerCompleted += (sender, e) =>
        {
            this.AsyncManager.Parameters["brokered"] = e.Response;
            this.AsyncManager.OutstandingOperations.Decrement();
        };

        hubBroker.BrokerAsync(this.Request, redirectTo);
   }

    public ActionResult RedirectCompleted(HttpWebResponse brokered)
    {
        RequestBroker.BuildControllerResponse(this.Response, brokered);
        return new HttpStatusCodeResult(Response.StatusCode);
    }
}

Це проксі-клас, який займається важким підйомом:

namespace MyProxy
{
    /// <summary>
    /// Asynchronous operation to proxy or "broker" a request via MVC
    /// </summary>
    internal class RequestBroker
    {
        /*
         * HttpWebRequest is a little protective, and if we do a straight copy of header information we will get ArgumentException for a set of 'restricted' 
         * headers which either can't be set or need to be set on other interfaces. This is a complete list of restricted headers.
         */
        private static readonly string[] RestrictedHeaders = new string[] { "Accept", "Connection", "Content-Length", "Content-Type", "Date", "Expect", "Host", "If-Modified-Since", "Range", "Referer", "Transfer-Encoding", "User-Agent", "Proxy-Connection" };

        internal class BrokerEventArgs : EventArgs
        {
            public DateTime StartTime { get; set; }

            public HttpWebResponse Response { get; set; }
        }

        public delegate void BrokerEventHandler(object sender, BrokerEventArgs e);

        public event BrokerEventHandler BrokerCompleted;

        public void BrokerAsync(HttpRequestBase requestToBroker, string redirectToUrl)
        {
            var httpRequest = BuildWebRequest(requestToBroker, redirectToUrl);

            var brokerTask = new Task(() => this.DoBroker(httpRequest));
            brokerTask.Start();
        }

        private void DoBroker(HttpWebRequest requestToBroker)
        {
            var startTime = DateTime.UtcNow;

            HttpWebResponse response;
            try
            {
                response = requestToBroker.GetResponse() as HttpWebResponse;
            }
            catch (WebException e)
            {
                Trace.TraceError("Broker Fail: " + e.ToString());

                response = e.Response as HttpWebResponse;
            }

            var args = new BrokerEventArgs()
            {
                StartTime = startTime,
                Response = response,
            };

            this.BrokerCompleted(this, args);
        }

        public static void BuildControllerResponse(HttpResponseBase httpResponseBase, HttpWebResponse brokeredResponse)
        {
            if (brokeredResponse == null)
            {
                PerfCounters.ErrorCounter.Increment();

                throw new GriddleException("Failed to broker a response. Refer to logs for details.");
            }

            httpResponseBase.Charset = brokeredResponse.CharacterSet;
            httpResponseBase.ContentType = brokeredResponse.ContentType;

            foreach (Cookie cookie in brokeredResponse.Cookies)
            {
                httpResponseBase.Cookies.Add(CookieToHttpCookie(cookie));
            }

            foreach (var header in brokeredResponse.Headers.AllKeys
                .Where(k => !k.Equals("Transfer-Encoding", StringComparison.InvariantCultureIgnoreCase)))
            {
                httpResponseBase.Headers.Add(header, brokeredResponse.Headers[header]);
            }

            httpResponseBase.StatusCode = (int)brokeredResponse.StatusCode;
            httpResponseBase.StatusDescription = brokeredResponse.StatusDescription;

            BridgeAndCloseStreams(brokeredResponse.GetResponseStream(), httpResponseBase.OutputStream);
        }

        private static HttpWebRequest BuildWebRequest(HttpRequestBase requestToBroker, string redirectToUrl)
        {
            var httpRequest = (HttpWebRequest)WebRequest.Create(redirectToUrl);

            if (requestToBroker.Headers != null)
            {
                foreach (var header in requestToBroker.Headers.AllKeys)
                {
                    if (RestrictedHeaders.Any(h => header.Equals(h, StringComparison.InvariantCultureIgnoreCase)))
                    {
                        continue;
                    }                   

                    httpRequest.Headers.Add(header, requestToBroker.Headers[header]);
                }
            }

            httpRequest.Accept = string.Join(",", requestToBroker.AcceptTypes);
            httpRequest.ContentType = requestToBroker.ContentType;
            httpRequest.Method = requestToBroker.HttpMethod;

            if (requestToBroker.UrlReferrer != null)
            {
                httpRequest.Referer = requestToBroker.UrlReferrer.AbsoluteUri;
            }

            httpRequest.UserAgent = requestToBroker.UserAgent;

            /* This is a performance change which I like.
             * If this is not explicitly set to null, the CLR will do a registry hit for each request to use the default proxy.
             */
            httpRequest.Proxy = null;

            if (requestToBroker.HttpMethod.Equals("POST", StringComparison.InvariantCultureIgnoreCase))
            {
                BridgeAndCloseStreams(requestToBroker.InputStream, httpRequest.GetRequestStream());
            }

            return httpRequest;
        }

        /// <summary>
        /// Convert System.Net.Cookie into System.Web.HttpCookie
        /// </summary>
        private static HttpCookie CookieToHttpCookie(Cookie cookie)
        {
            HttpCookie httpCookie = new HttpCookie(cookie.Name);

            foreach (string value in cookie.Value.Split('&'))
            {
                string[] val = value.Split('=');
                httpCookie.Values.Add(val[0], val[1]);
            }

            httpCookie.Domain = cookie.Domain;
            httpCookie.Expires = cookie.Expires;
            httpCookie.HttpOnly = cookie.HttpOnly;
            httpCookie.Path = cookie.Path;
            httpCookie.Secure = cookie.Secure;

            return httpCookie;
        }

        /// <summary>
        /// Reads from stream into the to stream
        /// </summary>
        private static void BridgeAndCloseStreams(Stream from, Stream to)
        {
            try
            {
                int read;
                do
                {
                    read = from.ReadByte();

                    if (read != -1)
                    {
                        to.WriteByte((byte)read);
                    }
                }
                while (read != -1);
            }
            finally 
            {
                from.Close();
                to.Close();
            }
        }
    }
}

1

Це спрацювало, як сказав Кевін.

Я використовую статичний метод для отримання HttpContext.Current.Request, і тому завжди маю HttpRequestоб’єкт для використання, коли це потрібно.

Тут, у Class Helper

public static HttpRequest GetRequest()
{
    return HttpContext.Current.Request;
}

Тут, у Controller

if (AcessoModel.UsuarioLogado(Helper.GetRequest()))

Тут у Перегляді

bool bUserLogado = ProjectNamespace.Models.AcessoModel.UsuarioLogado(
                      ProjectNamespace.Models.Helper.GetRequest()
                   );

if (bUserLogado == false) { Response.Redirect("/"); }

Мій метод UsuarioLogado

public static bool UsuarioLogado(HttpRequest Request)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.