Using Castle windsor to resolve WCF service usingfactorymethod - c#

I'm trying to see if this is possible. I want to resolve the WCF service class from castle windsor via a factory class. The WCF service is hosted in IIS and so far I've only been getting a 404 when I try to call the service when using the factory. Here is my registration code:
container.AddFacility<WcfFacility>();
container.Register(Component.For<IServiceFactory>()
.ImplementedBy<ServiceFactory>()
.LifestyleSingleton());
container.Register(Component.For<IFooService>()
.UsingFactoryMethod((kernel, context)
=> kernel.Resolve<IServiceFactory>()
.CreateService(context.RequestedType))
.Named("FooService")
.LifestylePerWcfOperation());
Here is my factory class:
public class ServiceFactory : IServiceFactory
{
public IFooService CreateService(Type forType)
{
IFooService createdType = null;
if (forType == typeof(IFooService))
createdType = new FooService();
return createdType;
}
}
I have tried doing a strait .ImplementedBy<FooService>() and that works fine. It's only when I want to do it via a factory that I have a problem. Is this possible, meaning I'm missing something, or is it not possible?
(I know that the code shown is pretty simple, I am only testing if its possible before fully implementing my factory code)

you don't have to create a custom ServiceHost to do this, though you're right this is harder than it should be. The article that eouw0o83hf references first talks about an IInstanceProvider. That's the key, but you can wire it up using and WCF ServiceBehavior as well instead of a customer ServiceHost. I'm not sure what your FactoryMethod has to do with this - it sounds like it's a general wire up issue... or I'm not understanding your problem. I'll show below how I do the wire up without the ServiceHost and hopefully that fixes your problem.
First create a class that implements IInstanceProvider - mine below calls out to my ObjectResolver class with wraps Windsor. I'll leave that out for brevity.
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
public class ObjectResolverInstanceProvider : IInstanceProvider
{
private readonly Type _serviceType;
public ObjectResolverInstanceProvider(Type serviceType)
{
_serviceType = serviceType;
}
public object GetInstance(InstanceContext instanceContext)
{
return ObjectResolver.Resolve(_serviceType);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return ObjectResolver.Resolve(_serviceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
ObjectResolver.Release(instance);
}
}
Then create a service behavior that assigns your instance provider to each endpoint's DispatchRuntime's InstanceProvider:
using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
public class ConstructWithObjectResolverAttribute : Attribute, IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider = new ObjectResolverInstanceProvider(serviceDescription.ServiceType);
}
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
Next apply the service attribute to your service implementation... note you could do this in config if you wanted too, but I prefer applying it via an attribute like so:
[ConstructWithObjectResolver]
[ServiceBehavior(Namespace="YourNamespace")]
public class FooService : IFooService {}

Related

Notify Icon for Window Service

I have developed win service program which reads a excel file from my local drive and then save this file values to database and now I want to develop a notify icon which will be display to show a message("Excel File Saved In Database") after my service will start and will save excel file to database.
Please give me some hints to solve this.
From Vista onwards, your service will not be allowed to interact with the desktop, so cannot have a UI runnning directly out of the service. You need to build an agent application that starts up at user login that can chat to your service (maybe using WCF).
Here's what MS have to say about doing this:
For more complex interactions, developers should move their UI code into an agent that runs in the user’s session and handles all UI requirements. The agent communicates with the service through RPC or named pipes. If the user initiates the UI interaction by using Control Panel, Internet Explorer, or a similar UI experience, that UI experience should start the agent. The agent then handles all UI interactions. If UI is required but is not initiated by the user, the service must request the agent to start any required UI, instead of attempting to launch that UI by itself. In the rare situation where the service must initiate a user interaction and the agent is not already running, the service should call the CreateProcessAsUser API to start the agent. The agent can then initiate all UI interactions. It is important for developers to carefully review all possible usage scenarios and consider moving all UI code into an agent that runs in the user session.
The problem here is that a windows service runs in the background and has no impact on the user's desktop.
You could create an application similar to this (without the windows form): Notify Icon control in .Net 2.0
And then use something like the following class in the application to communicate with the windows service:
public class Program
{
public int Setting { get; set; }
}
[ServiceContract]
public interface ISettingService
{
[OperationContract]
void SetSetting(int setting);
}
public class SettingService : ISettingService
{
private readonly Program program;
public SettingService(Program program)
{
this.program = program;
}
public void SetSetting(int setting)
{
program.Setting = setting;
}
}
internal class CustomInstanceProvider : IInstanceProvider
{
private readonly Program program;
public CustomInstanceProvider(Program program)
{
this.program = program;
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
return new SettingService(program);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
IDisposable disposable = instance as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
internal class CustomInstanceProviderBehaviorAttribute : Attribute, IServiceBehavior
{
private readonly IInstanceProvider instanceProvider;
public CustomInstanceProviderBehaviorAttribute(IInstanceProvider instanceProvider)
{
this.instanceProvider = instanceProvider;
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
if (!ed.IsSystemEndpoint)
{
ed.DispatchRuntime.InstanceProvider = instanceProvider;
}
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
}
public class CustomServiceHost : ServiceHost
{
private readonly Program p;
public CustomServiceHost(Program program, params Uri[] baseAddresses)
: base(typeof(SettingService), baseAddresses)
{
this.p = program;
}
protected override void OnOpening()
{
Description.Behaviors.Add(new CustomInstanceProviderBehaviorAttribute(new CustomInstanceProvider(p)));
base.OnOpening();
}
}
I think you need NotifyIcon.ShowBalloonTip Method to implement in your service.
You may need to read this.

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.

Validate WCF user based on URL

If I have a wcf rest service such as http://somedomain.com/service.svc/uniqueid/somemethod/parameter1
then is there a way to globally check if the uniqueid is valid for every request hitting the server.
I could put in a check for every operation contract but I'm looking for a way where this is not needed so that everytime the service is accessed the uniqueid is checked and does not proceed if invalid.
Just for some further background as to what I'm trying to achieve... The WCF service is an open API. Getting a uniqueid is also open and requires no kind of signup. I want to use the uniqueid so if the API is abused I can easily pull 1 ID's access without affecting any of the other users of the system.
UPDATE:Based on Mike's Suggestion I've created an IParameterInspector
[AttributeUsage(AttributeTargets.Class)]
class IDParameterInspector : Attribute, IParameterInspector
And attached it to my Service class
[IDParameterInspector]
public class MetaData : IMetaData
The problem I now have is the ApplyDispatchBehavior never runs.
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
{
if (channelDispatcher == null)
{
continue;
}
foreach (var endPoint in channelDispatcher.Endpoints)
{
if (endPoint == null)
{
continue;
}
foreach (var operation in endPoint.DispatchRuntime.Operations)
{
operation.ParameterInspectors.Add(this);
}
}
}
}
Does anyone now what I'm doing wrong?
This is how to use a parameter inspector and custom behaviour via attributes. You need to unfortunately implement both.
So starting with the decoration of the service method in the interface
[MyFirstCustomBehavior()]
string SayHello(string language);
We then need to define the MyFirstCustomBehavior class.
internal sealed class MyFirstCustomBehavior : Attribute, System.ServiceModel.Description.IOperationBehavior
{
#region IOperationBehavior Members
public void AddBindingParameters(System.ServiceModel.Description.OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
//no special behaviour
}
public void ApplyClientBehavior(System.ServiceModel.Description.OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
{
throw new NotImplementedException();
}
public void ApplyDispatchBehavior(System.ServiceModel.Description.OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
{
dispatchOperation.ParameterInspectors.Add(new MyFirstCustomParameterInspector());
}
public void Validate(System.ServiceModel.Description.OperationDescription operationDescription)
{
//no special behaviour
}
#endregion
}
We then need to code up the inspector.
internal sealed class MyFirstCustomParameterInspector : System.ServiceModel.Dispatcher.IParameterInspector
{
#region IParameterInspector Members
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
////do stuff here
}
public object BeforeCall(string operationName, object[] inputs)
{
////or here
return null;
}
#endregion
}
You should then be good to go.
You can try creating a custom service behavior that will affect all the incoming requests.
Here is an example that filters the requests based upon IP address and you can use that as a reference. If I get some time I'll post some code.

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

WCF: Using my "custom" ServiceHost in my app.config/web.config for my wcf service?

I have a created a simple Custom ServiceHost that inherits from ServiceHost and overrides the method InitializeRuntime.
How do i change my app.config / web.config to use the custom service host so my overriden InitializeRunTime is executes..
I see attributes in the config file like behaviorConfiguration etc but nothing obvious where i can force it to use my Custom ServiceHost
My ServiceHost is simple :-
public class UnityServiceHost : ServiceHost
{
protected override void InitializeRuntime()
{
//DO MY UNITY INJECTION HERE
//Console.WriteLine("");
base.InitializeRuntime();
}
}
Any help really appreciated.
Thanks
Oran Dennison describes how to do this using Spring.NET: http://orand.blogspot.com/2006/10/wcf-service-dependency-injection.html
In summary, you'll use WCF's "behavior injection" to supply an instance of the service created by your DI container.
1) Create custom IInstanceProvider implementation with the GetInstance method returning the service object created by your container:
public object GetInstance(InstanceContext instanceContext, Message message)
{
return _container.Resolve(_serviceType);
}
2) Implement a custom IServiceBehaviour that adds your custom IInstanceProvider to each endpoint configuration.
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider =
new YourCustomInstanceProvider(serviceDescription.ServiceType);
}
}
}
}
3) In your custom service host, override OnOpening and add your custom service behavior
protected override void OnOpening()
{
this.Description.Behaviors.Add(new CustomServiceBehavior());
base.OnOpening();
}
Note that you may have to pass down your UnityContainer instance through to the IInstanceProvider so that it can do the resolving.
You need to create a custom ServiceHostFactory and use that to create your UnityServiceHost. You specify the ServiceHostFactory to use in the SVC file. See the MSDN docs for the SVC syntax.
If you're hosting the service yourself (as opposed to using IIS or WAS), you should simply create a UnityServiceHost instead of a regular ServiceHost.
If you are using IIS or WAS, write a ServiceHostFactory

Categories