HttpRequestBase를 HttpRequest 객체로 어떻게 변환합니까?


88

내 ASP.NET MVC 컨트롤러 안에 HttpRequest개체 가 필요한 메서드가 있습니다. 내가 접근 할 수있는 것은 HttpRequestBase객체뿐입니다.

어쨌든 내가 어떻게 든 이것을 변환 할 수 있습니까?

무엇을 할 수 있고 /해야합니까 ??


4
참고 :이 질문의 '반대'여기 stackoverflow.com/questions/15275370/...
Simon_Weaver

답변:


50

그것은 당신의 방법입니까, 그래서 그것을 다시 쓸 수 HttpRequestBase있습니까? 그렇지 않은 경우 항상 전류 HttpRequest를 가져와 HttpContext.Current.HttpRequest전달할 수 있습니다. 그러나 ASP.NET : 더 나은 단위 테스트 지원을 위해 System.Web 종속성 제거에 언급 된 것과 같이 클래스 내에서 HttpContext에 대한 액세스를 종종 래핑합니다 .


4
부끄럽게도 이것도 생각했는데 작동하지 않습니다. HttpContext는 MVC 컨텍스트 ..이므로 'Current'속성이 노출되지 않습니다. 'oldschool'HttpContext.Current에 액세스하는 방법을 잘 모르겠습니다 ... ???
Pure.Krome

48
컨트롤러 멤버 대신 HttpContext 클래스를 확보하고 있는지 확인하려면 System.Web.HttpContext.Current를 사용해보십시오.
Kevin Hakanson

1
현재 MVC 네임 스페이스 속성을 사용하기 때문에 전체 네임 스페이스를 사용해야했습니다. 건배. 다른 사람들에게 참고 : 내가하는 일을하지 마십시오. VeryBadThing (tm)입니다.
Pure.Krome

링크가 죽었습니다. developmentalmadness.com 도메인은 GoDaddy와 필러 페이지 현재 만료
크리스 Moschini에게

2
System.Web.HttpContext.Current.Request
제니 오라일리

72

테스트가 불가능한 구체적인 버전 (typemock 또는 다른 마술없이)과는 반대로 항상 애플리케이션에서 HttpRequestBase 및 HttpResponseBase를 사용해야합니다.

HttpRequestWrapper 클래스를 사용하여 아래와 같이 변환하면됩니다.

var httpRequestBase = new HttpRequestWrapper(Context.Request);

2
뿐만 아니라 사용하는 또 다른 노트 HttpRequestBaseHttpResponseBaseHttpContextBase. :)
Junle Li

30

그냥 사용할 수 있습니다

System.Web.HttpContext.Current.Request

여기서 핵심은 "올바른"HttpContext를 얻기 위해 전체 네임 스페이스가 필요하다는 것입니다.

이 질문을받은 지 4 년이 지났다는 것을 알고 있지만 이것이 누군가에게 도움이된다면 여기 있습니다!

(편집 : Kevin Hakanson이 이미이 답변을 주었다는 것을 알고 있습니다 ... 그러면 내 답변이 댓글이 아닌 답변을 읽는 사람들에게 도움이되기를 바랍니다.) :)


9

HttpRequestBase를 사용하여 HttpRequestWrapper를 사용 / 생성 해보십시오.


9

ASP.NET MVC4 .NET 4.5에서 HttpRequest를 얻으려면 다음을 수행 할 수 있습니다.

this.HttpContext.ApplicationInstance.Context.Request

4

일반적으로 HttpContext컨트롤러 작업에서 속성에 액세스해야 할 때 더 나은 디자인 방식으로 수행 할 수있는 작업이 있습니다.

예를 들어 현재 사용자에 액세스해야하는 경우 테스트 할 때 원하는대로 및 mock으로 IPrincipal채울 유형의 매개 변수를 작업 메서드에 제공합니다 Attribute. 방법에 대한 간단한 예는 이 블로그 게시물 , 특히 7 번을 참조하십시오 .


전적으로 동의 한! 문제는 :(이 많은 나에게 도움이되지 않습니다 그래서 ... 우리가 사용하는 데 필요한하고있는 현재의 클래스 라이브러리를 수정할 수 없다
Pure.Krome

2

이러한 유형간에 변환 할 수있는 방법은 없습니다.

비슷한 경우가있었습니다. 클래스 / 웹 서비스 메서드를 다시 작성하여 "Base"접미사 (HttpContext, ... HttpSessionState)가없는 닫기 이름 유형 대신 HttpContextBase, HttpApplicationStateBase, HttpServerUtilityBase, HttpSessionStateBase ...를 사용합니다. 집에서 만든 조롱으로 처리하기가 훨씬 쉽습니다.

못해서 미안해.


1
true가 아님 .var httpRequest = Context.Request; var httpRequestBase = new HttpRequestWrapper (Context.Request);
CountZero 2013

2

이것은 요청을 받아들이고 인바운드 HttpRequestBase MVC 개체를 System.Web.HttpWebRequest로 변환하는 ASP.Net MVC 3.0 AsyncController입니다. 그런 다음 요청을 비동기 적으로 보냅니다. 응답이 돌아 오면 System.Web.HttpWebResponse를 MVC 컨트롤러를 통해 반환 할 수있는 MVC HttpResponseBase 개체로 다시 변환합니다.

이 질문에 명시 적으로 대답하려면 BuildWebRequest () 함수에만 관심이있을 것 같습니다. 그러나 전체 파이프 라인을 이동하는 방법을 보여줍니다. BaseRequest> 요청에서 응답> 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

Kevin이 말한 것처럼 작동했습니다.

을 검색하기 위해 정적 메서드를 사용 HttpContext.Current.Request하고 있으므로 HttpRequest필요할 때 항상 사용할 개체가 있습니다.

여기 클래스 도우미에서

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

여기 컨트롤러에서

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.