Есть способ, но он требует пару классов.
Когда ASP.NET MVC регистрирует маршрут, он определяет обработчик маршрута.Этот обработчик маршрута возвращает обработчик HTTP, который обрабатывает запрос.Если вы используете настраиваемый обработчик маршрута, который возвращает настраиваемый обработчик HTTP, вы можете переписать контекст HTTP, используя пару классов декораторов.
Начните с создания HttpContextProxy
и HttpRequestProxy
, производных от базовых классов.и оборачивает все методы и свойства во внутренний экземпляр.Я сделал тяжелую работу доступной .
Затем создайте декораторы, сначала декоратор HTTP-контекста:
using System.Web;
public class HttpContextDecorator : HttpContextProxy
{
public HttpContextDecorator(HttpContextBase innerHttpContext)
: base(innerHttpContext)
{
}
public override HttpRequestBase Request
{
get
{
return new HttpRequestDecorator(base.Request);
}
}
}
Декоратор HTTP-запроса:
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;
}
}
}
Как уже упоминалось, вам также необходимо переопределить классы MVC - здесь обработчик HTTP:
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);
}
}
Затем обработчик маршрута:
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);
}
}
Наконец, вынеобходимо заменить связанный обработчик для всех зарегистрированных маршрутов (или правильно отобразить их с самого начала):
var routes = RouteTable.Routes.OfType<Route>().Where(x => x.RouteHandler is MvcRouteHandler);
foreach (var route in routes)
{
route.RouteHandler = new CustomMvcRouteHandler();
}