всередині мого контролера ASP.NET MVC, у мене є метод, який вимагає HttpRequest
об'єкта. Все, до чого я маю доступ - це HttpRequestBase
об’єкт.
Чи можу я якось це перетворити?
Що я можу / повинен робити ??
всередині мого контролера ASP.NET MVC, у мене є метод, який вимагає HttpRequest
об'єкта. Все, до чого я маю доступ - це HttpRequestBase
об’єкт.
Чи можу я якось це перетворити?
Що я можу / повинен робити ??
Відповіді:
Це ваш метод, щоб ви могли переписати його, щоб взяти HttpRequestBase
? Якщо немає, то ви завжди можете отримати струм HttpRequest
від HttpContext.Current.HttpRequest
пройти далі. Однак я часто обгортаю доступ до HttpContext всередині класу, як це згадується в ASP.NET: Видалення залежностей System.Web для кращої підтримки модульного тестування.
Ви завжди повинні використовувати HttpRequestBase та HttpResponseBase у своєму додатку, на відміну від конкретних версій, які неможливо перевірити (без typemock чи іншої магії).
Просто використовуйте клас HttpRequestWrapper для перетворення, як показано нижче.
var httpRequestBase = new HttpRequestWrapper(Context.Request);
HttpRequestBase
а HttpResponseBase
, також HttpContextBase
. :)
Ви можете просто використовувати
System.Web.HttpContext.Current.Request
Ключовим тут є те, що вам потрібен повний простір імен, щоб дістатися до "правильного" HttpContext.
Я знаю, що минуло 4 роки з того моменту, як було поставлено це питання, але якщо це комусь допоможе, то ось вам!
(Редагувати: Я бачу, що Кевін Хакансон вже дав цю відповідь ... тому, сподіваюся, моя відповідь допоможе тим людям, які просто читають відповіді, а не коментують.) :)
Щоб отримати HttpRequest в ASP.NET MVC4 .NET 4.5, ви можете зробити наступне:
this.HttpContext.ApplicationInstance.Context.Request
Як правило, коли вам потрібен доступ до HttpContext
властивості під дією контролера, є щось, що ви можете зробити кращим у мудрому дизайні.
Наприклад, якщо вам потрібен доступ до поточного користувача, вкажіть для вашого методу дії параметр типу IPrincipal
, який ви заповнюєте знаком Attribute
і макет, як хочете під час тестування. Короткий приклад того, як це, дивіться у цьому дописі в блозі , а саме в пункті 7
Немає можливості конвертувати між цими типами.
У нас був подібний випадок. Ми переписали наші класи / методи веб-служб, щоб вони використовували HttpContextBase, HttpApplicationStateBase, HttpServerUtilityBase, HttpSessionStateBase ... замість типів близького імені без суфікса "Base" (HttpContext, ... HttpSessionState). З ними набагато легше впоратися із саморобними знущаннями.
Мені шкода, що ви не змогли цього зробити.
Це ASP.Net MVC 3.0 AsyncController, який приймає запити, перетворює вхідний об'єкт HttpRequestBase MVC в 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();
}
}
}
}
Це спрацювало, як сказав Кевін.
Я використовую статичний метод для отримання 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("/"); }
public static bool UsuarioLogado(HttpRequest Request)