前言:
最近一些使用URLRewriting的朋友們有時候會遇到ASP.NET AJAX和AJAX Control Toolkit控制項不能正常工作的現象,對於沒有相關經驗的開發人員來說相當棘手。本篇通過案例分析和相對的解決方案來討論在使用ASP.NET AJAX 與 URLRewriting 時應當注意到的一些相容性問題。
問題重現:
一般簡單的URLRewriting應用都是對來自用戶端對資源的Request進行路徑重新導向,比較典型的寫法如同下列代碼1 和代碼2:
代碼1:
// If the requested file exists
if (File.Exists(Request.PhysicalPath))
{
// Do nothing here, just serve the file
}
// If the file does not exist then
else if (!File.Exists(Request.PhysicalPath))
{
// Get the URL requested by the user
string sRequestedURL = Request.Path.Replace(".aspx", "").Replace("/gratis24/","");
// You can retrieve the ID of the content from database that is
// relevant to this requested URL (as per your business logic)
string sId;
sId = GetContentIDByPath(sRequestedURL);
// The ShowContents.aspx page should show contents relevant to
// the ID that is passed here
string sTargetURL = "~/Kategori.aspx?category=" + sId;
// Owing to RewritePath, the user will see requested URL in the
// address bar
// The second argument should be false, to keep your references
// to images, css files
Context.RewritePath(sTargetURL, false);
代碼2:
//in global.asax
void Application_BeginRequest(object sender, EventArgs e)
{
System.Web.HttpContext httpContext = HttpContext.Current;
String currentURL = httpContext.Request.Path.ToLower();
//Creates the physical path on the server
string physicalPath = httpContext.Server.MapPath(currentURL.Substring(currentURL.LastIndexOf("/") + 1));
//checks to see if the file does not exsists.
if (!System.IO.File.Exists(physicalPath) && !currentURL.EndsWith("webresource.axd"))
{
string reWritePage = "ViewProfile.aspx";
httpContext.RewritePath(reWritePage);
}
}
然而,當我們使用上面的代碼進行URLRewriting,並且在頁面中使用ASP.NET AJAX 或 AJAX Control Toolkit的話,將會得到:'sys' is undefined 錯誤警告,而AJAX控制項不能正常工作,totally not work.
分析:
很顯然,'sys' is undefined 告訴我們 ASP.NET AJAX架構沒有正常載入,根據分析可知,sys的定義是在指令碼資源檔ScriptResource.axd中的,然而在上面的URLRewriting代碼中,我們並沒有對ScriptResource.axd進行特殊處理,導致該資源被重新導向,沒有正常載入。所以導致了ASP.NET AJAX不工作的問題。
解決方案:
知道了原因,我們就要修改URLRewriting的代碼,為ScriptResource.axd增加一個例外:
代碼1的解決方案:
在CheckPath時加入特例
private static void CheckPath(string path)
{
if (!string.Equals(path, VirtualPathUtility.ToAbsolute("~/ScriptResource.axd"), StringComparison.OrdinalIgnoreCase))
//it should be at the root.
{
Throw404();
}
}
代碼2的解決方案:
與1同理,在IO判斷時加上特例,修改如下:
void Application_BeginRequest(object sender, EventArgs e)
{
System.Web.HttpContext httpContext = HttpContext.Current;
String currentURL = httpContext.Request.Path.ToLower();
//Creates the physical path on the server
string physicalPath = httpContext.Server.MapPath(currentURL.Substring(currentURL.LastIndexOf("/") + 1));
//checks to see if the file does not exsists.
if (!System.IO.File.Exists(physicalPath) && !currentURL.EndsWith("webresource.axd") && !currentURL.EndsWith("ScriptResource.axd"))
{
string reWritePage = "ViewProfile.aspx";
httpContext.RewritePath(reWritePage);
}
}
至此,可解決該問題。
相關case:
http://forums.asp.net/t/1178119.aspx
http://forums.asp.net/p/1356089/2795441.aspx#2795441
Thanks.