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));
Другие вопросы по тегам