基于WinService,开发Restful 风格的Wcf 服务端
2021-07-25 20:55
阅读:530
开发目的:降低和IIS的耦合,使用Winservice做宿主,迁移方便快捷。
步骤:
1.添加WcfService,分别实现 Get 和 Post 方法
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Runtime.Serialization; 5 using System.ServiceModel; 6 using System.ServiceModel.Web; 7 using System.Text; 8 9 namespace WcfSelfHost 10 { 11 // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together. 12 [ServiceContract] 13 public interface IService1 14 { 15 [OperationContract] 16 string Get(); 17 18 [OperationContract] 19 20 string Post(); 21 } 22 }
2.分别为每个方法添加路由信息,指定请求方式,确定返回信息格式
[ServiceContract] public interface IService1 { [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/method/")] string Get(); [OperationContract] [WebInvoke(Method = "Post", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/method/")] string Post(); }
3.接口实现:
public class Service1 : IService1 { #region Implementation of IService1 public string Get() { return "this is get method!"; } public string Post() { return "this is post method"; } #endregion }
4.如何解决跨域问题(坑)?
如果使用ajax来访问,会有跨域问题,api正常返回数据,但是ajax无法接收。
经测试,发现最好用的方法,是通过对请求添加拦截器的方式来处理,可以100%的解决跨域问题:
MessageInspector.cs
public class MessageInspector:IDispatchMessageInspector { private ServiceEndpoint _serviceEndpoint; public MessageInspector(ServiceEndpoint serviceEndpoint) { _serviceEndpoint = serviceEndpoint; } ////// Called when an inbound message been received /// /// The request message. /// The incoming channel. /// The current service instance. /// /// The object used to correlate stateMsg. /// This object is passed back in the method. /// public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { StateMessage stateMsg = null; HttpRequestMessageProperty requestProperty = null; if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name)) { requestProperty = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; } if (requestProperty != null) { var origin = requestProperty.Headers["Origin"]; if (!string.IsNullOrEmpty(origin)) { stateMsg = new StateMessage(); // if a cors options request (preflight) is detected, // we create our own reply message and don‘t invoke any // operation at all. if (requestProperty.Method == "OPTIONS") { stateMsg.Message = Message.CreateMessage(request.Version, null); } request.Properties.Add("CrossOriginResourceSharingState", stateMsg); } } return stateMsg; } /// /// Called after the operation has returned but before the reply message /// is sent. /// /// The reply message. This value is null if the /// operation is one way. /// The correlation object returned from /// the method. public void BeforeSendReply(ref Message reply, object correlationState) { var stateMsg = correlationState as StateMessage; if (stateMsg != null) { if (stateMsg.Message != null) { reply = stateMsg.Message; } HttpResponseMessageProperty responseProperty = null; if (reply.Properties.ContainsKey(HttpResponseMessageProperty.Name)) { responseProperty = reply.Properties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty; } if (responseProperty == null) { responseProperty = new HttpResponseMessageProperty(); reply.Properties.Add(HttpResponseMessageProperty.Name, responseProperty); } // Access-Control-Allow-Origin should be added for all cors responses responseProperty.Headers.Set("Access-Control-Allow-Origin", "*"); if (stateMsg.Message != null) { // the following headers should only be added for OPTIONS requests responseProperty.Headers.Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET,DELETE,PUT"); responseProperty.Headers.Set("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, x-requested-with"); } } } } class StateMessage { public Message Message; }
BehaviorAttribute.cs
public class BehaviorAttribute : Attribute, IEndpointBehavior, IOperationBehavior { public void Validate(ServiceEndpoint endpoint) { } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } ////// This service modify or extend the service across an endpoint. /// /// The endpoint that exposes the contract. /// The endpoint dispatcher to be /// modified or extended. public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { // add inspector which detects cross origin requests endpointDispatcher.DispatchRuntime.MessageInspectors.Add( new MessageInspector(endpoint)); } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } public void Validate(OperationDescription operationDescription) { } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } }
对请求添加拦截:
private static ServiceHost host; private static ServiceHost crosspolicy; public static void Start() { host = new ServiceHost(typeof(Service1)); host.Description.Endpoints[0].Behaviors.Add(new BehaviorAttribute()); host.Opening += (o, e) => {}; host.Opened += (o, e) => { }; host.Closing += (o, e) => { Console.WriteLine(" data server Closing..."); }; host.Closed += (o, e) => { Console.WriteLine("data setver Closed."); }; host.Open(); Console.Read(); }
5.APP.config:
xml version="1.0" encoding="utf-8" ?> configuration> system.web> compilation debug="true"/> system.web> system.serviceModel> services> service name="WcfSelfHost.Service1"> endpoint address="" binding="webHttpBinding" contract="WcfSelfHost.IService1" behaviorConfiguration="web"> endpoint> endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> host> baseAddresses> add baseAddress="http://127.0.0.1:12121/api/" /> baseAddresses> host> service> services> behaviors> serviceBehaviors> behavior > serviceMetadata httpGetEnabled="True"/> serviceDebug includeExceptionDetailInFaults="False" /> behavior> serviceBehaviors> endpointBehaviors> behavior name="web"> webHttp/> behavior> endpointBehaviors> behaviors> system.serviceModel> configuration>
后续步骤:改造成winService,笔者使用批处理脚本来进行服务安装不再赘述。
文章来自:搜素材网的编程语言模块,转载请注明文章出处。
文章标题:基于WinService,开发Restful 风格的Wcf 服务端
文章链接:http://soscw.com/essay/106964.html
文章标题:基于WinService,开发Restful 风格的Wcf 服务端
文章链接:http://soscw.com/essay/106964.html
评论
亲,登录后才可以留言!