Need a way to close a ChannelFactory when the client only know of the interface - wcf

please help me solve this issue.
I have a client using WCF. I don't want this client to know that it gets its data from a service. I want to use a model like this so I it easier for me to unit test the code and to later replace the implementation of the given interface. The problem with this model is that I'm not able to call close on the ChannelFactory. I'm not sure that I need to call close, but it feels right.
So my question is:
Does anybody know of a good pattern for closing the ChannelFactory when the client only should know the interface of the service? Or is the ChannelFactory closed by it self by some kind of magic?
Below is some sample code that I hope will you understand the question:
static void Main(string[] args)
{
ITestService service = GetTestService();
Console.WriteLine(service.GetData(42));
}
private static ITestService GetTestService()
{
var cf = new ChannelFactory<ITestService>(new WSHttpBinding(), new EndpointAddress("http://localhost:8731/TestService/"));
return cf.CreateChannel();
}
Thanks,
GAT

The best way to solve this is to keep the reference to the ChannelFactory alive for as long as you need it. So take the creation of the ChannelFactory out of the GetTestService method and create the factory on initialization of your class (in the constructor for example) and close it when you no longer need the factory (in the Dispose method of your class for example).
ChannelFactory is a factory class that you can reuse as many times as you like, so there is no need to create it each time you need a service implementation.

You should implement class like
public class MyClient : ITestService
{
private ChannelFactory<ITestService> factory;
private ITestService proxy;
//...
//expose here methods Open and Close that internally will open and close channel factory
//implement interface members
}
The lifetime of the client here will be the same as lifetime of channel factory.

Have you tried casting it to a IClientChannel and then calling Close?
((IClientChannel)service).Close();

Related

C#- Using IClientChannel interface without implementing all methods, and/or without casting in a messy manner

Software Environment Details:
-Visual Studio 2017
-.NET Framework 4.5
We have a WCF Service and WCF Client Library C# library.
In order to adhere to proper coding practices, I want the WCFService that I'm coding to also implement the System.ServiceModel.IClientChannel interface.
However, if my WCF Service classes implements the System.ServiceModel.IClientChannel interface then I have to implement a whole bunch of methods that I don't need to use.
However, I am only interested in using
IClientChannel.Close();
and
IClientChannel.Abort();
I could resort to coding:
((IClientChannel)blahblahWcfChannel).Close()
((IClientChannel)blahblahWcfChannel).Abort()
However, invoking the aforementioned casting code looks messy.
Therefore, could someone please show me code that will allow me to invoke the IClientChannel Close() and/or Abort() , but without having to implement all the methods within the System.ServiceModel.IClientChannel interface
and/or resorting to the messy casting?
There is no ability to not implement a required method from an interface. No way around that.
You can just add a stub function to cover the requirement that just calls this line:
throw new NotImplementedException();
That way in the future if someone tries to use that function not knowing that it was never fleshed out then they'll know it needs to be written still.
#CarCar We want the WCF Service implementation class code to implement IClientChannel’s Abort() and Close() functionality withOut having to implement all the other methods of the IClientChannel interface. It’s better coding practice to ensure that references to WCF Service are closed off after we finish using it.
Therefore, The following 2 interfaces were created:
public interface IProjectWCFService : IServiceContract, IClientChannel
The WCF Service logic is within the WcfService class:
public class WcfService : IServiceContract
Within the WcfService class, we have implementations for Abort() and Close() methods like so:
public void Close()
{
((IClientChannel)this).Close();
}
public void Dispose()
{
this.Close();
}
public void Abort()
{
((IClientChannel)this).Abort();
}
Within the code, we can bind the IProjectWCFService interface to the WcfService class
We create the WCF Service url End Point Address string that ends with $"{nameof(WcfService)}.svc" , and then
using the System.ServiceModel. ChannelFactory < TChannel > (Binding binding, EndpointAddress remoteAddress) API,
we can bind the IProjectWCFService interface to the WcfService class ( i.e.
new ChannelFactory < IProjectWCFService > (blablahBindingblahblah, http://blahblah/ WcfService.svc)
)
With the aforementioned programming technique, implement IClientChannel’s Abort() and Close() functionality withOut having to implement all the other methods of the IClientChannel interface

How to receive IHubContext out of Dependency Injected classes?

I want to send message from Service A using SignalR when some event occures (for example, message from Service B received).
So hub method needs to be called from some sort of handler, that not constructed using Dependency Injection. How I can do this?
So far, I tried and read about the following things:
I can inject context into Controller and lead it to my handler. I probably can do that, but passing hub context from the top (controller class) to the bottom (handler class) is not the best approach, which adds a lot of dependencies to the classes that should not be aware of this context, so I would like to avoid that.
I can inject my IHubContext in "any" class, but then, the thing is, how to get an instance of that class on my handler?
Add Static method to class with injected context!? Well, that works until you have 1 client because with new client static property is going to be overwritten.
So I cannot imagine, how handler can use dependency injected IHubContext.
Probably, someone did that before and have an example of how to truly inject context into any class.
Thank you in advance and any additional information will be provided, if necessary.
Answer 1
Here is one possible solution. Implement a factory pattern. Create a factory that knows how to create your handler. Inject the IHubContext in the factory. You can use a few approaches that way:
Construct the Handler by passing in the IHubContext
Create a public property in the Handler and set the IHubContext
Create a method in the Handler and pass the IHubContext as a parameter
You can decide whichever approach suits you. Inject that factory in the controller via DI, and get the handler using the factory method. That way you are not exposing the IHubContext. Please see the code below
public interface IHandlerFactory
{
Handler CreateHandler();
}
public class HandlerFactory : IHandlerFactory
{
private IHubContext _hubContext;
public HandlerFactory(IHubContext context)
{
_hubContext = context;
}
public Handler CreateHandler()
{
return new Handler(param1, param2, _context);
}
}
Then in the entry point, controller/service, inject the factory via DI
public class MyController : Controller
{
private Handler _handler;
public MyController(IHandlerFactory factory)
{
_handler = factory.CreateHandler();
}
}
Then you can use that _handler in the other methods. I hope this helps.
Answer 2
Another possible solution is to use IHostedService if it's possible at all for you. Please see a solution to a GitHub issue, provided by David Fowler here, that I think somewhat relevant to your scenario.

Register WCF proxy wrapper using Unity

I am trying to consume WCF in my MVC web app. I have implemented the channel factory for instantiating the proxy client.
I am stuck at a point. Here is the code highlight -
I created a proxy base class where i am creating the channel :
public abstract class ServiceProxyBase<T> : IDisposable where T : class
For creating teh proxy wrapper class i have inherited this base class as :
public class ProxyWrapper : ServiceProxyBase<IMyService>,IMyService
Here "IMyService" is the WCf contract.
Now, in the controllers i have added overloaded constructors as :
public class AccountController : Controller
{
private IMyService businessService;
public AccountController(IMyService _businessService)
{
this.businessService = _businessService;
}
}
For injecting dependency I have included unity.mvc4 package.
It works fine when I am using the following code :
container.RegisterType<IMyService, ProxyWrapper>();
This works as long as the ProxyWrapper is inheriting the IMyService interface directly. If i remove the inheritance like
public class ProxyWrapper : ServiceProxyBase<IMyService>
it gives an error while registering type.
I would like to have a way without inherting the contract in the proxy wrapper. I have spent almost a day trying to fix this. But am able to figure out a solution.
Please give your valuable suggestions on this.
If I understand correctly, your application is using a WCF service but the functionality your application needs is limited compared to the functionality that the service offers (it contains more methods than you need). According to the Interface Segregation Principle, "no client should be forced to depend on methods it does not use" and the Dependency Inversion Principle states that clients own the abstraction.
In other words, you should define your own interface that the application should use and define an implementation that wraps (i.e. composition over inheritance) the generated WCF proxy class.
For instance:
public interface IMyApplicationService
{
object GetStuff();
void PutStuff(object instance);
}
public class MyServiceApplicationProxy : IMyApplicationService
{
private readonly ProxyWrapper wcfProxy;
public MyServiceApplicationProxy(ProxyWrapper wcfProxy) {
this.wcfProxy = wcfProxy;
}
public object GetStuff() {
return this.wcfProxy.GetStuff();
}
public void PutStuff(object instance) {
this.wcfProxy.PutStuff(instance);
}
}
To make application development easier, makes your code easier to read, maintain and test.
You might even want to change the methods of your interface to better suit your application needs. Remember: the client defines the interface! So that might mean that you need to do more mapping inside the MyServiceApplicationProxy class to map adapt your core domain to the contract of the external web service. Don't let the external WCF service's contract leak into your core domain.

New function added in WCF service is not reflecting on adding the web reference

I am trying to add a web reference to a WCF service. On browsing to that service through the project explorer, the new function added to that service is not getting listed.
This is my code in the *.svc file
public class Service1 : IService1
{
public string GetData(int value){;}
public CompositeType GetDataUsingDataContract(CompositeType composite){;}
public double Undo(double value, bool isPound){;}
}
Now, while referencing my service as UndoService, my Undo method is not showing up. The following show up by intellisense:
(class) CompositeType
(interface) Service1
(interface) Service1Channel
(class) Service1Client
This might be a naive question, but I am not able to proceed. I probably am missing something big here. Please help!
The Service1Client is your proxy class and have to instantiate that class to invoke the service methods.
var proxy = new Service1Client();
proxy.Undo(..)
You need to update the reference if you have added new functionality. You can do this by right clicking the existing reference entry and selecting update, this will download the updated service contract.
You most likely forgot to either add the method to your contract interface or to decorate the contract method with the [Operationcontract] attribute.
EDIT : I kinda misread the question, apply Mark answer before anything.

Extension methods in a data contract

Can we two WCF services where one service contract derives from another and have an extension method inside the derived contract. what will be the result of accessing this contract from the WCF Client. I.e. what will happen if IDServiceis accessed
E.g.
[ServiceContract]
public interface IBaseService
{
public void A();
...
}
[ServiceContract]
public interface IDService: IBaseService
{
public static void B(this IBaseService S);
....
}
You can't define static methods in an interface (nor the access modifier public which you've specified above either).
A good question - got me to a lot of head scratching.
Extension method is meaningless to WCF - and WSDL for that matter.
If you use Service Reference to generated the client, you would not see the extension method (since WSDL would not know anything about the extension method) so you cannot use it.
If you use DLL/Project reference, your code will be called locally and not through the proxy.