wewnątrz mojego kontrolera ASP.NET MVC mam metodę, która wymaga HttpRequest
obiektu. Jedyne, do czego mam dostęp, to HttpRequestBase
obiekt.
Czy w ogóle mogę to jakoś przekonwertować?
Co mogę / powinienem zrobić?
wewnątrz mojego kontrolera ASP.NET MVC mam metodę, która wymaga HttpRequest
obiektu. Jedyne, do czego mam dostęp, to HttpRequestBase
obiekt.
Czy w ogóle mogę to jakoś przekonwertować?
Co mogę / powinienem zrobić?
Odpowiedzi:
Czy to twoja metoda, więc możesz ją ponownie napisać HttpRequestBase
? Jeśli nie, zawsze możesz przekazać prąd HttpRequest
z 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.
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);
HttpRequestBase
, a HttpResponseBase
także HttpContextBase
. :)
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.) :)
Aby uzyskać HttpRequest w ASP.NET MVC4 .NET 4.5, możesz wykonać następujące czynności:
this.HttpContext.ApplicationInstance.Context.Request
Zwykle, gdy potrzebujesz uzyskać dostęp do HttpContext
wł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 Attribute
podczas 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.
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ć.
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();
}
}
}
}
Zadziałało tak, jak powiedział Kevin.
Używam metody statycznej do pobierania HttpContext.Current.Request
, więc zawsze mam HttpRequest
obiekt do użycia w razie potrzeby.
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)