¿Cómo convierto una HttpRequestBase en un objeto HttpRequest?

87

dentro de mi controlador ASP.NET MVC, tengo un método que requiere un HttpRequestobjeto. Todo lo que tengo acceso es un HttpRequestBaseobjeto.

¿Hay alguna forma de que pueda convertir esto de alguna manera?

¿Qué puedo / debo hacer?

Pure.Krome
fuente
4
Nota: El 'opuesto' de esta pregunta está aquí stackoverflow.com/questions/15275370/…
Simon_Weaver

Respuestas:

50

¿Es su método, por lo que puede volver a escribirlo para tomarlo HttpRequestBase? Si no, siempre se puede obtener la corriente HttpRequestde HttpContext.Current.HttpRequesttransmitir. Sin embargo, a menudo envuelvo el acceso a HttpContext dentro de una clase como se menciona en ASP.NET: Eliminación de las dependencias de System.Web para una mejor compatibilidad con las pruebas unitarias.

Kevin Hakanson
fuente
4
Vergonzosamente, también pensé en esto y no funciona. El HttpContext es el contexto MVC ... por lo que no hay una propiedad 'Actual' expuesta en él. No estoy seguro de cómo obtener acceso a HttpContext.Current 'oldschool' ... ???
Pure.Krome
48
Para asegurarse de que está tomando la clase HttpContext en lugar del miembro controlador, intente usar System.Web.HttpContext.Current.
Kevin Hakanson
1
Necesitaba usar el espacio de nombres completo porque estaba tomando la propiedad actual del espacio de nombres MVC. salud. Nota para los demás: no hagas lo que estoy haciendo. es un VeryBadThing (tm).
Pure.Krome
Link está muerto; El dominio developmentmadness.com expiró, la página de relleno de GoDaddy ahora
Chris Moschini
2
System.Web.HttpContext.Current.Request
Jenny O'Reilly
72

Siempre debe usar HttpRequestBase y HttpResponseBase en su aplicación a diferencia de las versiones concretas que son imposibles de probar (sin typemock o alguna otra magia).

Simplemente use la clase HttpRequestWrapper para convertir como se muestra a continuación.

var httpRequestBase = new HttpRequestWrapper(Context.Request);
CountZero
fuente
2
Otra nota que, no solo usa HttpRequestBasey HttpResponseBase, también HttpContextBase. :)
Junle Li
30

Puedes usar

System.Web.HttpContext.Current.Request

La clave aquí es que necesita el espacio de nombres completo para llegar al HttpContext "correcto".

Sé que han pasado 4 años desde que se hizo esta pregunta, pero si esto ayudará a alguien, ¡aquí tiene!

(Editar: Veo que Kevin Hakanson ya dio esta respuesta ... así que espero que mi respuesta ayude a aquellas personas que solo leen respuestas y no comentarios) :)

Adamgede
fuente
9

Intente usar / crear un HttpRequestWrapper usando su HttpRequestBase.

Klaas
fuente
8

Para obtener HttpRequest en ASP.NET MVC4 .NET 4.5, puede hacer lo siguiente:

this.HttpContext.ApplicationInstance.Context.Request
Mohamed Mansour
fuente
4

Normalmente, cuando necesita acceder a la HttpContextpropiedad en una acción de controlador, hay algo que puede hacer mejor en cuanto al diseño.

Por ejemplo, si necesita acceder al usuario actual, asigne a su método de acción un parámetro de tipo IPrincipal, que debe completar con Attributey simular como desee al realizar la prueba. Para ver un pequeño ejemplo de cómo, consulte esta publicación de blog , y específicamente el punto 7.

Tomas Aschan
fuente
¡Totalmente de acuerdo! El problema es que no puedo modificar la biblioteca de clases actual que debemos usar ... así que esto no me ayuda mucho :(
Pure.Krome
2

No hay forma de convertir entre estos tipos.

Tuvimos un caso similar. Reescribimos nuestros métodos de clases / servicios web para que usen HttpContextBase, HttpApplicationStateBase, HttpServerUtilityBase, HttpSessionStateBase ... en lugar de los tipos de nombre de cierre sin el sufijo "Base" (HttpContext, ... HttpSessionState). Son mucho más fáciles de manejar con burlas caseras.

Siento que no pudieras hacerlo.

Barbara Post
fuente
1
No es cierto.var httpRequest = Context.Request; var httpRequestBase = new HttpRequestWrapper (Context.Request);
CountZero
2

Este es un ASP.Net MVC 3.0 AsyncController que acepta solicitudes, convierte el objeto HttpRequestBase MVC entrante en un System.Web.HttpWebRequest. Luego envía la solicitud de forma asincrónica. Cuando la respuesta regresa, vuelve a convertir System.Web.HttpWebResponse en un objeto MVC HttpResponseBase que se puede devolver a través del controlador MVC.

Para responder esta pregunta explícitamente, supongo que solo estaría interesado en la función BuildWebRequest (). Sin embargo, demuestra cómo moverse a través de toda la canalización: conversión de BaseRequest> Solicitud y luego Respuesta> BaseResponse. Pensé que compartir ambos sería útil.

A través de estas clases, puede tener un servidor MVC que actúa como proxy web.

¡Espero que esto ayude!

Controlador:

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

Esta es la clase de proxy que hace el trabajo pesado:

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();
            }
        }
    }
}
Kenn
fuente
1

Funcionó como dijo Kevin.

Estoy usando un método estático para recuperar el HttpContext.Current.Request, por lo que siempre tengo un HttpRequestobjeto para usar cuando sea necesario.

Ayudante aquí en clase

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

Aquí en Controller

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

Aquí en vista

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

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

Mi Método UsuarioLogado

public static bool UsuarioLogado(HttpRequest Request)
RogerGales
fuente