ฉันจะแปลง HttpRequestBase เป็นวัตถุ HttpRequest ได้อย่างไร


89

ภายในตัวควบคุม ASP.NET MVC ของฉันฉันมีวิธีการที่ต้องใช้HttpRequestวัตถุ ทั้งหมดที่ฉันสามารถเข้าถึงได้คือHttpRequestBaseวัตถุ

ฉันสามารถแปลงสิ่งนี้ได้หรือไม่?

ทำอะไรได้บ้าง ??


4
หมายเหตุ: 'ตรงข้าม' ของคำถามนี้อยู่ที่นี่stackoverflow.com/questions/15275370/…
Simon_Weaver

คำตอบ:


50

เป็นวิธีการของคุณดังนั้นคุณสามารถเขียนใหม่ได้HttpRequestBaseหรือไม่? ถ้าไม่คุณสามารถรับกระแสHttpRequestจากHttpContext.Current.HttpRequestการส่งต่อได้ตลอดเวลา อย่างไรก็ตามฉันมักจะปิดการเข้าถึง HttpContext ภายในคลาสดังที่กล่าวไว้ในASP.NET: Removing System Web Dependenciesเพื่อรองรับการทดสอบหน่วยที่ดีขึ้น


4
ด้วยความยินดีฉันก็คิดเช่นนี้และมันก็ไม่ได้ผล HttpContext เป็นบริบท MVC .. ดังนั้นจึงไม่มีคุณสมบัติ 'ปัจจุบัน' ที่เปิดเผยอยู่ ฉันไม่แน่ใจว่าจะเข้าถึง HttpContext 'oldschool' ได้อย่างไรปัจจุบัน ... ???
Pure.Krome

48
เพื่อให้แน่ใจว่าคุณกำลังคว้าคลาส HttpContext แทนสมาชิกคอนโทรลเลอร์ให้ลองใช้ System.Web.HttpContext.Current
Kevin Hakanson

1
ฉันจำเป็นต้องใช้เนมสเปซแบบเต็มเนื่องจากใช้คุณสมบัติเนมสเปซ MVC ปัจจุบัน ไชโย หมายเหตุสำหรับผู้อื่น: อย่าทำในสิ่งที่ฉันกำลังทำ มันเป็น VeryBadThing (tm)
Pure.Krome

ลิงค์ตายแล้ว; developmentalmadness.com โดเมนหมดอายุหน้าตัวเติม GoDaddy ตอนนี้
Chris Moschini

2
System.Web.HttpContext.Current.Request
Krisztián Balla

72

คุณควรใช้ HttpRequestBase และ HttpResponseBase ในแอปพลิเคชันของคุณเสมอเมื่อเทียบกับเวอร์ชันคอนกรีตซึ่งไม่สามารถทดสอบได้ (โดยไม่ใช้ typemock หรือเวทมนตร์อื่น ๆ )

เพียงใช้คลาสHttpRequestWrapperเพื่อแปลงดังที่แสดงด้านล่าง

var httpRequestBase = new HttpRequestWrapper(Context.Request);

3
ทราบว่าไม่เพียง แต่ใช้อีกHttpRequestBaseและยังHttpResponseBase HttpContextBase:)
Junle Li

นั่นกำลังแปลงไปในทิศทางที่ไม่ถูกต้อง คำถามคือถ้าผมมีHttpRequestBaseฉันจะได้รับที่เกิดขึ้นจริงHttpRequestจากมันได้หรือไม่
Suncat2000

30

คุณสามารถใช้

System.Web.HttpContext.Current.Request

ที่สำคัญคือคุณต้องมีเนมสเปซแบบเต็มเพื่อไปยัง HttpContext "ถูกต้อง"

ฉันรู้ว่ามันเป็นเวลา 4 ปีแล้วที่คำถามนี้ถูกถาม แต่ถ้าสิ่งนี้จะช่วยใครสักคนได้ก็ไปเลย!

(แก้ไข: ฉันเห็นว่า Kevin Hakanson ให้คำตอบนี้แล้ว ... ดังนั้นหวังว่าคำตอบของฉันจะช่วยให้คนที่เพิ่งอ่านคำตอบและไม่แสดงความคิดเห็น) :)



9

ในการรับ 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
ไม่ใช่ true.var httpRequest = Context.Request; var httpRequestBase = HttpRequestWrapper ใหม่ (Context.Request);
CountZero

2

นี่คือ ASP.Net MVC 3.0 AsyncController ซึ่งรับคำขอแปลงอ็อบเจ็กต์ HttpRequestBase ขาเข้าเป็น 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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.