Multiple WCF service contracts to share same session - c#

I have two service contracts and they get implemented as one. Naturally, I'm creating two client proxies for those contracts. Is it possible to maintain session between these two proxies. (btw I'm just starting with WCF so cut me some slack if I'm being too dumb)
As an example,
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IFoo
{
[OperationContract]
void DoFoo(int something);
}
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IBoo
{
[OperationContract]
int DoBoo();
}
[ServiceBehavior(InstanceContextMode =InstanceContextMode.PerSession)]
public class myservice: IFoo, IBoo
{
int somevalue;
void DoFoo(int something)
{
somevalue = something;
}
int DoBoo()
{
return somevalue;
}
}
Client Side Code:
using ServiceReference1;
static void main()
{
DoFooServiceClient fooproxy = new DoFooServiceClient();
DoBooServiceClient booproxy = new DoBooServiceClient();
fooproxy.DoFoo(5);
Console.WriteLine(booproxy.DoBoo());
}
I want it to return 5 but it returns 0. I know what's wrong, it is indeed creating two instances but is it possible to force them to use same instance? If I used static wouldn't it be the same value for all clients?

Since WCF instancing operates at the service contract level, you are going to struggle to share memory between only these two services.
Yes you could use a some static type but, as you say, the value would be synchronized across all service instances regardless, which is not the behavior you require.
An option would be to use some persistent resource like a database, or a singleton service instance, to store this shared data.
Another option may be possible, if you were to define Doo and Foo as singleton services for instancing. This would mean that you could access the state of each service directly from the service host, but would require some mediation logic to synchronize values between them.
I will try the mediation logic to sync values but that would require
additional client side code, wouldn't it?
It does not require client side code, but something on the service host to sync values between two service instances. I can only think of a way to do this if the services are both singleton instances. This becomes more complicated if you are using IIS for hosting, as this means you are not exposed to the actual ServiceHost instances.

Related

Fake WCF-Service calls with FakeItEasy

I want to test my Class, which calls the third Party Webservice. Is it possible to use FakeItEasy for this?
Wenn I try to Fake the Class from Reference.cs (auto generated), UnitTest started and doesn't come back.
Reference.cs(auto generated)
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class ws_AccessoryClient : System.ServiceModel.ClientBase<AccessoryService.ws_Accessory>,
AccessoryService.ws_Accessory
{
public ws_AccessoryClient()
{
}
public ws_AccessoryClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public AccessoryService.ResponseMessageOf_ListOf_SomeMethodInfo SomeMethod(
AccessoryService.RequestMessageOf_SomeMethod request)
{
return base.Channel.SomeMethod(request);
}
}
Test.cs
[Test]
public void DoBusinessLogicTryTest()
{
var accessoryProxy = A.Fake<ws_AccessoryClient>();
}
As has been mentioned you may not want to do what you are purposing for Unit Testing as this would cause more noise than is necessary for a Unit Test which could used mocked interfaces. However it is a valid approach for integration testing, this would allow you to test that your WCF wiring is working as you expect it. It also allows you to test your application as whole if you are adopting a more behaviour driven style of testing where you want to mock as little as possible.
I use this approach myself for spinning up fake endpoints using NSubstitute which is covered in my blog Hosting a Mock as a WCF service. The main things you need to do is spin up a ServiceHost, give it the endpoint address you want to use, set the context mode to single and provide the mock you want to use as the endpoint.
var serviceHost = new ServiceHost(mock, new[] { baseAddress });
serviceHost.Description.Behaviors
.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
serviceHost.Description.Behaviors
.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;
serviceHost.AddServiceEndpoint(typeof(TMock), new BasicHttpBinding(), endpointAddress);
One thing that I do in my testing is randomly choose the port that I host the endpoint on and inject the address into my application during testing. That way your tests will be able to run on other machines and build servers without clashing with other ports in use.
After looking at your example you might want to consider using the WCF ChannelFactory to create your client instead of using a concrete proxy client class. The ChannelFactory creates a proxy on the fly using the Interface you provide and allowing you to inject the proxy into its dependencies using the service interface. This would make unit testing easier and give you a more decoupled design.
You cannot (and why would you want to?).
If you want to verify that your class under test makes the call to the service, then wrap the service call in a class who's only job it is to call the service, and define it with an interface.
interface ICallTheService
{
void CallTheService();
}
class ServiceCaller : ICallTheService
{
void CallTheService()
{
// Call the service...
}
}
Then you can fake this class and verify that your class under test invokes the CallTheService operation.
// fake the service caller and pass it into your service
var serviceCaller = A.Fake<ICallTheService>();
// Verify invocation
A.CallTo(() => serviceCaller.CallTheService()).MustHaveHappened();
I want to test the logic in my class, depends on Response from
WCF-Service
This is where I think you're going wrong with separation of concerns. Your test is called DoBusinessLogicTryTest, yet it has a dependency on System.ServiceModel, which is an infrastructure concern. Your business logic should be testable without this dependency. If your class under test needs to behave differently depending on the response, you could do something like this:
interface ICallTheService
{
ServiceResponseModel CallTheService();
}
enum ServiceResponseModel
{
Success,
PartialSuccess,
FailureCondition1,
FailureCondition2,
// etc...
}
Then you can prime the ICallTheService fake to return each of the possible responses and test your class based on this.
A.CallTo(() => serviceCaller.CallTheService()).Returns(ServiceResponseModel.Success);
For Example if some Exceptions (defined in WCF) are handled correct
This is also nothing to do with business logic. The actual handling of exceptions is the responsibility of the ICallTheService implementation. In fact, I would introduce another class for this, whose job it would be to translate the various possible exceptions from System.ServiceModel into your response model. Eg
class WCFErrorResponseTranslator
{
ServiceResponseModel TranslateWCFException (Exception ex)
{
if (ex.GetType() == typeOf(TimeoutException)) { return ServiceResponseModel.TimeOut; }
/// etc
}
}
This behaviour could then be tested in isolation.

How To create Extensible WCF service

I need to have a service which would be called from my client project. The requirement is that I can change and release a service but after changing the service there should not be a need to rebuild the client. The example is, suppose I have service which helps s person reach the destination
[ServiceContract]
IDestinationHelper
{
[OperationContract]
void ReachDestination(string person);
}
class ReachedByTrain:IDetinationHelper
{
void ReachDestination(string person)
{
//Help the person to reach destination
}
}
Now the service is helping the person to reach the destination by train, in this case I will be calling the ReachedByTrain service from client, but suppose a requirement comes and I want the person to reach by Flight, in that case how should I proceed without changing or building the client. The functionality should be plugable and client should automatically detect it
class ReachedByFlight:IDetinationHelper
{
void ReachDestination(string person)
{
//Help the person to reach destination
}
}
Please provide any help or reference about how it can be done.
P.S There will be only one mode present to the client at a time. No matter if the client doesn't know about it.
You have multiple ways to reach extensibility.
The interface is fixed in your client. Building code that handles a changing interface is hard and error prone. Don't do that.
So you will need to keep the interface intact and change the internal behaviour of your class.
In your example, your service could return a list of points as a route to the target and a string that notes the transportation mode. Now you can include all sort of transportation modes and return routes for them without changing the interface.
When you add a new possible transportation mode, the client must be notified so it can be presented to the user for example in a ComboBox. That means you need a method in your interface that returns all possible transportation modes. That way, your client can handle new ones without recompile. It can even handle it when you remove modes.
This way your client has a contract and the contract never changes. But your methods can return different things when you rebuild and redeploy your service.
Example:
This contract never changes:
[ServiceContract]
IDestinationHelper
{
[OperationContract]
IEnumerable<Waypoint> ReachDestination(string transportationMode);
[OperationContract]
IEnumerable<string> GetAvailabletransportationModes();
}
IDestinationHelperService : IDestinationHelper
{
public IEnumerable<Waypoint> ReachDestination(string transportationMode)
{
// decide return value by transportation mode. Use a switch statement, dependency injection, IoC containers, whatever you want
}
public IEnumerable<string> GetAvailabletransportationModes()
{
// decide return value by getting all modes from wherever you decided upon above.
}
}
I think you need to have a [ServiceContract] with an [OperationContract] which would take "ModeOfTransport" as a parameter and has a routing logic to create an object of either ReachByTrain or ReachByPlane or ReachByAnything and would call it from within the [OperationContract]. From the client side you can call the [OperationContract] which has the routing logic with the appropriate parameter on hand.

WCF invoke not interfaced method?

just came across a problem.
I'm trying to make a wcf service unittest ready or better all code have to be tested with unittest.
Atm its not possible coze I've got a connection to a crm 2011 server that is used every time.
so i replaced it with a Interface. but i want to unittest the WCF like you use it.
now my idea is to make a public method and and give a fake connection.
now my question is would it be possible to invoke this method(example: ConnectionHandler), even if its not in the interface?
this would look like this:
public interface IWCF
{
[OperationContract]
bool method1();
[OperationContract]
bool method2();
}
public class WCF: IWCF
{
public bool method1(){
...
}
public bool method2(){
...
}
private connection connectionHandler;
public connection ConnectionHandler(Iconnection con){
if(con != null){
connectionHandler = con;
} else {
connectionHandler = takedefault;
}
}
}
Edit
ah i forgot to tell this: im actually have the security in mind, i don't want that anyone can pass a different connection to the server its for unittest purpose only.
It is possible to invoke this method, you can cast the interface to the concrete object. But that would compromise the calling code, which should not know the implementation details of your service.
I would reccomend in your sittuation to use the constrcutor injection so your service implemetation would look like this:
public interface IWCF
{
[OperationContract]
bool method1();
[OperationContract]
bool method2();
}
public class WCF: IWCF
{
private connection connectionHandler;
public WCF(Iconnection con)
{
if(con != null){
connectionHandler = con;
} else {
connectionHandler = takedefault;
}
}
public bool method1(){
...
}
public bool method2(){
...
}
}
In this case the client code will not know the details of the service implementation, if you use the constrcutor injection on the client as well
One of important features of any well designed piece of code is that you are explicit about the functionality that you expose to your clients. This becomes a key feature of service orientated applications, as you are exposing your functionality in a standardised way for external clients to consume.
Calling a method that is not part of the interface is bad in principle as you are now programming to the implementation and not the interface. Happily WCF knows this and will not let you a method that is not on the interface as it is not decorated with the OperationContract attribute.
With respect to your code - I am not sure exactly what it is you are trying to achieve - to have a client set (what I assume is) something like a database connection makes me a little uneasy (for a start this means your service is holding some state which goes against the Service statelessness principle). This does not mean that what you are doing is necessarily wrong, but you should find that you only rarely have to violate this in a well designed application.
That said, if you want to expose different areas of functionality to different clients the correct way to do this is by exposing endpoints on your service representing the different contracts:
[ServiceContract]
public interface IWCF
{
[OperationContract]
bool method1();
[OperationContract]
bool method2();
}
[ServiceContract]
public interface IConnectionWCF
{
[OperationContract]
bool SetConnection(string connection);
}
public class WCF : IWCF, IConnectionWCF
{
public bool method1()
{
...
}
public bool method2()
{
...
}
public bool SetConnection(string connection)
{
...
}
}
You also need to be mindful that everything the WCF service received must first be serialized by the client, sent over the wire, and deserialized on the server. You are very much dealing with concrete classes here - not abstractions. Passing an interface (such as Iconnection) as an argument to a service call does not really make any sense in a service-orientated environment.
With regards to unit testing - just remember that fundamentally the class WCF is just a plain old class. You can unit test this class in isolation of the fact that it is a WCF service. You shouldn't be setting up any of the service hosting functionality within your unit tests anyway - you want to check that the code that YOU write is correct - the WCF stack has already been tested by Microsoft.
EDIT
In response to your comment, as suggested here, you should used constructor injection to set the connection object when the class is instantiated. This then raises the question of how you gain control over the instantiation of the WCF service. You need to implement IInstanceProvider, or for a more detailed implementation see here. This way, when you service is hosted in WCF, you use IInstanceProvider, when you are testing you simply pass your fake connection object to the constructor.
EDIT
To clarify, a unit test for this class would resemble this:
[TestClass]
public class UnitTests
{
[TestMethod]
public void Test()
{
Iconnection connection = new FakeConnection();
WCF classUnderTest = new WCF(connection);
//Run test logic
}
}

wcf interface: why doesn't it 'just' go to the methode but to the whole class

I have WCF service implemented and the connection works just fine. I use BasicHttpBinding.
[ServiceContract]
public interface IScannerInput
{
[OperationContract]
string ScannedPRX(string barcode, string user, int color);
}
public class ProcessPRX : IScannerInput
{
ProcessClass c = new ProcessClass(); // every time a call ScannedPRX() this class is made again
public string ScannedPRX(string barcode, string user, int color)
{
c.PrxScannedInput(barcode, user, color);
return "Bussy processing: " + barcode;
}
}
In a normal class I can just make ProcessClass c one time. But now it is made again and again every time a call the methode ScannedPRX(). What am I doing wrong? It is not just going to the methode but to the whole class.
There is three ways of instantiating WCF service object:
PerCall: A new InstanceContext (and therefore service object) is created for each client request.
PerSession: A new InstanceContext (and therefore service object) is created for each new client session and maintained for the lifetime of that session (this requires a binding that supports sessions).
Single: A single InstanceContext (and therefore service object) handles all client requests for the lifetime of the application.
PerCall is default one, and that is what you are having.
If you want other behaviour read article below.
http://msdn.microsoft.com/en-us/library/ms731193.aspx
Take into account concurrent request that are made to your service, as if you are choosing for instance Single instantiation mode, you need to take care on your own that all your methods are thread safe.
Because the default instancing behavior for WCF services is to create a new instance for every call. You generally want this to avoid sharing state between different callers of your service or multiple invocations by the same client. Unless ProcessClass is expensive to create or you need to maintain state between calls, I would stick with this model.

Dealing with concurrency and complex WCF services interacting with objects of the overall application

I am enjoying creating and hosting WCF services.
Up until now I can create services defining contracts for the service and data (interfaces) and defining hosts and configuration options to reach them (endpoint specifications).
Well, consider this piece of code defining a service and using it (no mention for endpoints that are defined in app.config not shown here):
[ServiceContract]
public interface IMyService {
[OperationContract]
string Operation1(int param1);
[OperationContract]
string Operation2(int param2);
}
public class MyService : IMyService {
public string Operation1(int param1) { ... }
public string Operation2(int param2) { ... }
}
public class Program {
public static void Main(stirng[] args) {
using (ServiceHost host = new ServiceHost(typeof(MyService))) {
host.Open();
...
host.Close();
}
}
}
Well, this structure is good when creating something that could be called a Standalone service.
What if I needed my service to use objects of a greater application.
For example I need a service that does something basing on a certain collection defined somewhere in my program (which is hosting the service). The service must look into this collection and search and return a particular element.
The list I am talking about is a list managed by the program and edited and modified by it.
I have the following questions:
1) How can I build a service able to handle this list?
I know that a possible option is using the overloaded ServiceHost constructor accepting an Object instead of a Type service.
So I could pass my list there. Is it good?
[ServiceContract]
public interface IMyService {
[OperationContract]
string Operation1(int param1);
[OperationContract]
string Operation2(int param2);
}
public class MyService : IMyService {
private List<> myinternallist;
public MyService(List<> mylist) {
// Constructing the service passing the list
}
public string Operation1(int param1) { ... }
public string Operation2(int param2) { ... }
}
public class Program {
public static void Main(stirng[] args) {
List<> thelist;
...
MyService S = new MyService(thelist)
using (ServiceHost host = new ServiceHost(S)) {
host.Open();
...
host.Close();
// Here my application creates a functions and other that manages the queue. For this reason my application will edit the list (it can be a thread or callbacks from the user interface)
}
}
}
This example should clarify.
Is it the good way of doing? Am I doing right?
2) How to handle conflicts on this shared resource between my service and my application?
When my application runs, hosting the service, my application can insert items in the list and delete them, the same can do the service too. Do I need a mutex? how to handle this?
Please note that the concurrency issue concerns two actors: the main application and the service. It is true that the service is singleton but the application acts on the list!!!
I assume that the service is called by an external entity, when this happens the application still runs right? Is there concurrency in this case???
Thankyou
Regarding point 2, you can use Concurrent Collections to manage most of the thread safety required.
I'm not sure what you mean by point 1. It sounds like you're describing basic polymorphism, but perhaps you could clarify with an example please?
EDIT: In response to comments you've made to Sixto's answer, consider using WCF's sessions. From what you've described it sounds to me like the WCF service should be sat on a seperate host application. The application you are using currently should have a service reference to the service, and using sessions would be able to call an operation mimicking your requirement for instantiating the service with a list defined by the current client application.
Combine this with my comment on exposing operations that allow interaction with this list, and you'll be able to run multiple client machines, working on session stored Lists?
Hope that's explained well enough.
Adding the constructor to MyService for passing the list certainly will work as you'd expect. Like I said in my comment to the question however, the ServiceHost will only ever contain a single instance of the MyService class so the list will not be shared because only one service instance will consume it.
I would look at a dependency injector (DI) container for WCF to do what you are trying do. Let the DI container provide the singleton list instance to your services. Also #Smudge202 is absolutely correct that using the Concurrent Collection functionality is what you need to implement the list.
UPDATE based on the comments thread:
The DI approach would works by getting all of an object's dependencies from the DI container instead of creating them manually in code. You register all the types that will be provided by the container as part of the application start up. When the application (or WCF) needs a new object instance it requests it from the container instead of "newing" it up. The Castle Windsor WCF integration library for example implements all the wiring needed to provide WCF a service instance from the container. This posts explains the details of how to use the Microsoft Unity DI container with WCF if you want to roll your own WCF integration.
The shared list referenced in this question would be registered in the container as an already instantiated object from your application. When a WCF service instance is spun up from the DI container, all the constructor parameters will be provided including a reference to the shared list. There is a lot of information out there on dependency injection and inversion of control but this Martin Fowler article is a good place to start.

Categories

Resources