Wie konvertiere ich eine HttpRequestBase in ein HttpRequest-Objekt?

86

In meinem ASP.NET MVC-Controller habe ich eine Methode, die ein HttpRequestObjekt erfordert . Ich habe nur Zugriff auf ein HttpRequestBaseObjekt.

Kann ich das irgendwie konvertieren?

Was kann / soll ich tun?

Pure.Krome
quelle
4
Hinweis: Das "Gegenteil" dieser Frage ist hier stackoverflow.com/questions/15275370/…
Simon_Weaver

Antworten:

50

Ist es Ihre Methode, damit Sie sie neu schreiben können HttpRequestBase? Wenn nicht, können Sie immer den Strom HttpRequestvon HttpContext.Current.HttpRequestweiterleiten lassen. Ich verpacke den Zugriff auf den HttpContext jedoch häufig in eine Klasse wie in ASP.NET: Entfernen von System.Web-Abhängigkeiten, um eine bessere Unterstützung für Komponententests zu erzielen .

Kevin Hakanson
quelle
4
Peinlich, ich habe auch daran gedacht und es funktioniert nicht. Der HttpContext ist der MVC-Kontext. Daher ist keine 'Current'-Eigenschaft darauf verfügbar. Ich bin mir nicht sicher, wie ich auf 'oldschool' HttpContext.Current zugreifen soll ... ???
Pure.Krome
48
Versuchen Sie, System.Web.HttpContext.Current zu verwenden, um sicherzustellen, dass Sie die HttpContext-Klasse anstelle des Controller-Mitglieds abrufen.
Kevin Hakanson
1
Ich musste den vollständigen Namespace verwenden, da er die aktuelle MVC-Namespace-Eigenschaft verwendete. Prost. Hinweis für andere: Tu nicht das, was ich tue. Es ist ein VeryBadThing (tm).
Pure.Krome
Link ist tot; Die Domain "developmentmadness.com" ist abgelaufen, die GoDaddy-Füllseite jetzt
Chris Moschini,
2
System.Web.HttpContext.Current.Request
Jenny O'Reilly
71

Sie sollten in Ihrer Anwendung immer HttpRequestBase und HttpResponseBase verwenden, im Gegensatz zu den konkreten Versionen, die nicht getestet werden können (ohne Typemock oder andere Magie).

Verwenden Sie einfach die HttpRequestWrapper- Klasse, um wie unten gezeigt zu konvertieren.

var httpRequestBase = new HttpRequestWrapper(Context.Request);
CountZero
quelle
2
Ein weiterer Hinweis, den nicht nur HttpRequestBaseund HttpResponseBaseauch verwenden HttpContextBase. :)
Junle Li
30

Sie können einfach verwenden

System.Web.HttpContext.Current.Request

Der Schlüssel hier ist, dass Sie den vollständigen Namespace benötigen, um zum "richtigen" HttpContext zu gelangen.

Ich weiß, es ist 4 Jahre her, seit diese Frage gestellt wurde, aber wenn dies jemandem hilft, dann können Sie loslegen!

(Bearbeiten: Ich sehe, dass Kevin Hakanson diese Antwort bereits gegeben hat ... also hoffentlich hilft meine Antwort den Leuten, die nur Antworten und keine Kommentare lesen.) :)

Adamgede
quelle
9

Versuchen Sie, einen HttpRequestWrapper mit Ihrer HttpRequestBase zu verwenden / zu erstellen.

Klaas
quelle
8

Um HttpRequest in ASP.NET MVC4 .NET 4.5 abzurufen, haben Sie folgende Möglichkeiten:

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

Wenn Sie HttpContextin einer Controller-Aktion auf die Eigenschaft zugreifen müssen, können Sie in der Regel das Design verbessern.

Wenn Sie beispielsweise auf den aktuellen Benutzer zugreifen müssen, geben Sie Ihrer Aktionsmethode einen Parameter vom Typ IPrincipal, den Sie Attributebeim Testen nach Belieben mit einem und verspotten. Ein kleines Beispiel dazu finden Sie in diesem Blog-Beitrag und speziell in Punkt 7.

Tomas Aschan
quelle
Total einverstanden! Das Problem ist, ich kann die aktuelle Klassenbibliothek, die wir verwenden müssen, nicht ändern. Das hilft mir also nicht viel :(
Pure.Krome
2

Es gibt keine Möglichkeit, zwischen diesen Typen zu konvertieren.

Wir hatten einen ähnlichen Fall. Wir haben unsere Klassen- / Webdienstmethoden so umgeschrieben, dass sie HttpContextBase, HttpApplicationStateBase, HttpServerUtilityBase, HttpSessionStateBase ... anstelle der Typen von engen Namen ohne das Suffix "Base" (HttpContext, ... HttpSessionState) verwenden. Sie sind viel einfacher mit hausgemachtem Spott zu handhaben.

Es tut mir leid, dass du es nicht geschafft hast.

Barbara Post
quelle
1
Nicht true.var httpRequest = Context.Request; var httpRequestBase = neuer HttpRequestWrapper (Context.Request);
CountZero
2

Dies ist ein ASP.Net MVC 3.0 AsyncController, der Anforderungen akzeptiert und das eingehende HttpRequestBase MVC-Objekt in ein System.Web.HttpWebRequest konvertiert. Anschließend wird die Anforderung asynchron gesendet. Wenn die Antwort zurückkommt, konvertiert sie die System.Web.HttpWebResponse zurück in ein MVC HttpResponseBase-Objekt, das über den MVC-Controller zurückgegeben werden kann.

Um diese Frage explizit zu beantworten, interessieren Sie sich vermutlich nur für die Funktion BuildWebRequest (). Es wird jedoch gezeigt, wie Sie sich durch die gesamte Pipeline bewegen - Konvertieren von BaseRequest> Request und dann Response> BaseResponse. Ich dachte, beides zu teilen wäre nützlich.

Über diese Klassen können Sie einen MVC-Server haben, der als Webproxy fungiert.

Hoffe das hilft!

Regler:

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

Dies ist die Proxy-Klasse, die das schwere Heben übernimmt:

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

Es hat funktioniert, wie Kevin gesagt hat.

Ich verwende eine statische Methode, um das abzurufen HttpContext.Current.Request, und habe daher immer ein HttpRequestObjekt zur Verwendung, wenn es benötigt wird.

Hier in Class Helper

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

Hier in Controller

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

Hier im Blick

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

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

Meine Methode UsuarioLogado

public static bool UsuarioLogado(HttpRequest Request)
RogerGales
quelle