First of all, I have never seen an example of using ninject with wcf.
This is my .svc:
<%# ServiceHost Language="C#" Debug="true" Service="MyService.Services.NotifyService" %>
My Service:
[ServiceContract]
public interface INotifyService
{
[OperationContract]
void SendEmail(string to, string from, string message);
}
class NotifyService : INotifyService
{
private IEmailRepository emailRepo;
public NotifyService(IEmailRepository emailRepo)
{
if (emailRepo== null) throw new ArgumentNullException("emailRepo");
this.emailRepo= emailRepo;
}
public void SendEmail(string to, string from, string message)
{
//do stuff here
}
}
Using this information, how do I dependency inject MyEmailRepository in NotifyService?
If I do not have a default constructor, wcf throws an error asking for one. I also have experience using ninject with asp.net mvc3 if that helps.
See https://github.com/ninject/ninject.extensions.wcf/tree/master/src/Examples/WcfTimeService
Use a custom IInstanceProvider to resolve your service instance. Here is an example:
http://orand.blogspot.com/2006/10/wcf-service-dependency-injection.html
This answer at SO provides a full implementation to add NInject to a WCF project.
I won't copy and paste it here, but basically, after installing the Ninject, Ninject.Extensions.Wcf and Ninject.Web.Common extensions through Nuget, you'll have to create three classes:
public class NInjectInstanceProvider : IInstanceProvider, IContractBehavior
public class NInjectServiceHostFactory : ServiceHostFactory
public class NInjectServiceHost : ServiceHost
Then point the Factory attribute in your .svc (right click the file on Solution Explorer, then choose "View Markup") to the NInjectServiceHost class:
<%# ServiceHost ... Factory="SomeNamespace.NInjectServiceHostFactory" %>
Related
With .NET 4.5, my WCF creation using svcutil suddenly seems to break (I've been using only .NET 4.0 until very recently) ....
With the default settings I'm using to convert a pre-existing WSDL to my C# WCF proxy class:
c:> svcutil.exe /n:*,MyNamespace /out:WebService MyService.wsdl
I get this C# file created:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="MyService.IMyService1")]
public interface IMyService1
{
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMyService1/IsAlive", ReplyAction="http://tempuri.org/IMyService1/IsAliveResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(MyService.MyFault), Action="http://tempuri.org/IMyService1/IsAliveErrorInfoFault", Name="MyServiceErrorInfo", Namespace="http://schemas.datacontract.org/2004/07/MyService.Types")]
string IsAlive();
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMyService1/IsAlive", ReplyAction="http://tempuri.org/IMyService1/IsAliveResponse")]
System.Threading.Tasks.Task<string> IsAliveAsync();
This doesn't work - if I try to instantiate an implemention of this interface in a ServiceHost
using (ServiceHost svcHost = new ServiceHost(typeof(MyService01Impl)))
{
svcHost.Open();
Console.WriteLine("Host running ...");
Console.ReadLine();
svcHost.Close();
}
I get this error:
Cannot have two operations in the same contract with the same name, methods 'IsAlive' and 'IsAliveAsync' in type 'MyService01Impl' violate this rule. You can change the name of one of the operations by changing the method name or by using the Name property of OperationContractAttribute.
Why does svcutil suddenly generate code that doesn't work??
If I use the /async keyword with svcutil, then I get the "old-style" async pattern with BeginIsAlive and EndIsAlive and things work again - but how can I tell WCF / svcutil to generate no async stuff at all?
svcutil by default generates a proxy class with both synchronous and Task-based methods, eg:
public interface IService1
{
...
string GetData(int value);
...
System.Threading.Tasks.Task<string> GetDataAsync(int value);
...
}
To generate a proxy with only synchronous methods, you need to use /syncOnly. This will omit the Task-based version:
public interface IService1
{
...
string GetData(int value);
...
}
In both cases, the proxy class itself inherits from ClientBase:
public partial class Service1Client : System.ServiceModel.ClientBase<IService1>, IService1
Finally, the /serviceContract switch generates only the interface and DTOs necessary for generating a dummy service
I tried to minimize writing of code for WCF CRUD part of big project with use of generics and castle WCF facility.
I have WCF service contract:
[ServiceContract]
public interface IResourceService : ICRUDService<DTOResource>
{
[OperationContract]
DTOResource Get(long id);
}
and generic interface
public interface ICRUDService<T> where T is IDTO
{
T Get(long id);
}
also generic MVC controller (1 controller for all basic crud for dtos and services)
public class CRUDController<T> : Controller where T is IDTO
{
readonly ICRUDService<T> service;
public CRUDController(ICRUDService<T> service)
{
this.service = service;
}
}
On the client side i register WCF client in Windsor Container
Component
.For<IResourceService , ICRUDService<DTOResource>>()
.AsWcfClient(... standard stuff... )
Everythig is working fine, components and services registered, controller created properly,
service
readonly ICRUDService<T> service;
in controller is of type
Castle.Proxies.IResourceService
But when i try to use service in controller i have error
Method Get is not supported on this proxy, this can happen if the method is
not marked with OperationContractAttribute or if the interface type is not
marked with ServiceContractAttribute.
When in controller i hardcode cast
((IResourceService)service).Get(id);
all is running properly, so i believe this problem is solvable.
I've also tried to use Forward (with same result) :
Component
.For<IActionTypeService>
.Forward<ICRUDService<DTOResource>>().AsWcfClient(...
How to make it work?
In the end i had to use 'Channel Factory' on client side.
I was able to use Windsor WCF Facility on server side to register generic contract :
[ServiceContract]
public interface ICRUDService<I>
{
[OperationContract]
I Get(int id);
}
with generic implementation
public class CRUDService<I, IEntity> : ServiceBase, ICRUDService<I>
{
public I Get(int id)
{
...
}
in standard way (for multiple types)
private void InstallExample<I, IEntity>(IWindsorContainer container)
{
container.Register(
Component
.For<ICRUDService<I>>()
.ImplementedBy(CRUDService<I, IEntity>)
.Named("somename")
.AsWcfService(
new DefaultServiceModel()
.Hosted()
.PublishMetadata(x => x.EnableHttpGet())
.AddEndpoints(WcfEndpoint
.BoundTo(new BasicHttpBinding())
.At("someAddress")
)
)
.LifeStyle.PerWcfOperation();
}
with fileless activation in web.config
<add factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" service="ClientService" relativeAddress="./ClientService.svc" />
On server side it works perfectly. Sadly on client side i didn't found working solution for WCFFacility and i had to use ChannelFactory (which is working perfectly)
ChannelFactory<ICRUDService<I>> factory = new ChannelFactory<ICRUDService<I>>(someBinding, someEndpoint);
For the rest (standard non generic services i'm using WCF Facility without any problems.
I think you need to put the ServiceContract attribute on ICrudService<>, add the OperationContract to the method there and remove the duplicate declaration of Get() from IResourceService.
I have a WCF service hosted in IIS7. The service has a static class with a static list containing strings (sort of log). It periodically write the entries to a file or db.
However when the IIS decides the recyle the app or terminate for whatever reason, the entries in the static field are lost.
Is there any way I can handle the service shuttingdown kind event and persist the data from memory?
Thanks
Shreedhar
I've implemented several services via IIS with a custom service host (originally I did this so I could implement IErrorHandler for global error handling).
You'll need two things - an implementation of ServiceHost and an implementation of ServiceHostFactory, which will call your custom service host. For example (just the relevant parts of code shown):
public class MyCustomServiceHost : ServiceHost
{
protected override void OnClosing()
{
// logic to save off your static data
base.OnClosing();
}
}
public class MyCustomServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyCustomServiceHost(serviceType, baseAddresses);
}
}
In your .svc file, you'd have something like this:
<%# ServiceHost Service="MyCompany.MyServiceName" Factory="MyCompany.MyCustomServiceHostFactory" %>
<%# Assembly Name="MyCustomServiceHost" %>
This is one way to do this (and this dates back to .NET 3.5 days); there are quite likely other ways to accomplish this, but at least this should give you some direction.
I am currently using Ninject (2.2.1.4) and Ninject.Extensions.Wcf (2.2.0.4) with my WCF service. I would like to upgrade to Ninject (3.0.0.15) and Ninject.Extensions.Wcf (3.0.0.5) and it doesn't look like I can use my current approach anymore. Can anyone point me to some samples or posts on how to get the latest version of Ninject working with a WCF project.
My current approach:
I wrote a module:
public class NinjectDependencyResolver : NinjectModule
{
public override void Load()
{
// Declare bindings
}
}
I added the Factory Attribute to my .svc file
Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"
I added a Global.asax to the WCF project
public class Global : NinjectWcfApplication
{
protected override IKernel CreateKernel()
{
return new StandardKernel(new NinjectDependencyResolver());
}
}
Now I can modify the default constructor in my service and use constructor injection.
Any pointers on how I could upgrade are appreciated.
Thanks
Add Ninject.Web.Common and derive from NinjectHttpApplication or use the App_Start file that comes with the NuGet package.
i am using ninject in a wcf web service.This web service is hosted in a project created as a "ASP.NET MVC 2 Empty Web Application".
It is using the references for Ninject.dll v2 and Ninject.Extensions.Wcf.dll v1.
The markup for the service file is
<%# ServiceHost
Language="C#"
Debug="true"
Service="wcf_ninject.Service1"
CodeBehind="Service1.svc.cs"
Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>
The global.asax is inheriting from NinjectWcfApplication
public class Global : NinjectWcfApplication
{
protected override IKernel CreateKernel()
{
return new StandardKernel(new WCFNinjectModule());
}
}
with
public class WCFNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IRepository>().To<EFRepository>();
// rest of bindings
}
}
and the only constructor for the service is:
public Service1(IRepository repository)
{
_repo = repository;
}
Most of the time works fine, but from time to time i get the error:
"Error activating Service1 More than one matching bindings are available"
But as said i am unable to find a reproduction path.
I assume you are using an older version. I can remember there was a multithreading issue with implicit bindings in 2.1 or even 2.0. It should be fixed in 2.2 and 3.0.