creating a wcf client instance using unity - c#

So currently I'm creating a wcf client instance using the following code:
Service1Client client = (Service1Client)_container.Resolve<IService1>(new ParameterOverride("remoteAddress", url),
new ParameterOverride("endpointConfigurationName", "basicEndpoint"));
however this doesn't work when I'm creating unit tests as I'm casting the object as a Service1Client so my unit test bombs out as it cannot cast a Mock object:
//Mock the WCF service
var wcfMock = new Mock<IService1>();
//register with container!
var container = new UnityContainer();
container.RegisterInstance(wcfMock.Object);
Any ideas on how best to resolve this issue?

You claim to be casting to Service1Client so you can access the methods Open(), Abort() and Close() of System.ServiceModel.ClientBase.
Those methods are defined in System.ServiceModel.ICommunicationObject, so let your interface IService1 inherit from that:
public interface IService1 : ICommunicationObject
{
}
Then you can omit the cast.

Related

Dynamically using same method in multiple web service references?

In c# .Net Framework 4.5 (Visual Studio Ultimate 2012, Version 11.0.61219.00 Update 5), I'm trying to define a service variable at runtime for which webservice to use. Each webservice (there are many) are all defined the same except for the endpoint url but the credentials will not cross over to authenticate. The below condition is menial to simplify the issue at hand. The following code gives the error: Cannot implicitly convert type WebService2.Service to WebService1.Service.
What I've tried: calling functions to return the proper service but the parameters or assignment all require a specific type.
var service = new WebService1.Service();
service = new WebService2.Service();
I want to be able to use the variable service in the rest of the program without having to duplicate code everywhere for using the many web service references.
It seems like what you are looking to do, you would need a common interface between the two services so you could inject whichever service you wish to use.
public class WebService1 : IWebService {...service code}
public class WebService2 : IWebService{...service code}
public interface IWebService{...service methods you will be calling}
Then you could do the following.
IWebService service = new WebService1.Service();
service = new WebService2.Service();
Assuming that the different services share the same method names, you can create an interface that all of the services implement by using the interface
IMyService.cs
interface IMyService
{
void MyMethod(string filter);
}
MyWebServiceImplementation.cs
public class MyWebServiceImplementation : IMyService
{
public void MyMethod(string filter);
}
MySecondWebServiceImplementation.cs
public class MySecondWebServiceImplementation : IMyService
{
public void MyMethod(string filter);
}
MyImplemetationCode.cs
//Use different services from same variable
IMyService service = new MyWebServiceImplementation();
service.MyMethod("filter");
service = new MySecondWebServiceImplementation();
service.MyMethod("another filter");

TDD the WCF service class itself first

So I started to create TDD tests for a new WCF service I wanted to create. In TDD, you create the test, and start adding objects that don't exist yet into your tests. First object I wanted to test was that the service is not null after instantiated.
Then then I said wait, how the hell can you do that in WCF...a service extension is .svc. Yes there's a .svc.cs but the main parent is .svc. I don't see a way I can to TDD on this part where you've have something like this but it'd create an .svc instead of just a .cs:
[TestMethod]
public void UponInitialization_ServiceIsNotNull()
{
// Arrange
// Act
NyNewService service = new MyNewService();
// Assert
Assert.IsTrue(service != null);
}
This is a very fundamental necessary first test, testing the very simplest possible from the start...this is very common on any TDD or XP team doing TDD.
Any thoughts on how I can create a new .svc from within my test here? not a plain .cs?
I'd start with creating acceptance test for non-existing WCF service:
private Uri _baseAddress = new Uri("http://localhost:8713/service1");
private IService1 _client;
[SetUp]
public void Setup()
{
var binding = new BasicHttpBinding();
var endpoint = new EndpointAddress(_baseAddress);
var factory = new ChannelFactory<IService1>(binding, endpoint);
_client = factory.CreateChannel();
}
[TearDown]
public void TearDown()
{
if (_client != null)
((ICommunicationObject)_client).Close();
}
[Test]
public void ShouldReturnSampleData()
{
Assert.That(_client.GetData(42), Is.EqualTo("You entered: 42"));
}
Keep in mind, that nothing is created yet - we start from test. Now you can create service interface:
public interface IService1
{
string GetData(int value);
}
Test now compiles, but of course, it fails with error
Attempted to get contract type for IService1, but that type is not a
ServiceContract, nor does it inherit a ServiceContract.
Good, that's because we should mark our interface with [ServiceContract] attribute. We add this attribute and run test again:
Method GetData is not supported on this proxy, this can happen if the
method is not marked with OperationContractAttribute or if the
interface type is not marked with ServiceContractAttribute.
Ok, mark our service interface with required attributes:
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
Now we see another error (because nothing is actually running our non-existing service)
There was no endpoint listening at http://localhost:8713/service1 that
could accept the message. This is often caused by an incorrect address
or SOAP action. See InnerException, if present, for more details.
We can use ServiceHost to run our service (at this moment we need to create service class to compile tests):
private ServiceHost _host;
[SetUp]
public void Setup()
{
_host = new ServiceHost(typeof(Service1), _baseAddress);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
_host.Description.Behaviors.Add(smb);
_host.Open();
// creating client as above
}
[TearDown]
public void TearDown()
{
// closing client as above
if (_host != null)
_host.Close();
}
You also need to implement IService1 interface by service class (otherwise test will fail):
public class Service1 : IService1
{
public string GetData(int value)
{
throw new NotImplementedException();
}
}
Now I'd created some unit-tests for Service1 class in order to implement GetData functionality. With these tests passing you will have acceptance test passing also. Thats it. You did test first, and your WCF service is completely ready to be hosted.

Getting the WCF SessionID in the Client

I am writing a WCF client and am using a ChannelFactory to create my proxy to my Service:
[ServiceContract]
interface Service {
[OperationContract]
void Operation();
}
var proxy = ChannelFactory<MyServiceInterface>.CreateChannel(
new BasicHttpBinding(),
new EndpointAddress("http://localhost:8000/"));
How would I go about getting the SessionID? The proxy only has the basic Object methods as well as the ones defined in MyServiceInterface.
Thank you in advance.
Try this:
In your WCF Service file (.svc) add the following:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service1 : IService1
{
public string SessionId()
{
return OperationContext.Current.SessionId;
}
}
In your WCF Service interface add the following:
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IService1
{
[OperationContract]
string SessionId();
}
In your client, do the following:
ChannelFactory<IService1> factory = new ChannelFactory<IService1>(
new WSHttpBinding(), new EndpointAddress("http://localhost:4213/Service1.svc"));
IService1 proxy = factory.CreateChannel();
Console.WriteLine(proxy.SessionId());
((IClientChannel)proxy).Close();
factory.Close();
Console.Read();
By doing this you can get the proxy session created at service side. Just to know, when ((IClientChannel)proxy).Close(); and factory.Close(); were invoked, then proxy will get new session.
It wasn't what I was looking for to make the SessionId() an OperationContract. If, instead of using the ChannelFactory, I created my own proxy by extending ClientBase<>, and that gave me access to the InnerChannel.SessionId property.

using ninject with a remoting server

I have a class Server that implements interface IServer that is accessible using .net remoting (i have no chioce on the matter JICYAW).
internally this server uses other classes to implement logic and data access.
this server class has constructor injected dependencies that it needs to do its job.
when a client calls in (per call) the remoting framework will instatiate a Server instance using a parameterless constructor and not (of course) using Ninject.
how can i get Ninject to be the one in charge for new'ing up the class ?
i have seen this similar SO question but this isnt relevant for Ninject.
thanks for your help
You can create a service facade that will be called by the client. This facade will internally call your container to resolve the real service. For instance:
public class ServiceFacade : IService
{
private readonly IService service;
// default constructor
public ServiceFacade()
{
this.service = YourContainer.Current.Resolve<IService>();
}
void IService.ServiceOperation()
{
this.service.ServiceOperation();
}
}
What might work is to intercept the calls to those objects using a proxy and forward the calls to the real object. Note that I'm not very experienced with this, so I'm not sure if this actually works, but here goes:
public class DependencyInjectionProxy : RealProxy
{
private object realInstance;
public DependencyInjectionProxy(Type classToProxy,
object realInstance) : base(classToProxy)
{
this.realInstance = realInstance;
}
public static T MakeProxy<T>(T realInstance)
{
return (T)(new DependencyInjectionProxy(typeof(T),
realInstance).GetTransparentProxy());
}
public override IMessage Invoke(IMessage msg)
{
if (msg is IMethodCallMessage)
{
var message = (IMethodCallMessage)msg;
object value = message.MethodBase.Invoke(
this.realInstance, message.Args);
Console.WriteLine(value);
return new ReturnMessage(value, null, 0, null, message);
}
return msg;
}
}
This works when you do something like this:
var container = new YourContainer();
container.RegisterSingle<IService, Service>();
IService proxy = DependencyInjectionProxy.MakeProxy<IService>(
container.Resolve<IService>());
proxy.SomeMethod();
This works great, but to be honest, I have no idea how to configure this in a way that you can intercept incoming calls this way. Somewhere you need to register your DependencyInjectionProxy, but that's where my experience with remoting stops :-)

Dependency Injection wcf

I want inject a implementation of my Interface in the WCF but I want initialize my container of Dependency Injection in the Client of the WCF. So I can have a different implementation for each client of the my service.
When you use svcutil.exe or the Add Service Reference wizard in Visual Studio, one of the many types auto-generated will be a client interface. Let's call it IMyService. There will also be another auto-generated interface called something like IMyServiceChannel that implements IMyService and IDisposable. Use this abstraction in the rest of your client application.
Since you want to be able to create a new channel and close it again, you can introduce an Abstract Factory:
public interface IMyServiceFactory
{
IMyServiceChannel CreateChannel();
}
In the rest of your client application, you can take a dependency on IMyServiceFactory:
public class MyClient
{
private readonly IMyServiceFactory factory;
public MyClient(IMyServiceFactory factory)
{
if (factory == null)
{
throw new ArgumentNullException("factory");
}
this.factory = factory;
}
// Use the WCF proxy
public string Foo(string bar)
{
using(var proxy = this.factory.CreateChannel())
{
return proxy.Foo(bar);
}
}
}
You can create a concrete implementation of IMyServiceFactory that wraps WCF's ChannelFactory<T> as an implementation:
public MyServiceFactory : IMyServiceFactory
{
public IMServiceChannel CreateChannel()
{
return new ChannelFactory<IMyServiceChannel>().CreateChannel();
}
}
You can now configure your DI Container by mapping IMyServiceFactory to MyServiceFactory. Here's how it's done in Castle Windsor:
container.Register(Component
.For<IMyServiceFactory>()
.ImplementedBy<MyServiceFactory>());
Bonus info: Here's how to wire up a WCF service with a DI Container.
Here is what I understand from your question:
You have an interface that is not related to WCF. Let's call it IInterface
You have a WCF client that used a service. Let's call the service contract: IService
you want the ServiceClient class that by default implements the IService when you add a service reference also to implement IInterface.
IF this is the case, you can use the fact that the ServiceClient class is marked as partial.
Just make another partial declaration for ServiceClient and add the interface you need (You have to make sure that the namespaces are equal for the auto-generated code and your code). It should look somthing like:
namespace [ServiceClient Namespace]
{
public partial class ServiceClient : IInterface
{
}
}
Hope it helped.

Categories