ASP.NET MVC: Uri для использования данных маршрута
Моя проблема довольно проста. У меня есть Uri, и я хочу выяснить, к какому маршруту он относится, чтобы я мог выполнить некоторые проверки различных частей маршрута: контроллера, действия и т. Д.
Как мне перейти от Uri к RouteData или Route?
3 ответа
Основываясь на руководстве @tvanfosson, я придумал класс, который делает то, что мне нужно. Обратите внимание, что GetRouteData
на самом деле смотрит на AppRelativeCurrentExecutionFilePath
и PathInfo
свойства на RequestContextBase
класс, а не Url
имущество.
public class RouteInfo
{
public RouteInfo(RouteData data)
{
RouteData = data;
}
public RouteInfo(Uri uri, string applicationPath)
{
RouteData = RouteTable.Routes.GetRouteData(new InternalHttpContext(uri, applicationPath));
}
public RouteData RouteData { get; private set; }
//********************
//Miscellaneous properties here to deal with routing conditionals... (e.g. "CanRedirectFromSignIn")
//********************
private class InternalHttpContext : HttpContextBase
{
private HttpRequestBase _request;
public InternalHttpContext(Uri uri, string applicationPath) : base()
{
_request = new InternalRequestContext(uri, applicationPath);
}
public override HttpRequestBase Request { get { return _request; } }
}
private class InternalRequestContext : HttpRequestBase
{
private string _appRelativePath;
private string _pathInfo;
public InternalRequestContext(Uri uri, string applicationPath) : base()
{
_pathInfo = uri.Query;
if (String.IsNullOrEmpty(applicationPath) || !uri.AbsolutePath.StartsWith(applicationPath, StringComparison.OrdinalIgnoreCase))
{
_appRelativePath = uri.AbsolutePath.Substring(applicationPath.Length);
}
else
{
_appRelativePath = uri.AbsolutePath;
}
}
public override string AppRelativeCurrentExecutionFilePath { get { return String.Concat("~", _appRelativePath); } }
public override string PathInfo { get { return _pathInfo; } }
}
}
Вы можете попробовать расширить HttpRequestBase и переопределить свойство Uri, чтобы вы могли назначить свой Uri свойству по запросу. Затем переопределите HttpContextBase, чтобы позволить вам установить свойство Request в контексте. Затем вы можете использовать метод GetRouteData() класса RouteCollection, чтобы получить подходящий RouteValueDictionary. Обратите внимание, что RouteCollection доступен как статическое свойство в классе RouteTable.
var myRequest = new MyRequest( myUri );
var myContext = new MyContext( myRequest );
var routeData = RouteTable.Routes.GetRouteData( myContext );
Обновление:
Для вашего варианта использования (комментарии) вы можете просто сопоставить контроллер / действие:
if (myUri.ToString().ToLower().Contains( "/controller/action" ))
{
return RedirectToAction( action, controller, new { ...route data } );
}
else
{
return Redirect( "http://www.example.com/default" );
}
В зависимости от того, согласны ли вы с изменением пути текущего запроса (в моем случае это так), здесь очень простое решение, которое не включает в себя макетирование чего-либо:
HttpContext httpContext = HttpContext.Current;
httpContext.RewritePath(URL);
RouteData route = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));