Cross resource lookup for C # WCF. Web service supported by the Windows service.

I have a WCF Restful service that I host as a Windows service. I want to add cross-domain support to my service. However, I can do this easily when I use the global.asax file. But I want to host my service as a Windows service.

I created a project that serves my service as a Windows service. Now the problem I am facing is that now I cannot add cross-domain support. I tried all possible solutions that I could find through the app.config file, but no one works. I tried the solutions on these links:

dotnet tricks

enable-cors.org

I tried to customize the header in the code using the following function, calling it in each service contract method.

private static void SetResponseHeader() { WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*"); WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "no-cache, no-store"); WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Request-Methods", "GET, POST, PUT, DELETE, OPTIONS"); WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept"); } 

Interface:

 namespace ReaderService { [ServiceContract] public interface INFCReader { [OperationContract] [WebInvoke(UriTemplate = "GetLogin", Method = "POST")] GetLoginResults GetLogin(DisplayRequest dispRequest); } 

Here DisplayRequest is a class.

Please help the guys. Let me know if anyone wants to look at any other code.

Thank you very much.

EDIT :::

Thank you very much for your reply. I created a MessageInspector class that implements IDispactchMessageInspector. I have code in the MessageInspector class.

 public class MessageInspector : IDispatchMessageInspector { public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); if (HttpContext.Current.Request.HttpMethod == "OPTIONS") { HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache"); HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST"); HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000"); HttpContext.Current.Response.End(); } return null; } } 

The error I am getting now is "The object reference is not installed in the object instance." The error in this line of the above code is

 HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); 

All I want to do is add CORS support for my web service. Please let me know if I am doing this correctly. OR is there any other way to do the same.

+6
source share
2 answers

Finally found a solution to my queries.

It is all here. Cross Origin Resource Support

Good step by step explanation. I think I would never have thought of this myself.

CODE:

Create 2 classes as follows:

  • MessageInspector implementation of IDispatchMessageInspector .
  • BehaviorAttribute implementation of Attribute , IEndpointBehavior and IOperationBehavior .

With the following details:

 //MessageInspector Class using System; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.ServiceModel.Description; namespace myCorsService { public class MessageInspector : IDispatchMessageInspector { private ServiceEndpoint _serviceEndpoint; public MessageInspector(ServiceEndpoint serviceEndpoint) { _serviceEndpoint = serviceEndpoint; } /// <summary> /// Called when an inbound message been received /// </summary> /// <param name="request">The request message.</param> /// <param name="channel">The incoming channel.</param> /// <param name="instanceContext">The current service instance.</param> /// <returns> /// The object used to correlate stateMsg. /// This object is passed back in the method. /// </returns> 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; } /// <summary> /// Called after the operation has returned but before the reply message /// is sent. /// </summary> /// <param name="reply">The reply message. This value is null if the /// operation is one way.</param> /// <param name="correlationState">The correlation object returned from /// the method.</param> 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"); responseProperty.Headers.Set("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, x-requested-with"); } } } } class StateMessage { public Message Message; } } //BehaviorAttribute Class using System; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; namespace OpenBetRetail.NFCReaderService { public class BehaviorAttribute : Attribute, IEndpointBehavior, IOperationBehavior { public void Validate(ServiceEndpoint endpoint) { } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } /// <summary> /// This service modify or extend the service across an endpoint. /// </summary> /// <param name="endpoint">The endpoint that exposes the contract.</param> /// <param name="endpointDispatcher">The endpoint dispatcher to be /// modified or extended.</param> 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) { } } } 

After that, all you have to do is add a message inspector to serve the endpoint behavior.

 ServiceHost host = new ServiceHost(typeof(myService), _baseAddress); foreach (ServiceEndpoint EP in host.Description.Endpoints) EP.Behaviors.Add(new BehaviorAttribute()); 

Thanks guys for your help.

+11
source

I find the closest to Application_BeginRequest in the WCF world Message Inspectors :

A message inspector is an extensibility object that can be used in the working environment of a customer service model and programmatically or through scheduling at run time, and which can check and modify messages after they are received or before they are sent.

To use special message inspectors you need to:

  • Create a class that implements the IDispatchMessageInspector interface (your custom inspector)
  • Add a custom inspector to the DispatchRuntime.MessageInspectors service.

Here you can find additional information and sample code on how to do this.

+1
source

All Articles