2009-12-10 3 views
4

Mon problème est assez simple. J'ai un Uri et je veux savoir sur quelle route il mappe afin que je puisse faire des vérifications sur les différentes parties de la route: contrôleur, action, etc.ASP.NET MVC: Uri à données de route utilisables

Comment passer d'Uri à RouteData ou Route?

Répondre

4

, je est venu avec une classe qui fait ce dont j'ai besoin. Notez que le GetRouteData regarde réellement les propriétés AppRelativeCurrentExecutionFilePath et PathInfo sur la propriété RequestContextBase, pas la propriété 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; } } 
    } 
} 
+0

Note: Cela devrait probablement avoir quelques vérifications supplémentaires pour s'assurer que le Uri est absolu ... sinon, ça craps. – mkedobbs

2

Vous pouvez essayer d'étendre HttpRequestBase et remplacer la propriété Uri afin que vous puissiez affecter votre Uri à la propriété dans la requête. Puis remplacez HttpContextBase pour vous permettre de définir la propriété Request sur le contexte. Vous pouvez ensuite utiliser la méthode GetRouteData() sur la classe RouteCollection pour obtenir un RouteValueDictionary approprié. Notez que RouteCollection est disponible en tant que propriété statique sur la classe RouteTable.

var myRequest = new MyRequest(myUri); 
var myContext = new MyContext(myRequest); 
var routeData = RouteTable.Routes.GetRouteData(myContext); 

Mise à jour:

Pour votre cas d'utilisation (commentaires), vous pourriez être en mesure de faire correspondre simplement sur le contrôleur/action:

Sur la base de la direction de @ tvanfosson
if (myUri.ToString().ToLower().Contains("/controller/action")) 
{ 
    return RedirectToAction(action, controller, new { ...route data }); 
} 
else 
{ 
    return Redirect("http://www.example.com/default"); 
} 
+2

Wow . On dirait qu'il devrait vraiment y avoir une façon moins compliquée que ça ... – mkedobbs

+0

Je n'ai jamais vraiment eu besoin de le faire car le framework le gère. Quel est exactement votre cas d'utilisation? – tvanfosson

+0

Tout ce que j'ai à faire est un Uri et j'ai besoin de rediriger si cet Uri répond à certains critères (mapper à un contrôleur spécifique avec une action spécifique), sinon rediriger vers un Uri par défaut. – mkedobbs

1

Selon si vous êtes d'accord avec la modification du chemin de la requête en cours (Dans mon cas, je suis) ici est une solution très facile qui ne nécessite pas moqueur quoi que ce soit:

HttpContext httpContext = HttpContext.Current; 
httpContext.RewritePath(URL); 
RouteData route = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));