利用WCF搭建RESTful--纯代码启动
最近学习了这几年忽略了的当前几乎所有的开发技术,有深有浅,而服务层最有兴趣的是RESTfull,看的是java的书。因为不熟悉JSP,于是找了本书细细研读了一次。
dotnet的实现也相对简单,网上也很容易找到WCF实现RESTful的例子。于是我想将其作为开源HIS的服务端的基础服务。因为HIS业务的繁多,需要POST很多的表,如果每个表都需要调整服务的接口定义,这工作量就大了,所以我想,接口是否能动态生成方法名称并动态加载WCF?
第一步,就是不能使用配置文件,纯代码启动WCF。
接口和服务都是动态生成的,没有一个编译好的现成的类可以使用,所以利用配置文件启动WCF是不适用的,于是网上找,还好微软件写得非常详细,以下是页面地址
https://msdn.microsoft.com/zh-cn/magazine/dd315413.aspx
第二步,就是动态生成接口类与服务实现类。
因为逻辑简单,所以这部分也很简单。过程就是利用模板文件生成不同表的接口与服务实现类
[ServiceContract] public interface I{InfoClass}Service { [OperationContract] [WebInvoke( Method = ""GET"", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = ""{InfoClass}/{__infoId}"" )] {InfoClass} Get{InfoClass}(string __infoId); ....
利用上面的模板文本,替换{InfoClass},程序就得到了希望的类的源代码文本,再将该文本在运行时编译成类
string classCode = codeTemp.Replace("{InfoClass}", infoClass); //设置编译参数。 CompilerParameters cp = new CompilerParameters(); cp.GenerateExecutable = false; cp.GenerateInMemory = true; cp.ReferencedAssemblies.Add("System.dll"); cp.ReferencedAssemblies.Add("System.Data.dll"); cp.ReferencedAssemblies.Add("System.ServiceModel.dll"); cp.ReferencedAssemblies.Add("System.ServiceModel.Web.dll"); cp.ReferencedAssemblies.Add("DyncWcf.App.exe");//infoClass所在的程序集 //编译代码。 CompilerResults result = provider.CompileAssemblyFromSource(cp, classCode); if (result.Errors.Count > 0) { for (int i = 0; i < result.Errors.Count; i++) Console.WriteLine(result.Errors[i]); Console.WriteLine("error"); return null; } //获取编译后的程序集。 Assembly assembly = result.CompiledAssembly;
从assembly中取出接口与实现,就可以动态加载wcf了
Assembly asm = AssemblyHelper.BuildAssembly("CmdInfo"); Type[] types = asm.GetTypes(); Type tpInterface = null; Type tpService = null; if(types[0].IsInterface){ tpInterface = types[0]; tpService = types[1]; }else{ tpInterface = types[1]; tpService = types[0]; } try{ string baseUri = "http://localhost:8000/DynWcf"; ServiceHost sh = new ServiceHost(tpService, new Uri(baseUri)); //wsdl说明页 ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; sh.Description.Behaviors.Add(smb); // ServiceEndpoint se = sh.AddServiceEndpoint( tpInterface, new WebHttpBinding(), baseUri); se.Behaviors.Add(new WebHttpBehavior());
//利用头增加用户身份认证,这里简单的是Authorization="fangxing/123"
sh.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager();
sh.Open(); Console.WriteLine("The service is ready."); } catch (Exception ce){ Console.WriteLine("An exception occurred: {0}", ce.Message); }
从这找到简单的权限认证的处理办法
https://www.cnblogs.com/wolf-sun/p/4572591.html
抄其中了一个类的代码如下:
public class MyServiceAuthorizationManager : ServiceAuthorizationManager { protected override bool CheckAccessCore(OperationContext operationContext) { var ctx = WebOperationContext.Current; var auth = ctx.IncomingRequest.Headers[HttpRequestHeader.Authorization]; if (string.IsNullOrEmpty(auth) || auth != "fangxing/123") {
Console.WriteLine("无权访问,Url={0}", operationContext.RequestContext.RequestMessage.Properties["Via"]); ctx.OutgoingResponse.StatusCode = HttpStatusCode.MethodNotAllowed; return false; } return true; } }
这是我使用postman测试的界面
认证部分,还花了两天的时候翻了两本WCF的书。唉...人笨没办法。我的代码放在CSDN,目的是存点积分:)。当然其实几乎全部代码已帖在上面了。
源代码下载地址
https://download.csdn.net/download/kevin2y/10779906