Wcf service inheritance (Extend a service) - wcf

The program I am working on exposes both callbacks and services using wcf.
Basically, what the services do is simply return some variables value. As for the callback, they simply update those variables.
I want to be able to expose one class containing only the services and one class containing the services and the callbacks.
For example :
[ServiceContract]
[ServiceBehavior(InstanceContextMode=InstanceContextMode::Single, ConcurrencyMode=ConcurrencyMode::Multiple)]
public ServiceClass
{
[OperationContract]
public int getValue()
{
return mValue;
}
protected static int mValue;
};
[ServiceContract]
[ServiceBehavior(InstanceContextMode=InstanceContextMode::Single, ConcurrencyMode=ConcurrencyMode::Multiple)]
public ServiceAndCallbackClass : ServiceClass
{
[OperationContract]
public bool subscribe()
{
// some subscribing stuff
}
public void MyCallback()
{
++mValue;
// Notify every subscriber with the new value
}
};
If I want only the services, I can use the base class. However, if I want to subscribe to the callback and use the service, I can use ServiceAndCallbackClass.
Is this possible ?

One solution I found :
Make 2 interfaces. The first one containing only the services and the second one inheriting from the first one and adding the callbacks.
An implementation class would implement the 2 interfaces.
Example :
[ServiceContract]
[ServiceKnownType(typeof(ICallback))]
public interface IService
{
[OperationContract]
int GetData();
}
[ServiceContract]
public interface ICallback : IService
{
[OperationContract]
public bool subscribe();
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode::Single, ConcurrencyMode=ConcurrencyMode::Multiple)]
public ServiceClass : IService, ICallback
{
public int getValue()
{
return mValue;
}
public bool subscribe()
{
// some subscribing stuff
}
public void myCallback()
{
++mValue;
// Notify every subscriber with the new value
}
protected static int;
};
[ServiceBehavior(InstanceContextMode=InstanceContextMode::Single, ConcurrencyMode=ConcurrencyMode::Multiple)]
public ServiceAndCallbackClass : ServiceClass
{
// Dummy implementation used to create second service
};
From there, we can create 2 services. One based on the implementation class and one based on the "Dummy" class. Each service would be created from a different interface and thus exposing different methods.

Related

Autofac - Registering instance type that takes interface as parameter

I am very new to Autofac and not able to understand the syntax for registration. I have following calsses/interfaces :
//Interface
public interface ISender
{
void Send();
}
//implementations
public class Post : ISender
{
public void Send()
{
//Post implementation
}
}
public class Email : ISender
{
public void Send()
{
//Email implementation
}
}
And a class that calls these implementations
public class Consumer
{
ISender Sender;
public Consumer(ISender sender)
{
Sender = sender
}
public void Act()
{
Sender.Send();
}
}
Now, which implementation to call is to be decided in a controller, so I tried using IIndex from this page like:
public calss PostController
{
Consumer ConsumerObject;
public PostController(IIndex<string, Consumer> consumer)
{
ConsumerObject = consumer["post"];
}
}
public class EmailController
{
Consumer ConsumerObject;
public PostController(IIndex<string, Consumer> consumer)
{
ConsumerObject = consumer["email"];
}
}
Firstly, is it correct or doable? Now the problem is I don't understand how to register in Autofac. So, How can we register Consumer and ISender in Autofac ?? Please suggest if there is any better/alternative way.
The way of registering components in Autofac is described widely in the documentation here. And how to use keyed services is described in the documentation you linked.
Basically you have to create ContainerBuilder, register all your components and build the container itself, based on the project type you have.
In your situation you need to use the following registrations:
var builder = new ContainerBuilder();
builder.RegisterType<Post>().Keyed<ISender>("post");
builder.RegisterType<Email>().Keyed<ISender>("email");
builder.RegisterType<Consumer>();
If you use ASP.NET WebApi (I assume that based on the fact you are using Controllers), you need to register your controllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
or for MVC
builder.RegisterControllers(typeof(MvcApplication).Assembly);
Now, there are various way to pick the Consumer with proper ISender implementation (I assume you want to pick proper implementation in controller).
One would be to inject IIndex<string, ISender> to Consumer class and pass the proper key string to it as well:
public class Consumer
{
ISender Sender;
public Consumer(string type, IIndex<string, ISender> sender)
{
Sender = sender[type];
}
public void Act()
{
Sender.Send();
}
}
Then, in controller you could use Func injection:
public class PostController
{
Consumer ConsumerObject;
public PostController(Func<string, Consumer> consumer)
{
ConsumerObject = consumer("post");
}
}
public class EmailController
{
Consumer ConsumerObject;
public EmailController(Func<string, Consumer> consumer)
{
ConsumerObject = consumer("email");
}
}
Another could be registering Consumer twice with Register method and resolving ISender in registration time.

WCF avoiding too many endpoints for experts

I have a lot of businesses services already implemented, and I´m exposing them as services by WCF.
I don´t like the idea to have one endpoint to each service..... it could be a problem to maintain in the future as my repository grows.......
I´d like to know wcf´s experts opinions if the code below would be a good approach an them I can move ahead with this solution.
Business Service A:
[ServiceContract]
public interface IServiceA
{
[OperationContract]
object AddA(object a);
[OperationContract]
object Update();
}
Business Service B:
[ServiceContract]
public interface IServiceB
{
[OperationContract]
object AddB(object b);
[OperationContract]
object Update();
}
Concrete implementation for Service A
public class ConcreteServiceA : IServiceA
{
public object AddA(object a)
{
Console.WriteLine("ConcreateServiceA::AddA");
return null;
}
public object Update()
{
Console.WriteLine("ConcreateServiceA::Update");
return null;
}
}
Concrete implementation for Service B
public class ConcreteServiceB : IServiceB
{
public object AddB(object b)
{
Console.WriteLine("ConcreateServiceB::AddB");
return null;
}
public object Update()
{
Console.WriteLine("ConcreateServiceB::Update");
return null;
}
}
My single service is partial to separate concerns to each service.
Note that it´s constructors depends on both business services above, will be injection using IoC
Partial for constructors
public partial class WCFService
{
IServiceA _a;
IServiceB _b;
public WCFService()
: this(new ConcreteServiceA(), new ConcreteServiceB())
{
}
public WCFService(IServiceA serviceA, IServiceB serviceB)
{
_a = serviceA;
_b = serviceB;
}
}
Partial class implementing only IServiveA
public partial class WCFService : IServiceA
{
object IServiceB.AddB(object b)
{
return _b.AddB(b);
}
object IServiceB.Update()
{
return _b.Update();
}
}
Partial class implementing only IServiceB
public partial class WCFService : IServiceB
{
object IServiceA.AddA(object a)
{
return _a.AddA(a);
}
object IServiceA.Update()
{
return _a.Update();
}
}
And in the client side, I using like that:
var endPoint = new EndpointAddress("http://localhost/teste");
ChannelFactory<IServiceA> _factoryA = new ChannelFactory<IServiceA>(new BasicHttpBinding(), endPoint);
IServiceA serviceA = _factoryA.CreateChannel();
serviceA.Update();
var netTcpEndPoint = new EndpointAddress("net.tcp://localhost:9000/teste");
ChannelFactory<IServiceB> _factoryB = new ChannelFactory<IServiceB>(new NetTcpBinding(), netTcpEndPoint);
IServiceB serviceB = _factoryB.CreateChannel();
serviceB.Update();
I really appreciate any opinion or other suggestions.
There's nothing wrong with multiple endpoints - it's part of the process. What is wrong, however, is duplicating functionality over multiple endpoints. How many "UpdateThis's" or "AddThat's" developers need? This can get out of control and makes for a maintenance headache. Just look at your constructor, it will grow and grow as you add new services and consolidate them into one service.
Think coarse-grained not fine-grained.
As an alternative, maybe you can try passing request objects as a parameter and returning response objects. This approach may streamline your code and help you avoid the maintenance issues you mention in your post and gives you a suggestion.
So, it looks something like this:
// Your service will return a very generic Response object
public interface IService
{
Response YourRequest(Request request);
}
// Your service implementation
public partial class WCFService : IService
{
Response IService.YourRequest(Request request)
{
//inspect the Request, do your work based on the values
//and return a response object
}
}
// Your request object
public class Request()
{
object YourClass{get;set;}
DoWhat Action{get;set;} //enum, constants, string etc.
int ID {get; set;}
}
// Your response object
public class Response()
{
bool Success {get; set;}
}
// Create Request object
var request = new Request(){YourClass = YourClassName , Action DoWhat.Update(), ID=1};
// Your service call
var endPoint = new EndpointAddress("http://localhost/teste");
ChannelFactory<IService> _factory = new ChannelFactory<IService>(new BasicHttpBinding(), endPoint);
IService service = _factory.CreateChannel();
var response = service.YourRequest(request);
So, now you've removed the fine-grained approach and replaced it with course-grained one. Let me know if you'd like more detail.

How to make WCF data interface serializable

I have a WCF service and one method accepts an interface IValidationDictionary when calling the service I need to access the interface but the VS generated proxy class shows the interface as an object. I tried to add data attributes to the interface but that is not allowed.
Thanks in advance.
public class UserService : IUserService
{
private IValidationDictionary validatonDictionary;
private IUserAppService userAppService;
public UserService(IUserAppService userAppService)
{
this.userAppService = userAppService;
}
public void SetValidation(IValidationDictionary validationDictionary)
{
this.validatonDictionary = validationDictionary;
}
public UserDTO GetUser(int id)
{
return this.userAppService.GetUser(id);
}
}
public interface IValidationDictionary
{
void AddError(string key, string errorMessage);
bool IsValid();
}
Interfaces can not be serialize, but you can return any object which implements that interface.

How do I solve the error that I received when implementing the callback method?

I am currently developing a WCF duplex service and I am trying to implement the callback method in my client app however there is a error of
'App.CallbackHandler' does not implement interface member IPostingServiceCallback.retrieveNotification(Service.Posting)'
the service contract for my service are as follow
[ServiceContract(SessionMode=SessionMode.Required , CallbackContract = typeof(IPostingServiceCallBack))]
public interface IPostingService
{
[OperationContract(IsOneWay = true)]
void postNotification(Posting post);
}
public interface IPostingServiceCallBack
{
[OperationContract]
String retrieveNotification(Posting post);
}
I have generated the proxy and added into the project file of my client and adding the endpoint address into the app.config.
EDIT
The code I have in my client app currently is
public class CallBackHandler : IPostingServiceCallback
{
public void retrieveNotification()
{
//planning to do something
}
}
Your client application needs to implement IPostingServiceCallBack and define the retrieveNotification method.
Say you have a client (not the proxy) that will be consuming your duplex service:
public class MyClient : IPostingServiceCallBack
{
public String retrieveNotification(Posting post)
{
// Implement your logic here
}
}
Note the above is a bare-bones example as a simple illustration. Your client will probably derive from another class as well (depending on whether it's ASP.NET, WinForms, WPF, etc).
Updated
You're still not implementing the method. Your callback interface is:
public interface IPostingServiceCallBack
{
[OperationContract]
String retrieveNotification(Posting post);
}
Your implementation is:
public class CallBackHandler : IPostingServiceCallback
{
public void retrieveNotification()
{
//planning to do something
}
}
You have public void retrieveNotification(), whereas the interface has String retrieveNotification(Posting post). The method signatures don't match.
You need to do:
public class CallBackHandler : IPostingServiceCallback
{
public String retrieveNotification(Posting post)
{
// planning to do something
}
}

Passing callback objects to WCF service methods

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.