di dalam pengontrol ASP.NET MVC saya, saya punya metode yang membutuhkan HttpRequest
objek. Yang bisa saya akses hanyalah sebuah HttpRequestBase
objek.
Apakah tetap ada saya entah bagaimana bisa mengubahnya?
Apa yang bisa / harus saya lakukan ??
di dalam pengontrol ASP.NET MVC saya, saya punya metode yang membutuhkan HttpRequest
objek. Yang bisa saya akses hanyalah sebuah HttpRequestBase
objek.
Apakah tetap ada saya entah bagaimana bisa mengubahnya?
Apa yang bisa / harus saya lakukan ??
Jawaban:
Apakah itu metode Anda, sehingga Anda dapat menulis ulang untuk mengambilnya HttpRequestBase
? Jika tidak, Anda selalu bisa mendapatkan arus HttpRequest
dari HttpContext.Current.HttpRequest
untuk meneruskan. Namun, saya sering membungkus akses ke HttpContext di dalam kelas seperti yang disebutkan di ASP.NET: Menghapus Dependensi System.Web untuk dukungan pengujian unit yang lebih baik.
Anda harus selalu menggunakan HttpRequestBase dan HttpResponseBase dalam aplikasi Anda sebagai lawan dari versi konkret yang tidak mungkin untuk diuji (tanpa typemock atau sihir lainnya).
Cukup gunakan kelas HttpRequestWrapper untuk mengonversi seperti yang ditunjukkan di bawah ini.
var httpRequestBase = new HttpRequestWrapper(Context.Request);
HttpRequestBase
dan HttpResponseBase
, juga HttpContextBase
. :)
HttpRequestBase
, bagaimana cara mendapatkan aktual HttpRequest
dari itu?
Anda bisa menggunakan
System.Web.HttpContext.Current.Request
Kuncinya di sini adalah Anda memerlukan namespace lengkap untuk mendapatkan HttpContext yang "benar".
Saya tahu sudah 4 tahun sejak pertanyaan ini diajukan, tetapi jika ini akan membantu seseorang, maka ini dia!
(Sunting: Saya melihat Kevin Hakanson sudah memberikan jawaban ini ... jadi semoga tanggapan saya akan membantu orang-orang yang hanya membaca jawaban dan bukan komentar.) :)
Untuk mendapatkan HttpRequest di ASP.NET MVC4 .NET 4.5, Anda dapat melakukan hal berikut:
this.HttpContext.ApplicationInstance.Context.Request
Biasanya ketika Anda perlu mengakses HttpContext
properti dalam aksi pengontrol, ada sesuatu yang dapat Anda lakukan dengan desain yang lebih baik.
Misalnya, jika Anda perlu mengakses pengguna saat ini, berikan metode tindakan Anda parameter tipe IPrincipal
, yang Anda isi dengan Attribute
dan tiruan seperti yang Anda inginkan saat pengujian. Untuk contoh kecil tentang caranya, lihat posting blog ini , dan secara khusus poin 7.
Tidak ada cara untuk mengonversi di antara tipe-tipe ini.
Kami memiliki kasus serupa. Kami menulis ulang metode kelas / layanan web kami sehingga mereka menggunakan HttpContextBase, HttpApplicationStateBase, HttpServerUtilityBase, HttpSessionStateBase ... alih-alih jenis nama dekat tanpa akhiran "Base" (HttpContext, ... HttpSessionState). Mereka jauh lebih mudah ditangani dengan ejekan buatan sendiri.
Saya merasa menyesal Anda tidak bisa melakukannya.
Ini adalah AsyncController ASP.Net MVC 3.0 yang menerima permintaan, mengubah objek MVC HttpRequestBase masuk ke System.Web.HttpWebRequest. Kemudian mengirimkan permintaan secara asinkron. Ketika respons kembali, itu mengubah System.Web.HttpWebResponse kembali menjadi objek MVC HttpResponseBase yang dapat dikembalikan melalui pengontrol MVC.
Untuk menjawab pertanyaan ini secara eksplisit, saya rasa Anda hanya akan tertarik dengan fungsi BuildWebRequest (). Namun, ini mendemonstrasikan bagaimana untuk berpindah melalui seluruh pipeline - mengkonversi dari BaseRequest> Request dan kemudian Response> BaseResponse. Saya pikir berbagi keduanya akan berguna.
Melalui kelas ini, Anda dapat memiliki server MVC yang bertindak sebagai proxy web.
Semoga ini membantu!
Pengontrol:
[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);
}
}
Ini adalah kelas proxy yang melakukan tugas berat:
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();
}
}
}
}
Ini bekerja seperti yang dikatakan Kevin.
Saya menggunakan metode statis untuk mengambil HttpContext.Current.Request
, dan selalu memiliki HttpRequest
objek untuk digunakan saat diperlukan.
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)