How to pass dependencies to a WCF restful service - c#

I am new to Rest services. I did fair bit of research on this topic but still not clearly understood. Hope someone clear this to me. Thanks in advance.
My client is going to execute a method on my service class through an url. All I understood is client going to call
localhost/service/get/customers
In my rest service I have dependencies like a IRepository so that I can go to database and fetch the records. If I go with constructor injection when would client call this constructor?
It looks like I need to use a service locator to fetch IRepository inside the method which I need it.
Doesn't this violate OOP principle? Is testing easy without DI?
Can anyone please clarify this.
For any service how do we expect client to know what is IRepository is what methods it does have?
Is isn't it for internal implementation purpose Do we need t expose to the client? Why should he bother about it? Can't I provide just Uri Which method to call (localhost/service/Products) and job done.
I will appreciate if you provide any live example.
Thanks a lot.

No, it will not violate OOP priciple, if you will resolve for dependency inside a method. But there is no need for that, you can use constructor Dependency Injection within WCF using Instance Provider and ServiceHostFactory, there is also good example in this question.
If you are self-hosting the service, it will be even more simpler because it requires implementing only IInstanceProvider and ServiceHost. Assuming that you have Service service with constructor taking an IDependency parameter:
public class CustomInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IDependency dependency;
public CustomInstanceProvider(IDependency dependency)
{
this.dependency = dependency;
}
public object GetInstance(InstanceContext instanceContext)
{
// Here you are injecting dependency by constructor
return new Service(dependency);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
}
public class CustomServiceHost : ServiceHost
{
public CustomServiceHost(IDependency dependency, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
foreach (var cd in this.ImplementedContracts.Values)
{
cd.Behaviors.Add(new CustomInstanceProvider(dependency));
}
}
}
Then when creating service, use CustomServiceHost:
var serviceHost = new CustomServiceHost(dependency, typeof(Service), uris);

Related

Entity Framework data service request headers for mvc

We have an Entity framework web service, that needs authentication to access. This authentication needs to happen every time a request is sent.
The system im editing has it working perfectly for a WPF application by overriding the OnSendingRequest event of the entity container from the mainWindow.xaml.cs file. then adding the authorization to the header. And i found a resource that tells me to do something similar, but i dont know how this works in a ASP.NET MVC project, since the resource seems to only give an example of how to do it for a single request, in WPF. How to: Set Headers in the Client Request (WCF Data Services
I need to make this same authentication header for the connection of the mvc project, for every request.
You can try message interceptor to insert authentication headers.
public class ClientMessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
MessageHeader header1 = MessageHeader.CreateHeader("Testreply", "http://Test", "Test");
request.Headers.Add(header1);
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageHeader header = MessageHeader.CreateHeader("UserAgent", "http://User", "User1");
reply.Headers.Add(header);
return null;
}
}
[AttributeUsage(AttributeTargets.Interface)]
public class CustomBehavior : Attribute, IContractBehavior
{
public Type TargetContract => typeof(ServiceReference1.ICalculator);
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
return;
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
In the BeforeSendRequest method, you can insert a header, to apply this message interceptor, you need to add [CustomBehavior] in the client's service reference.
Like this:
Incase someone else finds this useful, i solved the problem by accident.
I made a static class, and a static method, that can be called from any page in the project. with this code:
var serviceUri = new Uri(WebConfigurationManager.AppSettings["DataServiceUri"]);
myService result = new myService(serviceUri);
result.SendingRequest += new EventHandler<SendingRequestEventArgs>((s, e) =>
{
string authenticationString = applicationName + " " + applicationId;
e.RequestHeaders.Add("Authorization", authenticationString);
});
return result;
This both creates and returns the instance of the service, to use in the calling method, and also automatically creates the Authorization and executes it.
This hasto be done on each of the controllers that communicates with the service.
Enjoy.

How to programmatically add a SOAP header based on a generated proxy class

I'm trying to consume a SOAP webservices provided by a third party. I don't have any control of that webservice. I'm consuming the webservice using a Low Code platform called OutSystems. OutSystems unfortunately doesn't recognize a SOAP header that has to be send with the request so I'll have to add it myself by extending the platform functionality with some custom c# code.
The SOAP Extensibility API gives me access to the WCF ClientCredentials, ServiceEndpoint, IClientChannel and CommunicationState objects. It also provides a method to register an endpoint behavior, using a IEndpointBehavior object.
Using svcutil I've been able to generate proxy classes for the data of the message, including the SOAP header that I should add.
Ideally I'm looking for a way to instantiate an object of the proxy of the header and then somehow pass that to the service. But here is where i'm stuck. I/m not able to find a way to use that object as a SOAP header.
The documentation of OutSytems also provides an example about adding a soap header using .net code. They use MessageHeader.CreateHeader to create a new element with a given element name, namespace and value. So this is also a place where i'm stuck. It would be great if I could use the proxy class here, but this will only allow me to set it as the value. This way I end up with a duplicate 'root' element.
Using the code below:
class AddSoapHeaderMessageInspector : IClientMessageInspector {
object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel) {
// before sending a request, add a new SOAP header, specifying its name, namespace and value
request.Headers.Add(MessageHeader.CreateHeader("MySoapHeader", "http://my-namespace.com", mySOAPHeader));
return request;
}
void IClientMessageInspector.AfterReceiveReply(ref Message reply, object correlationState) {
// here you would handle the web service response
}
}
Would result in XML like
<MySoapHeader><MySoapHeader><element1><element2></MySoapHeader></MySoapHeader>
While it should look like
<MySoapHeader><element1><element2></MySoapHeader>
The solution we have now is one where we've implemented a class that extends MessageHeader. In the OnWriteHeaderContents of that class we manually write the content of the header in code. Unfortunately this is cause some namespace issues at the server side.
I'm posting this on stackoverflow instead of the OutSystems forum because I consider this more of a WCF/C# question than an OutSystems question.
You can add soap header in the implementation class by implementing IClientMessageInspector interface.
public class ClientMessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageHeader header = MessageHeader.CreateHeader("MySoapHeader", "http://my-namespace.com", "asdas");
request.Headers.Add(header);
return null;
}
}
Add clientmessagelogger to clientruntime:
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false)]
public class CustContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
{
public Type TargetContract => throw new NotImplementedException();
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
Add Attribute to Interface of proxy class:
[CustContractBehavior]
public interface IService {
}
This is the soap message received by the server:
To learn more about IClientMessageInspector, please refer to the following link:
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.dispatcher.iclientmessageinspector?view=dotnet-plat-ext-3.1

Setup Ninject for WCF [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
Does anyone have a clear instruction on how to setup Ninject in WCF? been googling around but I cant see any updated guidelines on how to use Ninject in WCF.
Using NInject with WCF is the same as using any other DI container. To do this you need to use 3 WCF extensibility points: InstanceProvider, ServiceHost and ServiceHostFactory.
The custom InstanceProvider will be used to create service instances by using a constructor with parameters. The code can be seen below.
public class NInjectInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IKernel kernel;
public NInjectInstanceProvider(IKernel kernel)
{
if (kernel == null) throw new ArgumentNullException("kernel");
this.kernel = kernel;
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
//delegate to GetInstance(InstanceContext)
return GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
//resolve the service instance
return kernel.Get(instanceContext.Host.Description.ServiceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
kernel.Release(instance);
}
public void AddBindingParameters(ContractDescription contractDescription,
ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription,
ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription,
ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
}
This custom instance provider is then applied to every contract in the ServiceHost class. This is done by using a contract behavior. This is why the instance provider also implements IContractBehavior. You can see that we apply the instance provider in the ApplyDispatchBehavior method. The code below presents the ServiceHost and ServiceHostFactory implementations.
public class NInjectServiceHostFactory : ServiceHostFactory
{
private readonly IKernel kernel;
public NInjectServiceHostFactory()
{
kernel = new StandardKernel();
kernel.Bind<IDummyDependency>().To<DummyDepencency>();
//add the rest of the mappings here
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new NInjectServiceHost(kernel, serviceType, baseAddresses);
}
}
public class NInjectServiceHost : ServiceHost
{
public NInjectServiceHost(IKernel kernel, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (kernel == null) throw new ArgumentNullException("kernel");
foreach (var cd in ImplementedContracts.Values)
{
cd.Behaviors.Add(new NInjectInstanceProvider(kernel));
}
}
}
You can see that inside the ServiceHost constructor we iterate over all implemented contracts and apply the behavior we need. In our case this is NInjectInstanceProvider.
The custom ServiceHostFactory is required in order to create the DI container and populate it with mappings. We then override the CreateServiceHost method in order to provide our custom ServiceHost implementation.
The setup is complete at this point. All you need to do is create a WCF service that has a dependency on IDummyDependency. Also, don't forget to set the Factory attribute in the svc file like below (right click on svc file, then "View Markup"):
<%# ServiceHost Language="C#" Debug="true" Service="Service.DummyService" Factory="Service.NInjectServiceHostFactory" %>
Hope this helps. Also, I think NInject offers some implementations for this out of the box in NInject.Extensions.Wcf.dll.

Ninject - Creating a Custom NinjectWebServiceHost

I have a couple web services in my WCF project that require a custom ServiceAuthorizationManager to be able to authenticate OAuth calls. To do this, I created a custom WebServiceHostFactory. I am in the process of wiring up Ninject and am having a difficult time getting this converted over to a NinjectWebServiceHostFactory. Here is my code:
public class MyServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyServiceHost(serviceType, baseAddresses);
}
}
public class MyServiceHost: WebServiceHost
{
public MyServiceHost(Type serviceType, Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
Authorization.ServiceAuthorizationManager = new OAuthAuthorizationManager();
}
}
When I switch the WebServiceHost to a NinjectWebServiceHost it asks for an IServiceBehavior implementation. I have a ServiceBehavior attribute on my web service and I have a ServiceBehavior section in my web.config.
Has anyone seen this and been able to successfully implement something like this? Is there a better route to wire this up for my 2 web services? I do not want this to affect all of my web services.
We just did this the other day. We found it easier to implement a new type of NinjectWebServiceHostFactory that wired up the custom AuthorizationManager for us.
public class OAuthHostFactory : NinjectWebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var host = base.CreateServiceHost(serviceType, baseAddresses);
host.Authorization.ServiceAuthorizationManager = new OAuthAuthorizationManager();
return host;
}
}
This gives us the flexibility to pick and choose which routes or svc's we want to implement this particular factory on.
I believe you'll have to create a custom attribute which implements the IServiceBehavior interface yourself.
You're ApplyDispatchBehavior method implementation will want to look something like this:
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
Type serviceType = serviceDescription.ServiceType;
IInstanceProvider instanceProvider = new NinjectInstanceProvider(
new StandardKernel(), serviceType);
foreach(ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
{
DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
dispatchRuntime.InstanceProvider = instanceProvider;
}
}
}
Basically, you're creating a custom IInstanceProvider interface implementation which depends on Ninject to create instances for the DispatchRuntime.
Peter De Rycke goes into it further in his blog entry "Using an IoC container to create WCF service instances" (note the code above was taken from there).
I imagine if you still want to use a NinjectWebServiceHost, you could pass an IServiceBehavior implementation much like the one Peter outlines above.

Providing a factory instead of a Type in WCF ServiceHost

Is there any way to extend ServiceHost so that it accepts a factory?
I would like to use dynamic service proxies for some preprocessing of WCF calls without touching the service implementation.
EDIT
Now the ServiceHost creation looks like
var host = new ServiceHost(typeof(MyService));
and i would like to use something like
var factory = new ServiceProxyFactory<MyService>();
var host = new MyServiceHost(typeof(MyService), factory);
The interface i was looking for is IInstanceProvider.
public class MyServiceInstanceProvider<TService> : IInstanceProvider where TService : new()
{
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
return ServiceFactory.Create<TService>();
}
public object GetInstance(InstanceContext instanceContext)
{
return ServiceFactory.Create<TService>();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
return;
}
}
public class MyEndpointBehavior<TService> : IEndpointBehavior where TService : new()
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
return;
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.InstanceProvider = new MyServiceInstanceProvider<TService>();
}
public void Validate(ServiceEndpoint endpoint)
{
return;
}
}
public class MyServiceHost<TService> : ServiceHost where TService : new()
{
public MyServiceHost(params Uri[] baseAddresses)
:base(typeof(TService), baseAddresses)
{
}
public override System.Collections.ObjectModel.ReadOnlyCollection<ServiceEndpoint> AddDefaultEndpoints()
{
var endpoints = base.AddDefaultEndpoints();
foreach (var endpoint in endpoints)
{
endpoint.Behaviors.Add(new MyEndpointBehavior<TService>());
}
return endpoints;
}
public override void AddServiceEndpoint(ServiceEndpoint endpoint)
{
base.AddServiceEndpoint(endpoint);
endpoint.Behaviors.Add(new MyEndpointBehavior<TService>());
}
}
What you describe is not really possible with .NET...
You can implement a custom ServiceHost which allows you to customize the behaviour of the ServiceHost and/or the IDispatchMessageInspector which allows you inspect/modify any message inbound and outbound... IF you really wnat to implement some sort of "dynamic routing" then there is always the Routing capability of WCF...
Other options (though no 100% solution):
WCF service returning another service (service factory?)
WCF and factory design pattern
http://msdn.microsoft.com/en-us/library/aa702697.aspx
EDIT - I stand corrected:
It is not really possible to use a usual Factory BUT WCF provides the possibility to plug in an IInstanceProvider either at the Service or the Endpoint level...
For further reference see the following links
http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx
http://msdn.microsoft.com/library/system.servicemodel.dispatcher.iinstanceprovider.aspx
How do I pass values to the constructor on my wcf service?
http://geekswithblogs.net/13DaysaWeek/archive/2010/12/01/dependency-injection-and-wcf-services.aspx
http://www.eggheadcafe.com/tutorials/aspnet/b428fb65-08b4-45c8-97cd-47ee1a1eaf41/composing-wcf-applications.aspx

Categories