通常我不会在这个问题上放一个这样的标题,但我很确定它是一个错误(或设计?)
我创建了一个全新的ASP.NET MVC 3 Web应用程序.
然后我去了/ Home / About页面.
此页面的URL为:
http://localhost:51419/Home/About
然后我将URL更改为:
http://localhost:51419/(A(a))/Home/About
页面工作?看路线值,controller = Home,Action = About.第一部分被忽略了?
如果我查看源中的所有链接:
<link href="/(A(a))/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/(A(a))/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script> <script src="/(A(a))/Scripts/modernizr-1.7.min.js" type="text/javascript"></script> <li><a href="/(A(a))/">Home</a></li> <li><a href="/(A(a))/Home/About">About</a></li>
看看第一部分如何维护?这就像路由引擎认为它是域的一部分?
我感觉这是一个正则表达式,因为如果我将URL更改为:
http://localhost:51419/(a(a))/Home/About
(例如将大写A改为小写)
它是404的.
任何人都可以看出这一点吗?这是错误还是设计?
解决方法
这似乎与ASP.NET管道中的无聊会话有关.在处理请求时,它会剥离CookielessHelper.cs(System.Web.Security)内的URL模式:
// This function is called for all requests -- it must be performant. // In the common case (i.e. value not present in the URI,it must not // look at the headers collection internal void RemoveCookielessValuesFromPath() { // See if the path contains "/(XXXXX)/" string path = _Context.Request.ClientFilePath.VirtualPathString; // Optimize for the common case where there is no cookie if (path.IndexOf('(') == -1) { return; } int endPos = path.LastIndexOf(")/",StringComparison.Ordinal); int startPos = (endPos > 2 ? path.LastIndexOf("/(",endPos - 1,endPos,StringComparison.Ordinal) : -1); if (startPos < 0) // pattern not found: common case,exit immediately return; if (_Headers == null) // Header should always be processed first GetCookielessValuesFromHeader(); // if the path contains a cookie,remove it if (IsValidHeader(path,startPos + 2,endPos)) { // only set _Headers if not already set if (_Headers == null) { _Headers = path.Substring(startPos + 2,endPos - startPos - 2); } // Rewrite the path path = path.Substring(0,startPos) + path.Substring(endPos+1); // remove cookie from ClientFilePath _Context.Request.ClientFilePath = VirtualPath.CreateAbsolute(path); // get and append query string to path if it exists string rawUrl = _Context.Request.RawUrl; int qsIndex = rawUrl.IndexOf('?'); if (qsIndex > -1) { path = path + rawUrl.Substring(qsIndex); } // remove cookie from RawUrl _Context.Request.RawUrl = path; if (!String.IsNullOrEmpty(_Headers)) { _Context.Request.ValidateCookielessHeaderIfrequiredByConfig(_Headers); // ensure that the path doesn't contain invalid chars _Context.Response.SetAppPathModifier("(" + _Headers + ")"); // For Cassini and scenarios where aspnet_filter.dll is not used,// HttpRequest.FilePath also needs to have the cookie removed. string filePath = _Context.Request.FilePath; string newFilePath = _Context.Response.RemoveAppPathModifier(filePath); if (!Object.ReferenceEquals(filePath,newFilePath)) { _Context.RewritePath(VirtualPath.CreateAbsolute(newFilePath),_Context.Request.PathInfoObject,null /*newQueryString*/,false /*setClientFilePath*/); } } } }
您的模式与此相符:
/////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Make sure sub-string if of the pattern: A(XXXX)N(XXXXX)P(XXXXX) and so on. static private bool IsValidHeader(string path,int startPos,int endPos) { if (endPos - startPos < 3) // Minimum len is "X()" return false; while (startPos <= endPos - 3) { // Each iteration deals with one "A(XXXX)" pattern if (path[startPos] < 'A' || path[startPos] > 'Z') // Make sure pattern starts with a capital letter return false; if (path[startPos + 1] != '(') // Make sure next char is '(' return false; startPos += 2; bool found = false; for (; startPos < endPos; startPos++) { // Find the ending ')' if (path[startPos] == ')') { // found it! startPos++; // Set position for the next pattern found = true; break; // Break out of this for-loop. } if (path[startPos] == '/') { // Can't contain path separaters return false; } } if (!found) { return false; // Ending ')' not found! } } if (startPos < endPos) // All chars consumed? return false; return true; }