My problem is pretty simple. I've got a Uri and I want to figure out which route it maps to so I can do some checks on the various pieces of the route: controller, action, etc.
How do I go from Uri to RouteData or Route?
Based on @tvanfosson's direction, I came up with a class that does what I need. Note that the GetRouteData
actually looks at the AppRelativeCurrentExecutionFilePath
and the PathInfo
properties on the RequestContextBase
class, not the Url
property.
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; } }
}
}
You might try extending HttpRequestBase and override the Uri property so that you can assign your Uri to the property on the request. Then override HttpContextBase to allow you to set the Request property on the context. You can then use the GetRouteData() method on the RouteCollection class to get a suitable RouteValueDictionary. Note that the RouteCollection is available as a static property on the RouteTable class.
var myRequest = new MyRequest( myUri );
var myContext = new MyContext( myRequest );
var routeData = RouteTable.Routes.GetRouteData( myContext );
Update:
For your use case (comments), you might be able to simply match on the controller/action:
if (myUri.ToString().ToLower().Contains( "/controller/action" ))
{
return RedirectToAction( action, controller, new { ...route data } );
}
else
{
return Redirect( "http://www.example.com/default" );
}
Depending on if you are okay with changing the path of the current request (In my case I am) here is a very easy solution that doesn't involve mocking up anything:
HttpContext httpContext = HttpContext.Current;
httpContext.RewritePath(URL);
RouteData route = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With