Disposing/Cleaning up web service proxies - c#

What is the best practise for Disposing/Cleaning up a web service proxy instance after synchronous usage?
How does the answer differ if the proxy class is derived from SoapHttpClientProtocol versus ClientBase<T>?
Background
I'm trying to figure out why one of my WCF web services sometimes seems to get into a state where it no longer reponds to service calls. Basically it seems like it hangs and for now I don't really have any hard data to figure out what's going on when this occurrs.
One thing that I suspect might be an issue is the fact that this WCF service is itself doing web service calls to a few other services. These other services are called (synchronously) using proxies that are derived from SoapHttpClientProtocol (made using wsdl.exe) and at this time these proxy instances are left to be cleaned up by the finalizer:
...
var testProxy = new TestServiceProxy();
var repsonse = testProxy.CallTest("foo");
// process the reponse
...
So should I simply wrap these up in a using(...) { ... } block?
...
using(var testProxy = new TestServiceProxy())
{
var repsonse = testProxy.CallTest("foo");
// process the reponse
}
...
What if I were to change these proxy classes to be based on ClientBase<T> by recreating them using svcutil.exe? Based on my research so far, it seems the Dipose() method of classes derived from ClientBase<T> will internally call the Close() method of the class and this method might in turn throw exceptions. So wrapping a proxy based on ClientBase<T> in a Using() is not always safe.
So to reiterate the question(s):
How should I clean up my web service proxy after using it when the proxy is based on SoapHttpClientProtocol?
How should I clean up my web service proxy after using it when the proxy is based on ClientBase<T>?

Based on my best efforts to find the answer to this question, I'd say that for SoapHttpClientProtocol based proxies (regular .asmx web service proxies) the correct way is to simly wrap it in using():
using(var testProxy = new TestAsmxServiceProxy())
{
var response = testProxy.CallTest("foo");
// process the reponse
}
For proxies based on ClientBase<T> (WCF proxies) the answer is that it should not be wrapped in a using() statement. Instead the following pattern should be used (msdn reference):
var client = new TestWcfServiceProxy();
try
{
var response = client.CallTest("foo");
client.Close();
// process the response
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}

Related

Should I use the Using statement with HttpClient?

I’m creating an API that serves as the bridge between the app and 2 other APIs. I want to know if what is the best way to do this. I’m using HttpClient. The app has almost a thousand users.
I read this article https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/. Should I really not use the using statement? Also I am doing synchronous api calls. Does this have any effect? Is what I did efficient?
Here is my code:
[HttpGet]
[Route("api/apiname")]
public String GetNumberofP([FromUri]GetNumberofPRequest getNPRequest){
var request = JsonConvert.SerializeObject(getNPRequest);
string errorMessage = "";
try{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.gettoken());
var response = httpClient.GetAsync("api/MobileApp/GetNumberP?"
+ "strCardNumber=" + getNPRequest.strCardNumber
+ "&strDateOfBirth=" + getNPRequest.strDateOfBirth).Result;
return response;
}
catch (Exception e){
throw utils.ReturnException("GetNumberofP", e, errorMessage);
}
}
HttpClient does not need to be disposed and you should hold on to it to reuse it later.
One thing you can use (from the thread you linked):
You just provide your HttpClient factory and dispose methods and the
LimitedPool does the rest:
_httpClientPool = new LimitedPool<httpclient>(
CreateHttpClient, client => client.Dispose(), HttpClientLifetime);
using (var httpClientContainer = _httpClientPool.Get())
{ ... use httpClientContainer.Value ... }
When httpClientContainer is disposed, the HttpClient is actually returned back to the pool for other threads to use. When
lifetime is reached next dispose will eventually call the Dispose
method.
See code here
Alternative for .Net Core
Implement it as described in this document.
The IHttpClientFactory can be registered by calling the AddHttpClient extension method on the IServiceCollection, inside the Startup.ConfigureServices method.
services.AddHttpClient();
Once registered, code can accept an IHttpClientFactory anywhere services can be injected with dependency injection (DI). The IHttpClientFactory can be used to create a HttpClient instance:
public MyConstructor(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public async Task OnGet()
{
....
var client = _clientFactory.CreateClient();
var response = await client.SendAsync(request);
...
}
No need to use using().
If you are using asp.net core the right way to use HttpClient is explained in this article from Microsoft:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2#typed-clients
I usually use the typed client approach explained in the article.
This basically means that I delegate to the asp.net core container the injection of the http client in my class (a controller class, a service, a filter, whatever)
Doing so you can safely modify the http client in your class by adding all the request headers you need (you usually do it inside the constructor of your class).
You do not have to call dispose on the injected http client, you simply use it.
The asp.net core container will manage the http client lifetime for you and the pool of resources used by http client instances so that your app do not leak resources. All of this happens automatically.
Do not use sync calls. Make your action method async, and await on async methods of http client. Asp.net core fully support async code and make blocking requests does not make sense, doing so you will limit the scalability of your app.

How do you consume WCF services from a console app using Autofac?

So I have a console application in which I am using Autofac.
I have set up my console application as follows:
I have a class I call ContainerConfig - In this I have all my builder registrations:
public static class ContainerConfig
{
public static IContainer Configure()
{
var builder = new ContainerBuilder();
builder.Register(c => new MatchRun()).As<MatchRun>).SingleInstance();
builder.RegisterType<AuditLogic>().As<IAuditLogic>();
builder.RegisterType<AuditRepository>().As<IAuditRepository>();
builder.RegisterType<ValidationLogic>().As<IValidationLogic>();
return builder.Build();
}
}
I call my main applcation as follows:
private static void Main(string[] args)
{
var container = ContainerConfig.Configure();
using (var scope = container.BeginLifetimeScope())
{
var app = scope.Resolve<IApplication>();
app.Run(args);
}
}
The issue is that I have a connected WCF service. This is my AuditRepository. (FYI - I have not touched WCF for years so I have forgotten most of what I knew).
Its currently constructed to create and dispose of the the proxy each time I make a call to that client. This functions - mostly.
Looks like this:
public string GetStuff(string itemA, string itemB)
{
try
{
GetProxy();
return _expNsProxy.GetStuff(itemA, itemb);
}
catch (Exception ex)
{
IMLogger.Error(ex, ex.Message);
throw ex;
}
finally
{
// CloseProxyConn();
}
}
What i am wondering is can I do this better with Autofac - creating a single instance vs the constant open close - or am I just totally crazy? I know I am not fully asking this the right way - not 100% sure how to actually word the question.
Thanks
The approach to always create a new proxy and close it after each call is good for WCF.
Otherwise you can run into issues. For example if one service call fails the channel created by the proxy goes into a faulted state and you can not do more calls on it just abort it. Then you need to create a new proxy. Also you can have threading issues if you call the same proxy from multiple threads simultaneously.
Check also this documentation with a sample of how to handle errors correctly when calling WCF services.
There is an Autofac.Wcf package that can help you with the creation and freeing of channels. Check the documentation here. It uses the dynamic client generation approach where you just give the interface of your WCF service and it generates the channel based on the interface. This is a bit more low level approach so you will have to understand more what is going on. The generated client class does this for you in the background.
You need two registrations one for the channel factory that is a singleton:
builder
.Register(c => new ChannelFactory<IYourWcfService>(
new BasicHttpBinding(), // here you will have to configure the binding correctly
new EndpointAddress("http://localhost/YourWcfService.svc")))
.SingleInstance();
And a factory registration that will create the channel from the factory every time you request the service:
builder
.Register(c => c.Resolve<ChannelFactory<IYourWcfService>>().CreateChannel())
.As<IIYourWcfService>()
.UseWcfSafeRelease();

Calling service from self host

I have a very complex scenario in which my services are dynamically loaded and everything is done programmatically. In particular I have a service that has 2 endpoints
net.pip://localhost/test
net.pipe://localhost/test/mex
I have a client that access this without issue as well as the WCF Test Client tool.
I am trying to access the service from the selfhost wrapper. I have read you just treat it as a client and create a factory and channel but something is preventing this from working. The same code that works on the client will not work in the wrapper. The code just
private IAgentBase GetLocalClient(string serviceEndpointName)
{
var factory = new ChannelFactory<IAgentBase>(serviceEndpointName);
return factory.CreateChannel();
}
This does return a proxy and then I call a method on the service...
var proxy = GetLocalClient("net.pipe://localhost/test");
proxy.DoThis();
But the code just goes someplace - keeps running and no error. The statement never completes. When I step over that line or set a BP or a try catch, it never completes the method call
Change your GetLocalClient to the following
public IAgentBase GetlocalClient(string ed)
{
EndpointAddress edi = new EndpointAddress(ed);
var channel = ChannelFactory<IAgentBase>.CreateChannel(new NetNamedPipeBinding(), edi);
return channel;
}

Disposing of a WCF client instantiated via an interface [duplicate]

This question already has answers here:
What is the best workaround for the WCF client `using` block issue?
(26 answers)
Closed 8 years ago.
I would like some clarity around the following (apologies in advance if this is a stupid question)
Am working on some existing code which calls a WCF service.
This code instantiates a WCF service client via an interface and performs the operations it needs i.e.:
IWCFService proxyClient = new WCFServiceClient()
However what am trying to do here is ensure the connection is closed gracefully i.e.: proxyClient.Close() etc but I cant access these seeing as its created via an interface (which just houses the operations i.e.: DoSomething())
If i instantiate as a WCF service client (and not via interface) i will be able to access the Close() & Abort calls which i can use in try{}catch{} blocks.
i.e.:
WCFServiceClient proxyClient = new WCFServiceClient()
//do some stuff..
proxyClient.Close()
Is it a simple case of adding Close() & Abort() to the interface definition and then calling these in the code which should in turn implement the WCF implementations of these?
I recently wrote an article about the correct handling of a WCF client's life cycle: Only wrapping the instantiation in a using block is not sufficient...
Have a look at http://blog.rsuter.com/?p=975
Summary: Overload Dispose the following way to use the client with the using keyword:
public void Dispose()
{
if (isDisposed)
return;
try
{
if (service.State == CommunicationState.Faulted)
service.Abort();
else
{
try
{
service.Close();
}
catch (Exception closeException)
{
try
{
service.Abort();
}
catch (Exception abortException)
{
throw new AggregateException(closeException, abortException);
}
throw;
}
}
}
finally
{
isDisposed = true;
}
}

Is it possible to track all outgoing WCF call?

Our application calls external services like
//in client factory
FooServiceClient client = new FooServiceClient(binding, endpointAddress);
//in application code
client.BarMethod(); //or other methods
Is it possible to track all of these calls (e.g by events or something like that) so that the application can collect the statistics like number of call, response time, etc? Note that my application itself needs to access the values, not only to write to a log file.
What I can think is to create a subclass of VisualStudio-generated FooServiceClient and then add codes like this
override void BarMethod()
{
RaiseStart("BarMethod");
base.BarMethod();
RaiseEnd("BarMethod);
}
and the RaiseStart and RaiseEnd method will raise events that will be listened by my code.
But this seems tedious (because there are a lot of methods to override) and there is a lot of repeated codes, my code needs to change everytime the service contract changes, etc. Is there a simpler way to achieve this, for example by using reflection to create the subclass or by tapping into a built-in method in WCF, if any?
The first thing I would look at is to see if the counters available in your server's Performance Monitor can provide you with the kind of feedback you need. There's built in counters for a variety of metrics for ServiceModel Endpoints, Operations and Services. Here is some more info http://msdn.microsoft.com/en-us/library/ms735098.aspx
You could try building an implementation of IClientMessageInspector, which has a method to be called before the request is sent and when the reply is received. You can inspect the message, make logs etc in these methods.
You provide an implementation of IEndpointBehavior which applies your message inspector, and then add the endpoint behavior to your proxy client instance.
client.Endpoint.Behaviors.Add(new MyEndpointBehavior())
Check out the docs for MessageInspectors and EndpointBehaviors, there are many different ways of applying them (attributes, code, endpoint xml config), I can't remember of the top of my head which apply to which, as there also IServiceBehavior and IContractBehavior. I do know for sure that the endpoint behaviors can be added to the client proxy collection though.
I found a simple way to do it by using dynamic proxy, for example Castle's Dynamic Proxy.
Firstly, use a factory method to generate your client object
IFooClient GetClient()
{
FooClient client = new FooClient(); //or new FooClient(binding, endpointAddress); if you want
ProxyGenerator pg = new ProxyGenerator();
return pg.CreateInterfaceProxyWithTarget<IFoo>(client, new WcfCallInterceptor());
}
And define the interceptor
internal class WcfCallInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
RaiseStart(invocation.Method.Name);
invocation.Proceed();
}
finally
{
RaiseEnd(invocation.Method.Name);
}
}
//you can define your implementation for RaiseStart and RaiseEnd
}
I can also change the intercept method as I wish, for example I can add a catch block to call a different handler in case the method throw exception, etc.

Categories

Resources