What I'm trying to do is the following:
1) I have the following WCF service contract:
[ServiceContract]
public interface IUploadService
{
[OperationContract]
ServiceData Upload(Request request);
}
[DataContract]
public class Request
{
[DataMember]
public long AbnNumber;
[DataMember]
public string Email;
}
2) This contract is implemented like this.
public class UploadService : IUploadService
{
public bool Upload(Request request)
{
// Some code
}
}
In the "Some code" section I would like to call a validation class to validate the clients request, so something like this:
var result = validation.ValidateRequest(request);
So my question is: Is it a bad idea to create an instance of my validation class inside the Upload method? Like this:
public class UploadService : IUploadService
{
public bool Upload(Request request)
{
var validation = new Validation();
var result = validation.ValidateRequest(request);
}
}
I know you can get around this by creating a constructor but as far as I know you can't create a constructor inside a WCF service implementation class, or am I wrong?
I'm new to WCF so if I'm totally heading the wrong direction please let me know.
Thanks
Personally I like as little as possible in my service methods. I would have a separate project to handle the Upload. This then allows you to reuse this code more easily, and to test the functionality without creating the service.
As to whether you should create your Validation like this it really depends on what it does, but generally I would make sure the Validation class implements an interface containing ValidateRequest(Request) and then inject that. You can then mock it in your tests if you need to.
So your service code would look like
public class UploadService : IUploadService
{
private readonly IUploadHandler _uploadHandler;
public UploadService(IUploadHandler uploadHandler)
{
_uploadHandler = uploadHandler;
}
public bool Upload(Request request)
{
//would possibly do some mapping here to create a different type of object to pass to the handler
_uploadHandler.Upload(request);
}
}
and the handler in a different project would look like
public class UploadHandler : IUploadHandler
{
private readonly IValidation _validator;
public UploadHandler(IValidation validator)
{
_validator = validator;
}
public bool Upload(Request request)
{
return _validator.ValidateRequest(request);
}
}
So my question is: Is it a bad idea to create an instance of my validation class inside the Upload method?
It comes down to whether you will be using Singleton or Per Call services. Usually it is better to have new instance of Service created for every request, and in that case it is OK to create all instances in your operation.
Interesting discussion on this topic Should WCF service typically be singleton or not?
If you decide to not to create Validation class for each then request there are two options:
Make it singleton
Create custom ServiceHostFactory for your service and initialize your Service in it (with constructor). Useful links on this topic:Extending Hosting Using ServiceHostFactory, Integrating StructureMap with WCF
Related
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?
I'm trying to create a method using the object type within my WCF WebService, but I get the following error :
Interface :
[ServiceContract]
public interface IService1
{
[OperationContract]
object GetTwoX(object yo);
}
Class :
public class Service1 : IService1
{
static public Dictionary<string, List<OPUSInfo>> cache;
public object GetTwoX(object yo)
{
return yo;
}
}
Does somebody know how to pass Object type in ?
You can definitely create a method which takes and/or returns object, but as the error says, don't expect the simplistic Test Client to be able to do anything. Use a full-featured service testing application like SoapUI to do that.
I created a LoggerDomainService witch look like this :
[EnableClientAccess()]
public class LoggerDomainService : DomainService
{
public void info()
{
// todo
}
}
And after building the server side the LoggerDomainContext did not created.
I've noticed that in order to make it work I need to declare inside the class at least on method with the [Query] attribute.
Is there better way to solver the problem, should I inherit from something else then DomainService ?
You are correct about the [Query] attribute. With your logging service, I recommend using [Invoke]:
[EnableClientAccess()]
public class LoggerDomainService : DomainService
{
[Invoke]
public void info()
{
// todo
}
}
Then you will find the context created.
Lets say I have 3 assemblies, Example.Core, Example.Contracts, Example.WcfServices. In my contracts assembly I define an interface and add some operation, e.g. ICalculator, which has operation Add(double a, double b). In my WcfServices assembly I have an implementation of ICalculator explosed as a Wcf service.
Now my question is this....in my Example.Core assembly how do I program against that interface while keeping everything decoupled (to allow me to have an alternative implementation of the interface). If I have a class that needs an ICalculator I can create one from say a ChannelFactory and use it, or I can inject an instance in the constructor. If I create one in the class then I am putting dependencies in my class on ChannelFactory/Wcf and I really don't want to do that. If I inject an instance in my constructor then how will the injecting class manage and tidy up the wcf service? It seems that although I have an interface I have no clean way of using it. I have looked at something like NInject, but I am not convinced that it would clean up the ChannelFactory if it faults (at least I haven't found any documentation that shows it knows when to call Abort rather than Close on the channel).
What I have ended up doing is implmenting my interface again and using the method described in this question: creating WCF ChannelFactory<T> and just recalling the methods on the service. This "smells" a bit to me as I am wrapping all my calls again just to ensure the channel is properly closed/aborted.
Has anyone any patterns/methods that cleanly have two implmentations of an interface, one of which is a Wcf service?
Thanks,
Mike.
I have used a variation of the answer linked in Mark's comment and this article here to come up with a solution that has worked for me.
Given the service contract you defined, step 1 will be to define an interface implementing your service and IClientChannel.
// Service Contract
public interface ICalculator
{
Add(double a, double b);
}
// Interface to expose Close and Abort
public interface ICalculatorChannel : ICalculator, IClientChannel { }
Step 2 involves creating reusable code that will handle creating the proxies and implementing the code to close or abort connections.
public class ServiceClient<T> where T : class, IClientChannel
{
private ProxyGenerator _generator = new ProxyGenerator();
public T CreateProxy(string endpointConfigurationName)
{
return _generator.CreateInterfaceProxyWithoutTarget<T>
(new WcfInterceptor<T>(endpointConfigurationName));
}
}
The T in ServiceClient<T> will take the ICalculatorChannel defined in step 1. The ProxyGenerator is part of the Castle project. Its usage here is to allow us to intercept the calls to the WCF service and perform pre and post actions.
public class WcfInterceptor<T> : IInterceptor where T : IClientChannel
{
private ChannelFactory<T> _factory = null;
public WcfInterceptor(string endpointConfigurationName)
{
_factory = new ChannelFactory<T>(endpointConfigurationName);
}
public void Intercept(IInvocation invocation)
{
T channel = _factory.CreateChannel();
try
{
invocation.ReturnValue = invocation.Method.Invoke
(channel, invocation.Arguments);
}
finally
{
closeChannel(channel);
}
}
}
As you can see, the Intercept method encapsulates the channel and the call to close the channel. The closeChannel method will handle the decision to call Close() or Abort().
private void closeChannel(T channel)
{
if (channel != null)
{
try
{
if (channel.State != CommunicationState.Faulted)
{
channel.Close();
}
else
{
channel.Abort();
}
}
catch
{
channel.Abort();
}
}
}
Now we create a class to wrap up the usage of this ServiceClient.
public class Calculator : ICalculator
{
private var _calcualtor = new ServiceClient<ICalculatorChannel>();
public void Add(double a, double b)
{
var proxy = _calculator.CreateProxy("endpointConfigGoesHere");
return proxy.Add(a, b);
}
}
Notice that the implementation of add no longer has to deal with the WCF connection concerns. The consuming class only has to know about the Service Contract. The ugliness of of dealing with faulted connections is now taken care of for us by the ServiceClient class.
The client need only take on one dependency now.
public class MyClient
{
private ICalculator _calculator;
public MyClient(ICalculator calculator)
{
_calculator = calculator;
}
}
And IOC can populate the client:
Bind<ICalculator>().To<Calculator>();
Is it possible to pass callback objects (with callback methods) to a wcf service method?
Let's presume i have the following class:
class Callback
{
public Callback(){}
public int GetSomeData(int param)
{
return param;
}
}
Is it possible somehow to make a call like :
WCFServiceProxy proxy = new WCFServiceProxy();
Callback myCallback = new Callback();
proxy.SomeMethod(myCallback);
and have the service call GetSomeData() implemented on the client side?
Or what would be a working solution for this?
see Duplex Services
Yes, you can do that. You have to define a secondary interface that serves as the callback contract.
[ServiceContract]
public interface ICallback
{
[OperationContract(IsOneWay=true)]
void InvokeCallback();
}
[ServiceContract(CallbackContract=typeof(ICallback)]
public interface IContract
{
[OperationContract]
void DoSomething();
}
[ServiceBehavior]
public class MyService : IContract
{
void DoSomething() { }
}
That's the basic approach. I would strongly suggestion looking at Juval Lowy's website, IDesign.net. His downloads section has several examples of how to do this.