一、 通過自定義的HttpModule和HttpHandler,重寫url,自定義路由規則,實現 Web API功能。 簡單說
就是 請求路徑 例如 service/method, 那麼就指向當前應用app下某個services的某個方法method。
首先,實現IHttpModule,對於請求路徑 符合自定義規則的,交給自定義的HttpHandler
public class UrlRoutingModule : IHttpModule { //其他成員 public RouteCollection RouteCollection { get; set; } public void Init(HttpApplication context) { context.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache); } private void OnApplicationPostResolveRequestCache(object sender, EventArgs e) { HttpContext context = ((HttpApplication)sender).Context; string path = context.Request.AppRelativeCurrentExecutionFilePath; //為了解決iis6 中framework4.0 與 framework2.0共存的問題 if (path.EndsWith("/eurl.axd")) { path = path.Substring(0, path.Length - 9); } string[] pathArray = path.Split('/'); string fileName = pathArray[pathArray.Length - 1]; if (fileName.IndexOf(".") > 0) { context.RemapHandler(HttpContext.Current.Handler); } else { PageRouteHandler handler = new PageRouteHandler(); context.RemapHandler(handler); } } #region IHttpModule 成員 public void Dispose() { } #endregion }
自定義的httphandler 實現 IHttpHandler介面
public class PageRouteHandler : IHttpHandler { public bool IsReusable { get { return true; } } public void ProcessRequest(HttpContext context) { string result = string.Empty; string path = context.Request.AppRelativeCurrentExecutionFilePath; string[] pathArray = path.Split('/'); Func<HttpContext, string> handler = null; string serviceName = string.Empty; string methodName = string.Empty; if (pathArray.Length >= 3) { serviceName = pathArray[1]; methodName = pathArray[2]; } if (!string.IsNullOrEmpty(serviceName) && !string.IsNullOrEmpty(methodName)) { handler = GetWebMethod(serviceName + "." + methodName); if (handler != null) { result = handler(context); } } if (handler == null) { result = "{\"result\":\"not exist handler service\"}"; } if (context.Request.AcceptTypes != null && context.Request.AcceptTypes.Contains("application/json")) { context.Response.ContentType = "application/json"; } string callback = context.Request["jsoncallback"]; if (!string.IsNullOrEmpty(callback)) { result = callback + "(" + result + ")"; context.Response.AddHeader("Access-Control-Allow-Origin", "*"); } context.Response.Write(result); } }
自定義的 pageroutehandler的作用,就是處理合法請求時,通過委託方式呼叫請求的方法,並把結果返回。 獲取委託時使用了快取,getwebmethod 程式碼如下
public static Dictionary<string, Func<HttpContext, string>> WebMethods { get { Dictionary<string, Func<HttpContext, string>> _webMethods = HttpRuntime.Cache["WebMethods"] as Dictionary<string, Func<HttpContext, string>>; if (_webMethods == null) { _webMethods = new Dictionary<string, Func<HttpContext, string>>(); } return _webMethods; } } public static Func<HttpContext, string> GetWebMethod(string classMethodName) { if (string.IsNullOrEmpty(classMethodName)) { return null; } string[] arrClassMethod = classMethodName.Split('.'); if (arrClassMethod.Length != 2) { return null; } Func<HttpContext, string> handler = null; if (!WebMethods.ContainsKey(classMethodName)) { string binPath = AppDomain.CurrentDomain.RelativeSearchPath; foreach (string dll in Directory.GetFiles(binPath)) { FileInfo fi = new FileInfo(dll); if (fi.Extension.Equals(".dll", StringComparison.CurrentCultureIgnoreCase) && !fi.Name.StartsWith("system.") && !fi.Name.StartsWith("microsoft.")) { Assembly assembly = Assembly.LoadFile(dll); string typeName = assembly.GetName().Name + "." + arrClassMethod[0]; Type type = assembly.GetType(typeName, false, true); if (type != null) { handler = (Func<HttpContext, string>)Delegate.CreateDelegate(typeof(Func<HttpContext, string>), type.GetMethod(arrClassMethod[1], BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Static, null, new Type[1] { typeof(HttpContext) }, null)); WebMethods.Add(classMethodName, handler); break; } } } } else { handler = WebMethods[classMethodName]; } return handler; }
二 使用規則。首先在web config 的<httpModules>加上<add name="RouteModule" type="LinWebAPI.UrlRoutingModule, LinWebAPI"/>(這裡type就是 你自己定義的httpmodule的類的全名了)。
只要你把你的後臺類暴露出來給前臺呼叫,定義方法符合 public static string method(HttpContext context) 這個規則即可。
假設 你有個模組的類 TestServices 下有個 方法 public static string TestMethod(HttpContext context), 那麼前端頁面 通過 ajax請求路徑為 Testservices/testmethod,
至於請求的引數,你可以通過?a=x&b=y這種方式加到請求路徑後面,也可以放通過post方式提交 例如 jquery的 $.ajax(url,{a:x,b:y}....。
而對於 方法 TestMethod(HttpContext context),要獲取請求的引數,直接從 string a = context.Request["a"] 即可。
***
對於iis6,要支援這種不帶副檔名的請求路徑,需要
1. 開啟 IIS Microsoft 管理控制檯 (MMC),右鍵單擊本地計算機名稱,然後單擊“屬性”。
2. 單擊“MIME 型別”。
3. 單擊“新建”。
4. 在“副檔名”框中,鍵入星號 (*)。
5. 在“MIME 型別”框中,鍵入 application/octet-stream。
對於iis7,要支援這種不帶副檔名的請求路徑,需要
1 網站託管模式為 經典模式
2 處理程式對映--》新增指令碼對映--》配置(請求路徑:* ;可執行檔案:C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll)