Can't get Ninject Interception to work with WCF - wcf

we're switching from UNITY to Ninject as our default service locator for WCF services. There's a beautiful NuGet package available for doing this and getting the standard resolution up-and-running is a breeze.
However - I want to intercept the calls to my WCF service. Here's what I've got:
My svc file:
<%# ServiceHost Language="C#" Debug="true" Service="NinjectWcfApp.Service1" Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>
Here's my service:
public class Service1 : IService1
{
[Inject]
public ISomeManager Manager { get; set; }
public string GetData(int value)
{
if(this.Manager != null)
this.Manager.DoStuff();
return string.Format("You entered: {0}", value);
}
}
Kernel is built up like this:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISomeManager>().To<SomeManager>();
kernel.Bind<IService1>().To<Service1>().Intercept().With<MyInterceptor>();
}
If I setup the kernel like this, the manager instance is injected, but there's no interception taking place. My interceptor that logs something before execution and after execution is never invoked.
Other Stackoverflow threads suggest using:
kernel.Bind<Service1>().ToSelf().Intercept().With<MyInterceptor>();
If I do that, the manager is not being injected. If I then go ahead and create a constructor which takes in the manager, it works, but again: no interception.
kernel.Bind<Service1>().ToSelf().WithConstructorArgument("manager", kernel.Get<ISomeManager>()).Intercept().With<MyInterceptor>();
What am I doing wrong here?

Any methods which are intercepted must be virtual:
public virtual string GetData(int value)

Related

Running WCF service method during start of Windows Service

I have got WCF service running as Windows service and I need to run a method of the WCF Service when Windows Service is starting. Is it possible in any way?
[ServiceContract]
public interface IWebMonitorServiceLibrary
{
[OperationContract]
void TestMethod();
}
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class WebMonitorServiceLibrary : IWebMonitorServiceLibrary
{
#region properties
#endregion
#region events
#endregion
public WebMonitorServiceLibrary()
{
Initialization();
}
private void Initialization()
{
/////////
}
public void TestMethod()
{
//////////
}
}
You don't explain why you want this initialization code to run, but given you almost never want to use a single-instance WCF service, the proper way would be to use dependency injection (see How do I pass values to the constructor on my wcf service?).
Create an object in which you store the things you want to initialize, which you initialize on your Windows Service start:
public class SomeSettingsYouWantToInitialize
{
public string SomeSetting { get; set; }
}
public class WindowsServiceInstance : ServiceBase
{
protected override void OnStart(string[] args)
{
InitializeWcfService();
}
private void InitializeWcfService()
{
var settings = new SomeSettingsYouWantToInitialize
{
SomeSetting = "Foo"
};
_yourDependencyContainer.Register<SomeSettingsYouWantToInitialize>(settings);
}
}
Then (using whatever dependency injection framework you use), inject that into your service's constructor:
public class WebMonitorServiceLibrary
{
public WebMonitorServiceLibrary(SomeSettingsYouWantToInitialize settings)
{
// do stuff with settings
}
}
Generally, no. This is because by default (and following best practice) you will have configured your service to run per-call (or per session), which means there can be multiple instances of your actual service running in your service host.
Therefore, any requirement for you to be able to return an instance of the service from the service host will involve some nasty plumbing code and is not advised.
Specifically, however, there are two approaches you could use to do what you want.
The first involves running your service in InstanceContextMode.Single - this means there will be a single service instance which will handle all requests. If you do this then you can simply create the service instance and then pass it into the servicehost when you start the windows service:
var service = new MyService();
var host = new ServiceHost(service);
You then have access to the service instance and can call the operation directly.
service.MyOperation("something");
The second thing you can do for when you don't want to run a singleton service you can make your service implementation just a wrapper around a static instance of a shared class that actually process the requests. As an example:
public class MyService : IMyService
{
private static IMyService instance = new MySharedServiceClass();
public static IMyService Instance
{
get { return instance ; }
}
public bool MyOperation(string something)
{
return instance.MyOperation(something);
}
}
Then you can call the method on the class like this:
var host = new ServiceHost(typeof(MyService));
var instance = MyService.Instance;
instance.MyOperation("something");
I would still avoid doing this if at all possible. Think to yourself why do you even want this method called on startup? Surely it would be better to have this code directly in the windows service if it's something that needs to be run on startup?

Error accessing a WCF service

I have a very strange problem.
I have a working WCF service.
[ServiceContract]
public interface IService
{
[OperationContract]
int AddResult(int result, string name);
[OperationContract]
int list(int count);
}
In another class I have the implementation of this service. And it works.
But when I change the method "list" like this:
[ServiceContract]
public interface IService
{
[OperationContract]
int AddResult(int result, string name);
[OperationContract]
List<string> list(int count);
}
When I add service reference from targeted project (it is a Windows Phone application) I receive several errors and warnings. The key idea of them is that the service cannot be loaded (or endpoints can not be loaded).
The difference between two methods is very small - List instead of int type. But it is crucial.
Why it is so? Why I can not use List?
did you try to encapsulate your List collection into a proxy class? You could try something like:
[DataContract]
public class MyData
{
[DataMember]
public List<string> list { get; set; }
}
[ServiceContract]
public interface IService
{
[OperationContract]
int AddResult(int result, string name);
[OperationContract]
MyData list(int count);
}
Also, take a look at this link, I think that it might be what you are looking for.
UPDATE
As per discussed on the comments section of this thread, the problem was not located in the WCF service itself, but on the client that was being generated in #user1460819 Windows Phone app.
This problem was solved after the WCF Service binding was changed to "basicHttpBinding", the WCF reference on the client side was regenerated and the whole project was rebuilt.

WCF using Ninject Dispose not triggering in requestscope

Here is my module
internal class WebServiceConfiguration : NinjectModule
{
public override void Load()
{
Bind<IWebService>().To<WebService>().InRequestScope();
}
}
Here is the global.asax
public class Global : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
return new StandardKernel(new WebServiceConfiguration());
}
}
I also tried InScope(c => OperationContext.Current)
Here is my service with IDisposable in IWebService
[ServiceBehavior(InstanceContextMode = InstanceContextModeDefinition.Mode)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class WebService : IWebService
{
private readonly ISomeService _someService;
public WebService(ISomeService someService)
{
_someService = someService;
}
public void Dispose()
{
_someService.Dispose();
}
Here is the ServiceHostFactory in the service markup
<%# ServiceHost Language="C#" Debug="true" Factory="Ninject.Extensions.Wcf.NinjectDataServiceHostFactory" Service="WCFTest.Services.WebService" CodeBehind="WebService.svc.cs" %>
The injection of dependencies works. My only concern is that the dispose method is not being triggered when the Client closes the service call.
I tried to remove the Factory="Ninject.Extensions.Wcf.NinjectDataServiceHostFactory" just to test if the Dipose will be called, and it did call but of course i won't have auto injection. So there might be something i'm doing wrong in the setup? or there is a bug on ninject not calling Dispose?
Note: I grab the sample setup in ninject wcf extension and just added some DI.
Your help will be appreciated.
BTW: I'm using Ninject 3.0.0.15, Ninject.Extensions.Wcf 3.0.0.5, Ninject.Web.Common 3.0.0.7
Use
Bind<IWebService, WebService>().To<WebService>().InRequestScope();

Ninject with WCF and Interception (for AOP)

I've been trying to get the ninject working in wcf, using the wcf extension and the interception with dynamicproxy2 extension. I've basically created a Time attribute and have it all working in a basic scenario. Where I get trouble is when in ninject module I create my service binding with a constructor argument:
Bind<IMyDependency>().To<MyDependency>();
Bind<IService1>().To<Service1>().WithConstructorArgument("dependency", Kernel.Get<IMyDependency>());
Everything works fine, but the Time attribute wont fire on anything in my Service1 or MyDependency.
The time attribute is the standard one floating all over the internet. The only other piece of code really is the CreateKernel method is the global.asax, which looks like this:
protected override IKernel CreateKernel() {
IKernel kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new WcfNinjectModule(),
new DynamicProxy2Module()
);
return kernel;
}
Thanks for any help!
Matt
EDIT 12/12/2011: As requested, I've added some more detail below:
The entire wcf ninject module:
public class WcfNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IMyDependency>().To<MyDependency>();
Bind<IService1>().To<Service1>();
}
}
The create kernel method in the global.asax is above, and the global.asax inherits from NinjectWcfApplication.
Service method looks like this:
public class Service1 : IService1
{
private IMyDependency _dependency;
public Service1()
{
}
public Service1(IMyDependency dependency)
{
_dependency = dependency;
}
[Time]
public virtual string GetData(string value)
{
return string.Format(_dependency.GetMyString(), value);
}
}
public interface IMyDependency
{
string GetMyString();
}
public class MyDependency : IMyDependency
{
[Time]
public virtual string GetMyString()
{
return "Hello {0}";
}
}
Does this help?
Since removing the 'WithConstructor' argument, the time intercept attribute will fire on GetMyString but not on GetData.
Matt
After a little more work (and writing that last post edit), it turns out that just removing the WithConstructorArgument method did resolve my problem and everything now seems to be working fine.
Matt

Injecting an unrelated contract into the WSDL created by WCF's MEX provider

I am implementing a WCF service (Contract A) that will eventually make calls to a standalone service (Contract B) hosted by the client. At design-time when the client queries my service's WSDL to build its proxy, I'd like to include the WSDL for Contract B so the client can build its service around that. Unfortunately, I can't figure out how to inject Contract B into the WSDL emitted by the service. Since the contract is an interface and doesn't have the [DataContract] attribute I can't add it as a known type. Is there any other way to inject a contract into emitted WSDL?
Here's an example:
[ServiceContract]
public interface IServerService
{
[OperationContract]
void GiveTheServerMyServiceUri(string uri);
[OperationContract]
void TellAllClientsSomething(string message);
}
// THIS IS THE INTERFACE I WANT TO INCLUDE IN THE WSDL
[ServiceContract]
public interface IClientService
{
[OperationContract]
void ReceiveMessageFromServer(string message);
}
public class ServerService : IServerService
{
private List<string> knownClients;
public void GiveTheServerMyServiceUri(string uri)
{
knownClients.Add(uri);
}
public void TellAllClientsSomething(string message)
{
foreach (string clientUri in knownClients)
{
// 1. Create instance of ClientServiceProxy using client's uri
// 2. Call proxy.ReceiveMessageFromServer(message)
}
}
}
At first it seems that this is a textbook example of a duplex contract. However, for this particular application, for a variety of reasons, I need a bit more separation between client and server so I was hoping to just give the client an interface to implement (via the WSDL), let it host its own service, then just tell me the service's url.
I don't see that this makes sense. Unless your service is implementing the service contract of the other service, then don't do this.
On the other hand, your service can implement the other service contract, and become a client to the other service. It can then delegate calls to the other service contract to that other service.
I just tried this to make sure. I created a new WCF Service library project. This created a Service1 implementing IService1, with two operations. I modified the [ServiceContract] attribute to use a specific namespace (http://localhost/service1).
I then added a new service, which gave me Service2, implementing IService2, with a single operation (DoWork). I updated the [ServiceContract] to use http://localhost/service2/.
I then updated Service1 to implement IService2 as well as IService1, and to delegate IService2.DoWork to the Service2 service. I did also have to add a new endpoint implementing IService2, and I had to specify a relative address, so that the two would not conflict (since they were in the same project). Here's the result:
using System;
namespace WcfServiceLibrary1
{
public class Service1 : IService1, IService2
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
public void DoWork()
{
Service2Reference.IService2 svc = null;
try
{
svc = new Service2Reference.Service2Client();
svc.DoWork();
}
finally
{
if (svc != null)
{
((IDisposable)svc).Dispose();
}
}
}
}
}