ASP.NET MVC denetleyicimin içinde, HttpRequest
nesne gerektiren bir yöntemim var . Erişimim olan tek şey bir HttpRequestBase
nesne.
Bunu bir şekilde dönüştürebileceğim bir şey var mı?
Ne yapabilirim / yapmalıyım?
ASP.NET MVC denetleyicimin içinde, HttpRequest
nesne gerektiren bir yöntemim var . Erişimim olan tek şey bir HttpRequestBase
nesne.
Bunu bir şekilde dönüştürebileceğim bir şey var mı?
Ne yapabilirim / yapmalıyım?
Yanıtlar:
Yöntemin mi, yani tekrar yazmak için HttpRequestBase
mi? Değilse, her zaman akımı elde edebilirsiniz HttpRequest
dan HttpContext.Current.HttpRequest
aktarmak. Ancak, daha iyi birim testi desteği için ASP.NET: System.Web Bağımlılıklarını Kaldırma'da belirtildiği gibi bir sınıf içinde HttpContext'e erişimi sık sık sarıyorum .
Test edilmesi imkansız olan (typemock veya başka bir sihir olmadan) somut sürümlerin aksine, uygulamanızda her zaman HttpRequestBase ve HttpResponseBase'i kullanmalısınız.
Aşağıda gösterildiği gibi dönüştürmek için yalnızca HttpRequestWrapper sınıfını kullanın.
var httpRequestBase = new HttpRequestWrapper(Context.Request);
HttpRequestBase
ve HttpResponseBase
ayrıca, HttpContextBase
. :)
HttpRequestBase
, nasıl yok olsun gerçek HttpRequest
ondan?
Sadece kullanabilirsin
System.Web.HttpContext.Current.Request
Buradaki anahtar, "doğru" HttpContext'e ulaşmak için tam ad alanına ihtiyacınız olmasıdır.
Bu sorunun sorulmasının üzerinden 4 yıl geçtiğini biliyorum, ama bu birisine yardımcı olacaksa, o zaman buyrun!
(Düzenleme: Kevin Hakanson'un bu cevabı zaten verdiğini görüyorum ... bu yüzden umarım cevabım yorumları değil, sadece cevapları okuyanlara yardımcı olur.) :)
ASP.NET MVC4 .NET 4.5'te HttpRequest almak için aşağıdakileri yapabilirsiniz:
this.HttpContext.ApplicationInstance.Context.Request
Tipik olarak HttpContext
, bir denetleyici eyleminde özelliğe erişmeniz gerektiğinde , tasarım açısından daha iyi yapabileceğiniz bir şey vardır.
Örneğin, geçerli kullanıcıya erişmeniz gerekiyorsa, eylem yönteminize test sırasında istediğiniz gibi IPrincipal
bir Attribute
ve alay ile dolduracağınız bir tür parametresi verin . Nasıl yapılacağına dair küçük bir örnek için bu blog gönderisine bakın ve özellikle 7. noktaya bakın.
Bu türler arasında dönüştürme yapmanın bir yolu yoktur.
Benzer bir davamız vardı. Sınıfları / web hizmetleri yöntemlerimizi, "Base" soneki (HttpContext, ... HttpSessionState) olmayan close name türleri yerine HttpContextBase, HttpApplicationStateBase, HttpServerUtilityBase, HttpSessionStateBase ... kullanacak şekilde yeniden yazdık. Ev yapımı alaylarla başa çıkmak çok daha kolaydır.
Yapamadığın için üzgünüm.
Bu, istekleri kabul eden, gelen HttpRequestBase MVC nesnesini System.Web.HttpWebRequest'e dönüştüren bir ASP.Net MVC 3.0 AsyncController'dır. Daha sonra isteği eşzamansız olarak gönderir. Yanıt geri geldiğinde, System.Web.HttpWebResponse'yi, MVC denetleyicisi aracılığıyla döndürülebilen bir MVC HttpResponseBase nesnesine dönüştürür.
Bu soruyu açıkça yanıtlamak için, sanırım yalnızca BuildWebRequest () işleviyle ilgileniyorsunuz. Bununla birlikte, tüm ardışık düzen boyunca nasıl hareket edileceğini gösterir - BaseRequest> Request ve ardından Response> BaseResponse'den dönüştürme. İkisini de paylaşmanın yararlı olacağını düşündüm.
Bu sınıflar aracılığıyla, bir web proxy'si görevi gören bir MVC sunucunuz olabilir.
Bu yardımcı olur umarım!
Denetleyici:
[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);
}
}
Bu, ağır işi yapan proxy sınıfıdır:
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();
}
}
}
}
Kevin'in dediği gibi çalıştı.
Geri almak için statik bir yöntem kullanıyorum HttpContext.Current.Request
ve bu nedenle HttpRequest
gerektiğinde kullanmak için her zaman bir nesneye sahibim .
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("/"); }
public static bool UsuarioLogado(HttpRequest Request)