Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There is a way, but it requires a couple of classes.</p> <p>When ASP.NET MVC registers a route, it defines a route handler. This route handler returns a HTTP handler that handles the request. If you use a custom route handler that returns a custom HTTP handler, you can rewrite the HTTP context by using a couple decorator classes.</p> <p>Start by creating a <code>HttpContextProxy</code> and <code>HttpRequestProxy</code> that derives from the base classes and wraps all methods and properties to an inner instance. I've made the <a href="https://gist.github.com/1158264" rel="nofollow">hard work available</a>.</p> <p>Next create the decorators, first the HTTP context decorator:</p> <pre><code>using System.Web; public class HttpContextDecorator : HttpContextProxy { public HttpContextDecorator(HttpContextBase innerHttpContext) : base(innerHttpContext) { } public override HttpRequestBase Request { get { return new HttpRequestDecorator(base.Request); } } } </code></pre> <p>The HTTP request decorator:</p> <pre><code>using System; using System.Web; public class HttpRequestDecorator : HttpRequestProxy { public HttpRequestDecorator(HttpRequestBase innerHttpRequest) : base(innerHttpRequest) { } public override bool IsSecureConnection { get { return string.Equals(Headers["X-Forwarded-Proto"], "https", StringComparison.OrdinalIgnoreCase); } } public override Uri Url { get { var url = base.Url; var urlBuilder = new UriBuilder(url); if (IsSecureConnection) { urlBuilder.Port = 443; urlBuilder.Scheme = "https"; } else { urlBuilder.Port = 80; } return urlBuilder.Uri; } } public override string UserHostAddress { get { const string forwardedForHeader = "HTTP_X_FORWARDED_FOR"; var forwardedFor = ServerVariables[forwardedForHeader]; if (forwardedFor != null) { return forwardedFor; } return base.UserHostAddress; } } } </code></pre> <p>As mentioned, you also need to override the MVC classes - here the HTTP handler:</p> <pre><code>using System; using System.Web; using System.Web.Mvc; using System.Web.Routing; public class CustomMvcHandler : MvcHandler { public CustomMvcHandler(RequestContext requestContext) : base(requestContext) { requestContext.HttpContext = new HttpContextDecorator(requestContext.HttpContext); } protected override IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state) { httpContext = new HttpContextDecorator(httpContext); return base.BeginProcessRequest(httpContext, callback, state); } protected override void ProcessRequest(HttpContextBase httpContext) { httpContext = new HttpContextDecorator(httpContext); base.ProcessRequest(httpContext); } } </code></pre> <p>Then the route handler:</p> <pre><code>using System.Web; using System.Web.Mvc; using System.Web.Routing; public class CustomMvcRouteHandler : MvcRouteHandler { protected override IHttpHandler GetHttpHandler(RequestContext requestContext) { return new CustomMvcHandler(requestContext); } } </code></pre> <p>Finally, you'll need to replace the associated handler for all registered routes (or map them properly from the beginning):</p> <pre><code>var routes = RouteTable.Routes.OfType&lt;Route&gt;().Where(x =&gt; x.RouteHandler is MvcRouteHandler); foreach (var route in routes) { route.RouteHandler = new CustomMvcRouteHandler(); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload