关于MVC RouteExistingFiles疑问后续
前两天写了《关于MVC RouteExistingFiles疑问》,本来希望寻求大佬快速解答,奈何无人问津。
只能查看.NET 源代码,可以使用反编译工具(我用IL spy),也可以在线查看微软提供的:https://referencesource.microsoft.com/
MVC的路由会走UrlRoutingModule,代码在 System.Web/Routing/UrlRoutingModule.cs 中
RouteData routeData = RouteCollection.GetRouteData(context);
GetRouteData的源代码:
public RouteData GetRouteData(HttpContextBase httpContext) { if (httpContext == null) { throw new ArgumentNullException("httpContext"); } if (httpContext.Request == null) { throw new ArgumentException(SR.GetString(SR.RouteTable_ContextMissingRequest), "httpContext"); } // Optimize performance when the route collection is empty. The main improvement is that we avoid taking // a read lock when the collection is empty. Without this check, the UrlRoutingModule causes a 25%-50% // regression in HelloWorld RPS due to lock contention. The UrlRoutingModule is now in the root web.config, // so we need to ensure the module is performant, especially when you are not using routing. // This check does introduce a slight bug, in that if a writer clears the collection as part of a write // transaction, a reader may see the collection when it's empty, which the read lock is supposed to prevent. // We will investigate a better fix in Dev10 Beta2. The Beta1 bug is Dev10 652986. if (Count == 0) { return null; } bool isRouteToExistingFile = false; bool doneRouteCheck = false; // We only want to do the route check once if (!RouteExistingFiles) { isRouteToExistingFile = IsRouteToExistingFile(httpContext); doneRouteCheck = true; if (isRouteToExistingFile) { // If we're not routing existing files and the file exists, we stop processing routes return null; } } // Go through all the configured routes and find the first one that returns a match using (GetReadLock()) { foreach (RouteBase route in this) { RouteData routeData = route.GetRouteData(httpContext); if (routeData != null) { // If we're not routing existing files on this route and the file exists, we also stop processing routes if (!route.RouteExistingFiles) { if (!doneRouteCheck) { isRouteToExistingFile = IsRouteToExistingFile(httpContext); doneRouteCheck = true; } if (isRouteToExistingFile) { return null; } } return routeData; } } } return null; }
说实话,没看出来什么。
好吧,依稀记得可以调试源代码,也是查了一下,配置VS,下载PDB文件,就能调试了。具体设置,微软地址:https://referencesource.microsoft.com/setup.html
有类似需求的同学可以参考这篇文章,能详细点:https://blog.csdn.net/egman/article/details/78281424
然而,不知道什么原因,我用的VS2017怎样都无法进入源代码。
于是一个问题就变成了两个问题。
于是又搜其他办法,发现JB的DotPeek软件可以,官方地址:https://www.jetbrains.com/decompiler/
这里就不详细介绍操作了,可以参考园友博客:https://www.cnblogs.com/herenwei-wayne/p/5595429.html
run起来,终于进入到源码中GetRouteData方法中了
依次请求静态资源地址,进行调试:
①/a.jpg:匹配到默认路由“controller/action/id”,controller是a.jpg
②/Theme/a.jpg:匹配到默认路由“controller/action/id”,controller是Theme,Action是a.jpg
③/Areas/Admin/a.jpg:匹配到默认路由“controller/action/id”...
④/Areas/Admin/Theme/a.jpg:未匹配到任何路由,renturn
之前的理解是,
1.配到到路由,比如输入a/b/1,但未找到对应的控制器等,提示不存在
2.未匹配到路由,比如输入a/b/c/d/e/f,也会提示不存在
但事实上,
1.配到到路由,比如输入a/b/1,但未找到对应的控制器等,提示不存在(程序可以捕获)
2.未匹配到路由,比如输入a/b/c/d/e/f,路由中return,交由IIS处理
所以,如果利用此特性做文件夹的访问控制,一定要设置对应文件夹的路由规则,然后处理。