我在用.net實現Webservice的時候發現需要一個沒有任何用處的.asmx文件,但是卻沒法刪除,這兩天我實現一個通過接口時想實現dll直接部署,不需要弄個.asmx文件.翻閱了很多,最后在Spring.net里面得到了啟示.
我要實現的方式是直接在httpHandlers中配置
<httpHandlers>
<add verb="*" path="XXXservice.asmx" type="CampusWebService.DataService,CampusWebService"/>
</httpHandlers>
然后通過就可以直接部署,特別適合進行二次開發,嵌入式開始什么的.
具體的實現如下:
先需需要通過繼承反射實現一個c#的程序集封裝的調用(很討厭C#的程序集封裝,討嫌的要死)
/// <summary> /// WebService處理類. /// </summary> [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] internal class WebServiceHandlerFactory<T> : System.Web.Services.Protocols.WebServiceHandlerFactory, IHttpHandlerFactory where T : WebService { #region 成員變量,構造函數. /// <summary> /// 核心方法反射調用. /// </summary> private static readonly MethodInfo CoreGetHandler = typeof(System.Web.Services.Protocols.WebServiceHandlerFactory).GetMethod("CoreGetHandler", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(Type), typeof(HttpContext), typeof(HttpRequest), typeof(HttpResponse) }, null); private Type serviceType; /// <summary> /// 構造函數. /// </summary> /// <param name="serviceType"></param> public WebServiceHandlerFactory(T serviceType) { this.serviceType = serviceType.GetType(); } #endregion #region IHttpHandlerFactory 成員 /// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="requestType"></param> /// <param name="url"></param> /// <param name="pathTranslated"></param> /// <returns></returns> IHttpHandler IHttpHandlerFactory.GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { if (this.serviceType == null) { throw new ArgumentNullException("serviceType","服務類型為NULL!"); } new AspNetHostingPermission(AspNetHostingPermissionLevel.Minimal).Demand(); return (IHttpHandler)CoreGetHandler.Invoke(this, new object[] { this.serviceType, context, context.Request, context.Response }); } /// <summary> /// /// </summary> /// <param name="handler"></param> void IHttpHandlerFactory.ReleaseHandler(IHttpHandler handler) { base.ReleaseHandler(handler); } #endregion }
這個類可以成為一個工具類,這個類的是系統級的Web.config中所有.asmx文件的解析類,重載的目的就是把原來基於路徑的訪問變成對象訪問,
.net框架的原版實現是這樣的
1 public IHttpHandler GetHandler(HttpContext context, string verb, string url, string filePath) 2 { 3 TraceMethod caller = Tracing.On ? new TraceMethod(this, "GetHandler", new object[0]) : null; 4 if (Tracing.On) 5 { 6 Tracing.Enter("IHttpHandlerFactory.GetHandler", caller, Tracing.Details(context.Request)); 7 } 8 new AspNetHostingPermission(AspNetHostingPermissionLevel.Minimal).Demand(); 9 Type compiledType = WebServiceParser.GetCompiledType(url, context); 10 IHttpHandler handler = this.CoreGetHandler(compiledType, context, context.Request, context.Response); 11 if (Tracing.On) 12 { 13 Tracing.Exit("IHttpHandlerFactory.GetHandler", caller); 14 } 15 return handler; 16 }
這里的Url就是指向我們常用的只有一句話的.asmx文件.
我們發現CoreGetHandler是調用的目標WebService的type,但是這個函數是程序集可見,不能被我們調用,只能用萬能的反射來弄,
最后我們的WebService的實現為.
/// <summary> /// 數據服務接口. /// </summary> [WebService(Name="數字校園數據服務接口", Namespace="http://yaesoft.com", Description = "為第三方應用提供的基礎數據服務接口")] [WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1)] public class DataService : WebService,IHttpHandler { #region 成員變量,構造函數./// <summary> /// 構造函數. /// </summary> public DataService() { } #endregion #region Web服務函數. /// <summary> /// 獲取組織部門數據. /// </summary> /// <param name="type">部門類型.</param> /// <returns>部門信息集合.</returns> [WebMethod(Description = "獲取組織部門數據.")] public List<Dept> Departments(EnumDeptType type) { ///TODO:
return null; } /// <summary> /// 獲取教師用戶數據. /// </summary> /// <param name="deptCode">部門代碼</param> /// <returns>教師用戶集合.</returns> [WebMethod(Description = "獲取教師用戶數據.")] public List<User> Teachers(string deptCode) {
///TODO: return null; }#endregion #region IHttpHandler 成員 /// <summary> /// /// </summary> public bool IsReusable { get { return false; } } /// <summary> /// /// </summary> /// <param name="context"></param> public void ProcessRequest(HttpContext context) { IHttpHandlerFactory factory = (IHttpHandlerFactory)new WebServiceHandlerFactory<DataService>(this); IHttpHandler handler = factory.GetHandler(context, null, null, null); handler.ProcessRequest(context); } #endregion }
由於我們是WebService類,因此得繼承WebService,
我們需要在HttpHandlers中使用,所以至少要繼承IHttpHandler接口,
而解析是在HTTPHandler接口中進行的所以我們得在
public void ProcessRequest(HttpContext context) { IHttpHandlerFactory factory = (IHttpHandlerFactory)new WebServiceHandlerFactory<DataService>(this); IHttpHandler handler = factory.GetHandler(context, null, null, null); handler.ProcessRequest(context); }
這個方法的內容基本是不需要變化的,
我們可以將這個類進行抽象,作為我們所有的Webservice的基礎類來使用,
然后只要在Web.config中進行HttpHandlers中進行配置即可發布WebService服務!
