在.Net MVC中,您将路由定义为RouteCollection
。通过网址帮助程序方法,您可以轻松将controller
+ action
+ optional params
转换为网址。
当.Net MVC处理来自客户端浏览器的请求时,它会清楚地将此URL映射到右侧controller
+ action
,以执行相应的命令。
但是,我无法看到以动态方式访问此路由的方法,这样我就可以将完全限定的URL(或10k + URL列表)转换为其路由组件。
有没有人知道你怎么转,例如,以下字符串输入:
"http://stackoverflow.com/questions/2342325/c-sharp-net-mvc-turning-url-into-controller-action-pair"
进入以下输出:
{
controller: "questions",
action: "view",
id: 2342325,
seoText: "c-sharp-net-mvc-turning-url-into-controller-action-pair"
}
鉴于这种映射显然是由.Net完成的,它是否暴露在任何地方?
为什么有人想要这样做?
想象一下,您有一个您知道已访问过的URL列表,其中大部分是动态的,例如stackoverflow.com/questions/2342325/c-sharp-net-mvc-turning-url-into-controller-action-pair
,您希望找出以编程方式命中的实际端点/操作/控制器(不需要太在意)关于传递的实际数据)。
您可以手动代码映射,以便您知道/questions/{id}/{text}
- > controller: questions, action: question
,但这不是面向未来的,也不是有趣的,而是依赖于文本操作/处理。
给定路线词典和URL列表,使用上述功能,您可以查看哪个控制器最受欢迎,或哪些操作等等。
答案 0 :(得分:2)
您应该看看如何创建自己的MvcRouteHandler。这是MVC堆栈中的一点,路由引擎已经解析了URL以找到要调用的Controller和Action,然后它通过这个方法来获取实际的C#类和方法来调用。尚未授权甚至HTTP Verb,因此您将看到对您的应用程序进行的每次调用。
public class CustomRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext context)
{
var controller = context.RouteData.Values["controller"];
var action = context.RouteData.Values["action"];
// Do whatever logging you want with this data, maybe grab the other params too.
return base.GetHttpHandler(context);
}
}
可以在设置路由的位置轻松注册。
routes.MapRoute("Home", "{controller}/{action}", new
{
controller = "Home",
action = "Index"
})
.RouteHandler = new CustomRouteHandler();
答案 1 :(得分:1)
看起来这样做的唯一方法是创建一个虚拟HTTP上下文,类似于单元测试路由的方式。遗憾的是MVC并没有提供更好的访问权限,因为它是在每个请求上运行的,而不是将它包装在上下文对象中。
无论如何,这是一个可以修改的工作解决方案,以满足您的需求:
public class UrlToRouteMapper
{
public static RouteValueDictionary GetRouteDataFromURL(string absoluteURL)
{
var testUrl = "~" + new Uri(absoluteURL).AbsolutePath;
var context = new StubHttpContextForRouting(requestUrl: testUrl);
var routes = new System.Web.Routing.RouteCollection();
MvcApplication.RegisterRoutes(routes);
System.Web.Routing.RouteData routeData = routes.GetRouteData(context);
return routeData.Values;
}
public static string GetEndpointStringFromURL(string absoluteURL)
{
var routeData = GetRouteDataFromURL(absoluteURL);
return routeData["controller"] + "/" + routeData["action"];
}
}
public class StubHttpContextForRouting : HttpContextBase {
StubHttpRequestForRouting _request;
StubHttpResponseForRouting _response;
public StubHttpContextForRouting(string appPath = "/", string requestUrl = "~/") {
_request = new StubHttpRequestForRouting(appPath, requestUrl);
_response = new StubHttpResponseForRouting();
}
public override HttpRequestBase Request {
get { return _request; }
}
public override HttpResponseBase Response {
get { return _response; }
}
}
public class StubHttpRequestForRouting : HttpRequestBase {
string _appPath;
string _requestUrl;
public StubHttpRequestForRouting(string appPath, string requestUrl) {
_appPath = appPath;
_requestUrl = requestUrl;
}
public override string ApplicationPath {
get { return _appPath; }
}
public override string AppRelativeCurrentExecutionFilePath {
get { return _requestUrl; }
}
public override string PathInfo {
get { return ""; }
}
}
public class StubHttpResponseForRouting : HttpResponseBase {
public override string ApplyAppPathModifier(string virtualPath) {
return virtualPath;
}
}