Jak przekonwertować HttpRequestBase na obiekt HttpRequest?

87

wewnątrz mojego kontrolera ASP.NET MVC mam metodę, która wymaga HttpRequestobiektu. Jedyne, do czego mam dostęp, to HttpRequestBaseobiekt.

Czy w ogóle mogę to jakoś przekonwertować?

Co mogę / powinienem zrobić?

Pure.Krome
źródło
4
Uwaga: „Przeciwieństwem” tego pytania jest tutaj stackoverflow.com/questions/15275370/…
Simon_Weaver

Odpowiedzi:

50

Czy to twoja metoda, więc możesz ją ponownie napisać HttpRequestBase? Jeśli nie, zawsze możesz przekazać prąd HttpRequestz HttpContext.Current.HttpRequest. Jednak często zawijam dostęp do HttpContext wewnątrz klasy, jak wspomniano w ASP.NET: Usuwanie zależności System.Web w celu lepszej obsługi testów jednostkowych.

Kevin Hakanson
źródło
4
Żenująco, ja też o tym pomyślałem i to nie działa. HttpContext jest kontekstem MVC, więc nie ma w nim żadnej właściwości „Current”. Nie jestem pewien, jak uzyskać dostęp do „oldschool” HttpContext.Current ... ???
Pure.Krome,
48
Aby upewnić się, że pobierasz klasę HttpContext zamiast elementu członkowskiego kontrolera, spróbuj użyć System.Web.HttpContext.Current.
Kevin Hakanson
1
Musiałem użyć pełnej przestrzeni nazw, ponieważ pobierała bieżącą właściwość przestrzeni nazw MVC. Twoje zdrowie. Uwaga dla innych: nie rób tego, co ja. to jest VeryBadThing (tm).
Pure.Krome
Link nie żyje; developmentalmadness.com domena wygasła, strona wypełniacz GoDaddy teraz
Chris Moschini
2
System.Web.HttpContext.Current.Request
Jenny O'Reilly
72

Powinieneś zawsze używać HttpRequestBase i HttpResponseBase w swojej aplikacji w przeciwieństwie do wersji konkretnych, których nie można przetestować (bez blokowania typu lub innej magii).

Po prostu użyj klasy HttpRequestWrapper, aby przekonwertować, jak pokazano poniżej.

var httpRequestBase = new HttpRequestWrapper(Context.Request);
CountZero
źródło
2
Inna uwaga, że nie należy używać HttpRequestBase, a HttpResponseBasetakże HttpContextBase. :)
Junle Li
30

Możesz po prostu użyć

System.Web.HttpContext.Current.Request

Kluczem jest to, że aby dostać się do „prawidłowego” HttpContext, potrzebujesz pełnej przestrzeni nazw.

Wiem, że minęły 4 lata, odkąd zadano to pytanie, ale jeśli to komuś pomoże, to proszę bardzo!

(Edycja: Widzę, że Kevin Hakanson już udzielił tej odpowiedzi ... więc mam nadzieję, że moja odpowiedź pomoże tym, którzy po prostu czytają odpowiedzi, a nie komentarze.) :)

adamgede
źródło
9

Spróbuj użyć / utworzyć HttpRequestWrapper przy użyciu HttpRequestBase.

Klaas
źródło
8

Aby uzyskać HttpRequest w ASP.NET MVC4 .NET 4.5, możesz wykonać następujące czynności:

this.HttpContext.ApplicationInstance.Context.Request
Mohamed Mansour
źródło
4

Zwykle, gdy potrzebujesz uzyskać dostęp do HttpContextwłaściwości w akcji kontrolera, jest coś, co możesz zrobić lepiej, mądrze zaprojektować.

Na przykład, jeśli chcesz uzyskać dostęp do bieżącego użytkownika, nadaj swojej metodzie akcji parametr typu IPrincipal, który Attributepodczas testowania wypełniasz znakiem i mock, jak chcesz. Mały przykład, jak to zrobić , znajduje się w tym poście na blogu , a konkretnie w punkcie 7.

Tomas Aschan
źródło
Całkowicie zgodził! Problem polega na tym, że nie mogę zmodyfikować bieżącej biblioteki klas, z której mamy korzystać ... więc to mi nie pomaga :(
Pure.Krome
2

Nie ma możliwości konwersji między tymi typami.

Mieliśmy podobny przypadek. Przepisaliśmy nasze metody klas / usług internetowych, aby używały HttpContextBase, HttpApplicationStateBase, HttpServerUtilityBase, HttpSessionStateBase ... zamiast typów nazw bliskich bez przyrostka „Base” (HttpContext, ... HttpSessionState). Są o wiele łatwiejsze w obsłudze dzięki domowej roboty kpinie.

Przykro mi, że nie mogłeś tego zrobić.

Barbara Post
źródło
1
Nie true.var httpRequest = Context.Request; var httpRequestBase = new HttpRequestWrapper (Context.Request);
CountZero
2

To jest ASP.Net MVC 3.0 AsyncController, który akceptuje żądania, konwertuje przychodzący obiekt HttpRequestBase MVC na System.Web.HttpWebRequest. Następnie wysyła żądanie asynchronicznie. Gdy odpowiedź wróci, konwertuje System.Web.HttpWebResponse z powrotem na obiekt MVC HttpResponseBase, który może zostać zwrócony przez kontroler MVC.

Aby jednoznacznie odpowiedzieć na to pytanie, myślę, że interesuje Cię tylko funkcja BuildWebRequest (). Pokazuje jednak, jak przejść przez cały potok - konwersję z BaseRequest> Request, a następnie Response> BaseResponse. Pomyślałem, że przydałoby się udostępnienie obu.

Dzięki tym klasom możesz mieć serwer MVC, który działa jako internetowy serwer proxy.

Mam nadzieję że to pomoże!

Kontroler:

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

To jest klasa proxy, która wykonuje ciężkie prace:

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
źródło
1

Zadziałało tak, jak powiedział Kevin.

Używam metody statycznej do pobierania HttpContext.Current.Request, więc zawsze mam HttpRequestobiekt do użycia w razie potrzeby.

Tutaj w pomocniku klasy

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

Tutaj w kontrolerze

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

Tutaj w widoku

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

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

Moja metoda UsuarioLogado

public static bool UsuarioLogado(HttpRequest Request)
RogerGales
źródło