Is it possible to somehow invoke inline try statement in C#?
I'm detecting languages for my website and sometimes, when language is something like en-GR on client side for some reason .NET throws exception. So I need to use try and also catch even though I'm not really catching anything.
It just seems as a total overkill in this situation.
// Set allowed languages
string[] allowedLanguages = { "en", "fr", "ru" };
// Get all possible values
var routeLanguage = (filterContext.RouteData.Values["lang"] != null && allowedLanguages.Contains(filterContext.RouteData.Values["lang"].ToString())) ? filterContext.RouteData.Values["lang"].ToString() : null;
var cookieLanguage = (filterContext.HttpContext.Request.Cookies["lang"] != null && allowedLanguages.Contains(filterContext.HttpContext.Request.Cookies["lang"].Value)) ? filterContext.HttpContext.Request.Cookies["lang"].Value : null;
string clientLanguage = null;
try
{
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; // Exception sometimes without `try`
}
catch (Exception)
{
}
Edit
Exception is not something I can fix since I have no control over what user has in his culture info. .NET just sees en-FR as invalid one.
First off, it is always better to figure out how to avoid the exception in the first place. Concentrate on that first. There is some reason why that exception is being thrown, and if you can determine what it is, then don't do that.
To actually answer your question: there is no out-of-the-box "eat all the exceptions in this expression" mechanism, but building your own is straightforward:
static T EatExceptions(Func<T> func)
{
try { return func(); } catch { }
return default(T);
}
...
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ?
EatExceptions(() => new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName) :
null; }
If someone tried to pull shenanigans like that in code I was reviewing then I would... well let's just say that the change would not get checked in. Eating exceptions like this is a very bad idea 99% of the time. Again: figure out what you are doing wrong and stop doing it. Don't do something wrong and then handle the failure.
Have you tried getting rid of the try/catch statement completely?
string clientLanguage = null;
var userLanguages = filterContext.HttpContext.Request.UserLanguages;
if (userLanguages != null && userLanguages.Length > 0)
{
var culture = CultureInfo
.GetCultures(CultureTypes.AllCultures)
.FirstOrDefault(
x => string.Equals(
x.Name,
userLanguages[0].Name,
StringComparison.OrdinalIgnoreCase
)
);
if (culture != null)
{
clientLanguage = culture.TwoLetterISOLanguageName;
}
}
Use try/catch only for handling exceptions that are out of your control. As their name suggests exceptions should be used for handling exceptional cases.
In this case you are doing standard parsing so it is much better to do defensive programming instead of trying, throwing, catching, ...
_.Try(() => __YourStatementHere__ );
Using a little helper class like this:
/// <summary>
/// Other utility functions.
/// </summary>
public static class _ {
/// <summary>
/// Tries to execute the given action. If it fails, nothing happens.
/// </summary>
public static void Try(Action action) {
try {
action();
}
catch {
}
}
}
I know, this solution is not optimal either, but up to now the most concise one I could find.
First try to avoid the exception. Just because the string comes from a source you don't control, doesn't mean you can't validate it.
If you can't avoid it, you should catch the specific exception you expect and encapsulate that logic in a method. Don't catch all exceptions.
For example:
public static CultureInfo TryGetCultureByName(string name)
{
try
{
return new CultureInfo(name);
}
catch(CultureNotFoundException)//Only catching CultureNotFoundException
{
return null;
}
}
That way, if you later discover a better way to handle this specific error, you can easily replace it.
For example you could create a Dictionary<string, CultureInfo>, fill it from CultureInfo.GetCultures() and use TryGetValue to look up a culture without ever throwing an exception.
What you did is the right way to do it. You stated, why you cannot get rid of the exception (and I assume this is the case). So you have to handle it. Alas, C# does not have a try-catch as an expression (not sure how that would work - the catch "clause" would need to return a value).
Alternatively you can build a little helper function that takes a Func<T>, invokes it and passes through the value to the caller. If an exception occurres it returns (for example) default(T). That takes away a lot of the clutter and is reusable.
Well, leaving aside the (good) advice about pre-checking, there are several rather mundane/prosaic/obvious ways to do this:
First, you could wrap it in a function. I assume that this would not be general enough for you.
Or, you could collapse the catch branch:
try
{
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; // Exception sometimes without `try`
} catch (Exception) { }
Or, you could just collapse the whole thing to a single line:
try { clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; } catch (Exception) { }
Not elegant, but simple, and it works.
This is one another way:
await new #try(async () => { user = await GetItemAsync(userId); })
.#catch<Exception>(async () => { user = new User(); });
I think it's more verbose than the try/catch:
try { return await GetItemAsync(userId); }
catch (Exception ex) { return new User(); }
The helper class:
public class #try
{
private Func<Task> func;
private Action action;
public #try(Func<Task> func)
{
this.func = func;
}
public #try(Action action)
{
this.action = action;
}
public async Task #catch<T>(Func<Task> fallback) where T : Exception
{
try
{
await func.Invoke();
}
catch(T ex)
{
await fallback.Invoke();
}
}
public void #catch<T>(Action fallback) where T : Exception
{
try
{
action.Invoke();
}
catch (T ex)
{
fallback.Invoke();
}
}
}
I've built an in-line try catch mechanic that may suit this purpose. I was going for a sort of LINQ-like or Callback function-y syntax. This is done using a couple of wrappers, a TryWrapper and a CatchWrapper so that the dot operators prompt the next steps appropriately, that implicitly cast to type of T.
You could also do something like
Try(() => UpdateSweetGreen("21", SweetGreen))
.Catch(LogToDb(e.Message))
.Catch(LogToFile(e.Message).Finally(ReportNewSweetGreen(SweetGreen);
Basically a CatchWrapper extends TryWrapper. So you could catch an exception off of another catch block. In this instance logging a failure of your method to a database, then if that fails to a file, then no matter what reporting the SweetGreen variable to some other component.
This all extends from TryWrapper
public class TryWrapper<T>
{
protected internal T Result { get; set; } = default(T);
protected internal Exception Exception { get; set; } = null;
public static implicit operator T(TryWrapper<T> wrapper)
{
return wrapper.Result;
}
public static implicit operator Exception(TryWrapper<T> wrapper)
{
return wrapper.Exception;
}
}
and CatchWrapper which simply extends TryWrapper and cannot be invoked directly, instead only appearing after a try as you'd expect with standard implementation
public class CatchWrapper<T> : TryWrapper<T>
{
}
Then a series of static extension methods
public static TryWrapper<T> Try<T>(Func<T> func)
{
var product = new TryWrapper<T>();
try
{
product.Result = func.Invoke();
}
catch (Exception e)
{
product.Exception = e;
}
return product;
}
public static TryWrapper<T> Try<T>(Action action)
{
var product = new TryWrapper<T>();
try
{
action.Invoke();
}
catch (Exception e)
{
product.Exception = e;
}
return product;
}
public static CatchWrapper<T> Catch<T>(this TryWrapper<T> wrapper, Action<Exception> response)
{
if (wrapper.Exception is null) return wrapper as CatchWrapper<T>;
response.Invoke(wrapper);
wrapper.Exception = null;
return wrapper as CatchWrapper<T>;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Action<T> response)
{
response.Invoke(wrapper);
return wrapper;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Func<T> response)
{
wrapper.Result = response.Invoke();
return wrapper;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Action response)
{
response.Invoke();
return wrapper;
}
Now this does achieve that inline syntax the OP was asking for but I'd hazard to say its a touch less efficient since you could just deal with the exception directly in a standard try-catch. Still kindof cool to be able to specify the return directly before the Try, though this is risky if defaults to null.
I have a particular situation where I need to trap exceptions and return an object to the client in place of the exception. I cannot put the exception handling logic at a higher level i.e. wrap Foo within a try clause.
It's best to demonstrate with some sample code. The exception handling logic is clouding the intention of the method and if I have, many methods of similar intent, in the Foo class, I find myself repeating most of the catch logic.
What would be the best technique to wrap the common exception functionality in the code below?
public class Foo
{
public Bar SomeMethodThatCanThrowExcepetion()
{
try
{
return new Bar().Execute();
}
catch(BazException ex)
{
WriteLogMessage(ex, Bar.ErrorCode);
return new Bar() { ErrorMessage = ex.Message, ErrorCode = Bar.ErrorCode;}
}
}
public Baz SomeMethodThatCanThrowExcepetion(SomeObject stuff)
{
try
{
return new Baz(stuff).Execute();
}
catch(BazException ex)
{
WriteLogMessage(ex, Baz.ErrorCode);
return new Baz() { ErrorMessage = ex.Message, ErrorCode = Baz.ErrorCode;}
}
}
}
Updated per Lee's comment
One possibility is to use a generic helper method. Something like this:
T TryExecute<T>(Func<T> action, int ErrorCode)
{
try
{
return action();
}
catch (Exception ex)
{
result = Activator.CreateInstance<T>();
typeof(T).GetProperty("ErrorMessage").SetValue(result, ex.Message, null);
typeof(T).GetProperty("ErrorCode").SetValue(result, ErrorCode, null);
return result;
}
return result;
}
If you can modify Bar and Baz, then you could improve this by placing a requirement on T:
public interface IError
{
public string ErrorMessage { get; set; }
public int ErrorCode { get; set; }
}
T TryExecute<T>(Func<T> action, int ErrorCode) where T : IError
{
try
{
return action();
}
catch (Exception ex)
{
result = Activator.CreateInstance<T>();
result.ErrorMessage = ex.Message;
result.ErrorCode = ErrorCode;
return result;
}
}
Then you'd use:
return TryExecute<Bar>(new Bar().Execute, Bar.ErrorCode);
And:
return TryExecute<Baz>(new Baz(stuff).Execute, Baz.ErrorCode);
That may or may not be an over-abstraction for your particular design; the devil is in the details.
How about a base class:
public class ErrorCapable {
public string ErrorMessage { set; get; }
public int ErrorCode { set; get; }
public static ErrorCapable<T> Oops(Exception exc) where T : ErrorCapable, new() {
// Code for logging error here
return new T() { ErrorMessage = exc.Message, ErrorCode = exc.ErrorCode };
}
}
public class Bar : ErrorCapable {
//...
}
public class Baz : ErrorCapable {
//...
}
Then in the catch, just use, for example:
return ErrorCapable.Oops<Bar>(ex);
Do you really need the explicit logging in every method? Instead of having the exception logic in every method, have one handler in your Main method of the program and handle the exceptions generically.
Also, you don't need to return an arbitrary object from a catch block should you really need the logging there, simply use throw; to let it wander up the stack.
I think the best you can do is something like:
public T TryOrDefault<T>(Func<T> act, int errorCode, Func<BazException, T> onError)
{
try
{
return act;
}
catch(BazException ex)
{
WriteLogMessage(ex, errorCode);
return onError(ex);
}
}
then you can write your other methods in terms of it:
public Bar SomeMethodThatCanThrowException()
{
Bar b = new Bar();
return ExecOrDefault(() => b.Execute(), Bar.ErrorCode, ex => new Bar { ErrorMessage = ex.Message, ErrorCode = Bar.ErrorCode });
}
I like instantiating my WCF service clients within a using block as it's pretty much the standard way to use resources that implement IDisposable:
using (var client = new SomeWCFServiceClient())
{
//Do something with the client
}
But, as noted in this MSDN article, wrapping a WCF client in a using block could mask any errors that result in the client being left in a faulted state (like a timeout or communication problem). Long story short, when Dispose() is called, the client's Close() method fires, but throws an error because it's in a faulted state. The original exception is then masked by the second exception. Not good.
The suggested workaround in the MSDN article is to completely avoid using a using block, and to instead instantiate your clients and use them something like this:
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
Compared to the using block, I think that's ugly. And a lot of code to write each time you need a client.
Luckily, I found a few other workarounds, such as this one on the (now defunct) IServiceOriented blog. You start with:
public delegate void UseServiceDelegate<T>(T proxy);
public static class Service<T>
{
public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>("");
public static void Use(UseServiceDelegate<T> codeBlock)
{
IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel();
bool success = false;
try
{
codeBlock((T)proxy);
proxy.Close();
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
}
Which then allows:
Service<IOrderService>.Use(orderService =>
{
orderService.PlaceOrder(request);
});
That's not bad, but I don't think it's as expressive and easily understandable as the using block.
The workaround I'm currently trying to use I first read about on blog.davidbarret.net. Basically, you override the client's Dispose() method wherever you use it. Something like:
public partial class SomeWCFServiceClient : IDisposable
{
void IDisposable.Dispose()
{
if (this.State == CommunicationState.Faulted)
{
this.Abort();
}
else
{
this.Close();
}
}
}
This appears to be able to allow the using block again without the danger of masking a faulted state exception.
So, are there any other gotchas I have to look out for using these workarounds? Has anybody come up with anything better?
Actually, although I blogged (see Luke's answer), I think this is better than my IDisposable wrapper. Typical code:
Service<IOrderService>.Use(orderService=>
{
orderService.PlaceOrder(request);
});
(edit per comments)
Since Use returns void, the easiest way to handle return values is via a captured variable:
int newOrderId = 0; // need a value for definite assignment
Service<IOrderService>.Use(orderService=>
{
newOrderId = orderService.PlaceOrder(request);
});
Console.WriteLine(newOrderId); // should be updated
Given a choice between the solution advocated by IServiceOriented.com and the solution advocated by David Barret's blog, I prefer the simplicity offered by overriding the client's Dispose() method. This allows me to continue to use the using() statement as one would expect with a disposable object. However, as #Brian pointed out, this solution contains a race condition in that the State might not be faulted when it is checked but could be by the time Close() is called, in which case the CommunicationException still occurs.
So, to get around this, I've employed a solution that mixes the best of both worlds.
void IDisposable.Dispose()
{
bool success = false;
try
{
if (State != CommunicationState.Faulted)
{
Close();
success = true;
}
}
finally
{
if (!success)
Abort();
}
}
I wrote a higher order function to make it work right. We've used this in several projects and it seems to work great. This is how things should have been done from the start, without the "using" paradigm or so on.
TReturn UseService<TChannel, TReturn>(Func<TChannel, TReturn> code)
{
var chanFactory = GetCachedFactory<TChannel>();
TChannel channel = chanFactory.CreateChannel();
bool error = true;
try {
TReturn result = code(channel);
((IClientChannel)channel).Close();
error = false;
return result;
}
finally {
if (error) {
((IClientChannel)channel).Abort();
}
}
}
You can make calls like this:
int a = 1;
int b = 2;
int sum = UseService((ICalculator calc) => calc.Add(a, b));
Console.WriteLine(sum);
This is pretty much just like you have in your example. In some projects, we write strongly typed helper methods, so we end up writing things like "Wcf.UseFooService(f=>f...)".
I find it quite elegant, all things considered. Is there a particular problem you encountered?
This allows other nifty features to be plugged in. For instance, on one site, the site authenticates to the service on behalf of the logged in user. (The site has no credentials by itself.) By writing our own "UseService" method helper, we can configure the channel factory the way we want, etc. We're also not bound to using the generated proxies -- any interface will do.
This is Microsoft's recommended way to handle WCF client calls:
For more detail see: Expected Exceptions
try
{
...
double result = client.Add(value1, value2);
...
client.Close();
}
catch (TimeoutException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
catch (CommunicationException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
Additional information
So many people seem to be asking this question on WCF that Microsoft even created a dedicated sample to demonstrate how to handle exceptions:
c:\WF_WCF_Samples\WCF\Basic\Client\ExpectedExceptions\CS\client
Download the sample:
C# or VB
Considering that there are so many issues involving the using statement, (heated?) Internal discussions and threads on this issue, I'm not going to waste my time trying to become a code cowboy and find a cleaner way. I'll just suck it up, and implement WCF clients this verbose (yet trusted) way for my server applications.
Optional Additional Failures to catch
Many exceptions derive from CommunicationException and I don't think most of those exceptions should be retried. I drudged through each exception on MSDN and found a short list of retry-able exceptions (in addition to TimeOutException above). Do let me know if I missed an exception that should be retried.
// The following is typically thrown on the client when a channel is terminated due to the server closing the connection.
catch (ChannelTerminatedException cte)
{
secureSecretService.Abort();
// todo: Implement delay (backoff) and retry
}
// The following is thrown when a remote endpoint could not be found or reached. The endpoint may not be found or
// reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable.
catch (EndpointNotFoundException enfe)
{
secureSecretService.Abort();
// todo: Implement delay (backoff) and retry
}
// The following exception that is thrown when a server is too busy to accept a message.
catch (ServerTooBusyException stbe)
{
secureSecretService.Abort();
// todo: Implement delay (backoff) and retry
}
Admittedly, this is a bit of mundane code to write. I currently prefer this answer, and don't see any "hacks" in that code that may cause issues down the road.
I've finally found some solid steps towards a clean solution to this problem.
This custom tool extends WCFProxyGenerator to provide an exception handling proxy. It generates an additional proxy called ExceptionHandlingProxy<T> which inherits ExceptionHandlingProxyBase<T> - the latter of which implements the meat of the proxy's functionality. The result is that you can choose to use the default proxy that inherits ClientBase<T> or ExceptionHandlingProxy<T> which encapsulates managing the lifetime of the channel factory and channel. ExceptionHandlingProxy respects your selections in the Add Service Reference dialog with respect to asynchronous methods and collection types.
Codeplex has a project called Exception Handling WCF Proxy Generator. It basically installs a new custom tool to Visual Studio 2008, then use this tool to generate the new service proxy (Add service reference). It has some nice functionality to deal with faulted channels, timeouts and safe disposal. There's an excellent video here called ExceptionHandlingProxyWrapper explaining exactly how this works.
You can safely use the Using statement again, and if the channel is faulted on any request (TimeoutException or CommunicationException), the Wrapper will re-initialize the faulted channel and retry the query. If that fails then it will call the Abort() command and dispose of the proxy and rethrow the Exception. If the service throws a FaultException code it will stop executing, and the proxy will be aborted safely throwing the correct exception as expected.
Based on answers by Marc Gravell, MichaelGG, and Matt Davis, our developers came up with the following:
public static class UsingServiceClient
{
public static void Do<TClient>(TClient client, Action<TClient> execute)
where TClient : class, ICommunicationObject
{
try
{
execute(client);
}
finally
{
client.DisposeSafely();
}
}
public static void DisposeSafely(this ICommunicationObject client)
{
if (client == null)
{
return;
}
bool success = false;
try
{
if (client.State != CommunicationState.Faulted)
{
client.Close();
success = true;
}
}
finally
{
if (!success)
{
client.Abort();
}
}
}
}
Example of use:
string result = string.Empty;
UsingServiceClient.Do(
new MyServiceClient(),
client =>
result = client.GetServiceResult(parameters));
It's as close to the "using" syntax as possible, you don't have to return a dummy value when calling a void method, and you can make multiple calls to the service (and return multiple values) without having to use tuples.
Also, you can use this with ClientBase<T> descendants instead of ChannelFactory if desired.
The extension method is exposed if a developer wants to manually dispose of a proxy/channel instead.
#Marc Gravell
Wouldn't it be OK to use this:
public static TResult Using<T, TResult>(this T client, Func<T, TResult> work)
where T : ICommunicationObject
{
try
{
var result = work(client);
client.Close();
return result;
}
catch (Exception e)
{
client.Abort();
throw;
}
}
Or, the same thing (Func<T, TResult>) in case of Service<IOrderService>.Use
These would make returning variables easier.
What is this?
This is the CW version of the accepted answer but with (what I consider complete) Exception handling included.
The accepted answer references this website that is no longer around. To save you trouble, I am including the most relevant parts here. In addition, I modified it slightly to include exception retry handling to handle those pesky network timeouts.
Simple WCF Client Usage
Once you generate your client side proxy, this is all you need to implement it.
Service<IOrderService>.Use(orderService=>
{
orderService.PlaceOrder(request);
});
ServiceDelegate.cs
Add this file to your solution. No changes are needed to this file, unless you want to alter the number of retries or what exceptions you want to handle.
public delegate void UseServiceDelegate<T>(T proxy);
public static class Service<T>
{
public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>("");
public static void Use(UseServiceDelegate<T> codeBlock)
{
IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel();
bool success = false;
Exception mostRecentEx = null;
int millsecondsToSleep = 1000;
for(int i=0; i<5; i++) // Attempt a maximum of 5 times
{
try
{
codeBlock((T)proxy);
proxy.Close();
success = true;
break;
}
// The following is typically thrown on the client when a channel is terminated due to the server closing the connection.
catch (ChannelTerminatedException cte)
{
mostRecentEx = cte;
proxy.Abort();
// delay (backoff) and retry
Thread.Sleep(millsecondsToSleep * (i + 1));
}
// The following is thrown when a remote endpoint could not be found or reached. The endpoint may not be found or
// reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable.
catch (EndpointNotFoundException enfe)
{
mostRecentEx = enfe;
proxy.Abort();
// delay (backoff) and retry
Thread.Sleep(millsecondsToSleep * (i + 1));
}
// The following exception that is thrown when a server is too busy to accept a message.
catch (ServerTooBusyException stbe)
{
mostRecentEx = stbe;
proxy.Abort();
// delay (backoff) and retry
Thread.Sleep(millsecondsToSleep * (i + 1));
}
catch (TimeoutException timeoutEx)
{
mostRecentEx = timeoutEx;
proxy.Abort();
// delay (backoff) and retry
Thread.Sleep(millsecondsToSleep * (i + 1));
}
catch (CommunicationException comException)
{
mostRecentEx = comException;
proxy.Abort();
// delay (backoff) and retry
Thread.Sleep(millsecondsToSleep * (i + 1));
}
catch(Exception )
{
// rethrow any other exception not defined here
// You may want to define a custom Exception class to pass information such as failure count, and failure type
proxy.Abort();
throw ;
}
}
if (success == false && mostRecentEx != null)
{
proxy.Abort();
throw new Exception("WCF call failed after 5 retries.", mostRecentEx );
}
}
}
PS: I've made this post a community wiki. I won't collect "points" from this answer, but prefer you upvote it if you agree with the implementation, or edit it to make it better.
Below is an enhanced version of the source from the question and extended to cache multiple channel factories and attempt to look up the endpoint in the configuration file by contract name.
It uses .NET 4 (specifically: contravariance, LINQ, var):
/// <summary>
/// Delegate type of the service method to perform.
/// </summary>
/// <param name="proxy">The service proxy.</param>
/// <typeparam name="T">The type of service to use.</typeparam>
internal delegate void UseServiceDelegate<in T>(T proxy);
/// <summary>
/// Wraps using a WCF service.
/// </summary>
/// <typeparam name="T">The type of service to use.</typeparam>
internal static class Service<T>
{
/// <summary>
/// A dictionary to hold looked-up endpoint names.
/// </summary>
private static readonly IDictionary<Type, string> cachedEndpointNames = new Dictionary<Type, string>();
/// <summary>
/// A dictionary to hold created channel factories.
/// </summary>
private static readonly IDictionary<string, ChannelFactory<T>> cachedFactories =
new Dictionary<string, ChannelFactory<T>>();
/// <summary>
/// Uses the specified code block.
/// </summary>
/// <param name="codeBlock">The code block.</param>
internal static void Use(UseServiceDelegate<T> codeBlock)
{
var factory = GetChannelFactory();
var proxy = (IClientChannel)factory.CreateChannel();
var success = false;
try
{
using (proxy)
{
codeBlock((T)proxy);
}
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
/// <summary>
/// Gets the channel factory.
/// </summary>
/// <returns>The channel factory.</returns>
private static ChannelFactory<T> GetChannelFactory()
{
lock (cachedFactories)
{
var endpointName = GetEndpointName();
if (cachedFactories.ContainsKey(endpointName))
{
return cachedFactories[endpointName];
}
var factory = new ChannelFactory<T>(endpointName);
cachedFactories.Add(endpointName, factory);
return factory;
}
}
/// <summary>
/// Gets the name of the endpoint.
/// </summary>
/// <returns>The name of the endpoint.</returns>
private static string GetEndpointName()
{
var type = typeof(T);
var fullName = type.FullName;
lock (cachedFactories)
{
if (cachedEndpointNames.ContainsKey(type))
{
return cachedEndpointNames[type];
}
var serviceModel = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).SectionGroups["system.serviceModel"] as ServiceModelSectionGroup;
if ((serviceModel != null) && !string.IsNullOrEmpty(fullName))
{
foreach (var endpointName in serviceModel.Client.Endpoints.Cast<ChannelEndpointElement>().Where(endpoint => fullName.EndsWith(endpoint.Contract)).Select(endpoint => endpoint.Name))
{
cachedEndpointNames.Add(type, endpointName);
return endpointName;
}
}
}
throw new InvalidOperationException("Could not find endpoint element for type '" + fullName + "' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element.");
}
}
A wrapper like this would work:
public class ServiceClientWrapper<ServiceType> : IDisposable
{
private ServiceType _channel;
public ServiceType Channel
{
get { return _channel; }
}
private static ChannelFactory<ServiceType> _channelFactory;
public ServiceClientWrapper()
{
if(_channelFactory == null)
// Given that the endpoint name is the same as FullName of contract.
_channelFactory = new ChannelFactory<ServiceType>(typeof(T).FullName);
_channel = _channelFactory.CreateChannel();
((IChannel)_channel).Open();
}
public void Dispose()
{
try
{
((IChannel)_channel).Close();
}
catch (Exception e)
{
((IChannel)_channel).Abort();
// TODO: Insert logging
}
}
}
That should enable you to write code like:
ResponseType response = null;
using(var clientWrapper = new ServiceClientWrapper<IService>())
{
var request = ...
response = clientWrapper.Channel.MyServiceCall(request);
}
// Use your response object.
The wrapper could of course catch more exceptions if that is required, but the principle remains the same.
I used Castle dynamic proxy to solve the Dispose() issue, and also implemented auto-refreshing the channel when it is in an unusable state. To use this you must create a new interface that inherits your service contract and IDisposable. The dynamic proxy implements this interface and wraps a WCF channel:
Func<object> createChannel = () =>
ChannelFactory<IHelloWorldService>
.CreateChannel(new NetTcpBinding(), new EndpointAddress(uri));
var factory = new WcfProxyFactory();
var proxy = factory.Create<IDisposableHelloWorldService>(createChannel);
proxy.HelloWorld();
I like this since you can inject WCF services without consumers needing to worry about any details of WCF. And there's no added cruft like the other solutions.
Have a look at the code, it's actually pretty simple:
WCF Dynamic Proxy
Use an extension method:
public static class CommunicationObjectExtensions
{
public static TResult MakeSafeServiceCall<TResult, TService>(this TService client, Func<TService, TResult> method) where TService : ICommunicationObject
{
TResult result;
try
{
result = method(client);
}
finally
{
try
{
client.Close();
}
catch (CommunicationException)
{
client.Abort(); // Don't care about these exceptions. The call has completed anyway.
}
catch (TimeoutException)
{
client.Abort(); // Don't care about these exceptions. The call has completed anyway.
}
catch (Exception)
{
client.Abort();
throw;
}
}
return result;
}
}
If you don't need IoC or are using an autogenerated client (Service Reference), then you can simple use a wrapper to manage the closing and let the GC take the clientbase when it is in a safe state that will not throw any exception. The GC will call Dispose in serviceclient, and this will call Close. Since it is alread closed, it cannot cause any damage. I am using this without problems in production code.
public class AutoCloseWcf : IDisposable
{
private ICommunicationObject CommunicationObject;
public AutoDisconnect(ICommunicationObject CommunicationObject)
{
this.CommunicationObject = CommunicationObject;
}
public void Dispose()
{
if (CommunicationObject == null)
return;
try {
if (CommunicationObject.State != CommunicationState.Faulted) {
CommunicationObject.Close();
} else {
CommunicationObject.Abort();
}
} catch (CommunicationException ce) {
CommunicationObject.Abort();
} catch (TimeoutException toe) {
CommunicationObject.Abort();
} catch (Exception e) {
CommunicationObject.Abort();
//Perhaps log this
} finally {
CommunicationObject = null;
}
}
}
Then when you are accessing the server, you create the client and use using in the autodisconect:
var Ws = new ServiceClient("netTcpEndPointName");
using (new AutoCloseWcf(Ws)) {
Ws.Open();
Ws.Test();
}
Summary
Using the techniques described in this answer one can consume a WCF service in a using block with the following syntax:
var channelFactory = new ChannelFactory<IMyService>("");
var serviceHelper = new ServiceHelper<IMyService>(channelFactory);
var proxy = serviceHelper.CreateChannel();
using (proxy as IDisposable)
{
proxy.DoWork();
}
You can of course adapt this even further to achieve a more concise programming model specific to your situation - but the point is that we can create an implementation of IMyService reprenting the channel which correctly implements the disposable pattern.
Details
All the answers given thus far address the problem of getting around the "bug" in the WCF Channel implemention of IDisposable. The answer that seems to offer the most concise programming model (allowing you to use the using block to dispose on unmanaged resources) is this one - where the proxy is modifed to implement IDisposable with a bug-free implementation. The problem with this approach is maintainability - we have to re-implement this functionality for ever proxy we use. On a variation of this answer we will see how we can use composition rather than inheritance to make this technique generic.
First Attempt
There seem to various implementations for the IDisposable implementation, but for sake of argument we will use an adaption of that used by the currently accepted answer.
[ServiceContract]
public interface IMyService
{
[OperationContract]
void DoWork();
}
public class ProxyDisposer : IDisposable
{
private IClientChannel _clientChannel;
public ProxyDisposer(IClientChannel clientChannel)
{
_clientChannel = clientChannel;
}
public void Dispose()
{
var success = false;
try
{
_clientChannel.Close();
success = true;
}
finally
{
if (!success)
_clientChannel.Abort();
_clientChannel = null;
}
}
}
public class ProxyWrapper : IMyService, IDisposable
{
private IMyService _proxy;
private IDisposable _proxyDisposer;
public ProxyWrapper(IMyService proxy, IDisposable disposable)
{
_proxy = proxy;
_proxyDisposer = disposable;
}
public void DoWork()
{
_proxy.DoWork();
}
public void Dispose()
{
_proxyDisposer.Dispose();
}
}
Armed with the above classes we can now write
public class ServiceHelper
{
private readonly ChannelFactory<IMyService> _channelFactory;
public ServiceHelper(ChannelFactory<IMyService> channelFactory )
{
_channelFactory = channelFactory;
}
public IMyService CreateChannel()
{
var channel = _channelFactory.CreateChannel();
var channelDisposer = new ProxyDisposer(channel as IClientChannel);
return new ProxyWrapper(channel, channelDisposer);
}
}
This allows us to consume our service using the using block:
ServiceHelper serviceHelper = ...;
var proxy = serviceHelper.CreateChannel();
using (proxy as IDisposable)
{
proxy.DoWork();
}
Making this generic
All we have done so far is to reformulate Tomas' solution. What prevents this code from being generic is the fact that ProxyWrapper class has to be re-implemented for every service contract we want. We will now look at a class that allows us to create this type dynamically using IL:
public class ServiceHelper<T>
{
private readonly ChannelFactory<T> _channelFactory;
private static readonly Func<T, IDisposable, T> _channelCreator;
static ServiceHelper()
{
/**
* Create a method that can be used generate the channel.
* This is effectively a compiled verion of new ProxyWrappper(channel, channelDisposer) for our proxy type
* */
var assemblyName = Guid.NewGuid().ToString();
var an = new AssemblyName(assemblyName);
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName);
var proxyType = CreateProxyType(moduleBuilder, typeof(T), typeof(IDisposable));
var channelCreatorMethod = new DynamicMethod("ChannelFactory", typeof(T),
new[] { typeof(T), typeof(IDisposable) });
var ilGen = channelCreatorMethod.GetILGenerator();
var proxyVariable = ilGen.DeclareLocal(typeof(T));
var disposableVariable = ilGen.DeclareLocal(typeof(IDisposable));
ilGen.Emit(OpCodes.Ldarg, proxyVariable);
ilGen.Emit(OpCodes.Ldarg, disposableVariable);
ilGen.Emit(OpCodes.Newobj, proxyType.GetConstructor(new[] { typeof(T), typeof(IDisposable) }));
ilGen.Emit(OpCodes.Ret);
_channelCreator =
(Func<T, IDisposable, T>)channelCreatorMethod.CreateDelegate(typeof(Func<T, IDisposable, T>));
}
public ServiceHelper(ChannelFactory<T> channelFactory)
{
_channelFactory = channelFactory;
}
public T CreateChannel()
{
var channel = _channelFactory.CreateChannel();
var channelDisposer = new ProxyDisposer(channel as IClientChannel);
return _channelCreator(channel, channelDisposer);
}
/**
* Creates a dynamic type analogous to ProxyWrapper, implementing T and IDisposable.
* This method is actually more generic than this exact scenario.
* */
private static Type CreateProxyType(ModuleBuilder moduleBuilder, params Type[] interfacesToInjectAndImplement)
{
TypeBuilder tb = moduleBuilder.DefineType(Guid.NewGuid().ToString(),
TypeAttributes.Public | TypeAttributes.Class);
var typeFields = interfacesToInjectAndImplement.ToDictionary(tf => tf,
tf => tb.DefineField("_" + tf.Name, tf, FieldAttributes.Private));
#region Constructor
var constructorBuilder = tb.DefineConstructor(
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName,
CallingConventions.Standard,
interfacesToInjectAndImplement);
var il = constructorBuilder.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[0]));
for (var i = 1; i <= interfacesToInjectAndImplement.Length; i++)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg, i);
il.Emit(OpCodes.Stfld, typeFields[interfacesToInjectAndImplement[i - 1]]);
}
il.Emit(OpCodes.Ret);
#endregion
#region Add Interface Implementations
foreach (var type in interfacesToInjectAndImplement)
{
tb.AddInterfaceImplementation(type);
}
#endregion
#region Implement Interfaces
foreach (var type in interfacesToInjectAndImplement)
{
foreach (var method in type.GetMethods())
{
var methodBuilder = tb.DefineMethod(method.Name,
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig |
MethodAttributes.Final | MethodAttributes.NewSlot,
method.ReturnType,
method.GetParameters().Select(p => p.ParameterType).ToArray());
il = methodBuilder.GetILGenerator();
if (method.ReturnType == typeof(void))
{
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, typeFields[type]);
il.Emit(OpCodes.Callvirt, method);
il.Emit(OpCodes.Ret);
}
else
{
il.DeclareLocal(method.ReturnType);
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, typeFields[type]);
var methodParameterInfos = method.GetParameters();
for (var i = 0; i < methodParameterInfos.Length; i++)
il.Emit(OpCodes.Ldarg, (i + 1));
il.Emit(OpCodes.Callvirt, method);
il.Emit(OpCodes.Stloc_0);
var defineLabel = il.DefineLabel();
il.Emit(OpCodes.Br_S, defineLabel);
il.MarkLabel(defineLabel);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
}
tb.DefineMethodOverride(methodBuilder, method);
}
}
#endregion
return tb.CreateType();
}
}
With our new helper class we can now write
var channelFactory = new ChannelFactory<IMyService>("");
var serviceHelper = new ServiceHelper<IMyService>(channelFactory);
var proxy = serviceHelper.CreateChannel();
using (proxy as IDisposable)
{
proxy.DoWork();
}
Note that you could also use the same technique (with slight modifications) for auto-generated clients inheriting for ClientBase<> (instead of using ChannelFactory<>), or if you want to use a different implementation of IDisposable to close your channel.
I like this way of closing connection:
var client = new ProxyClient();
try
{
...
client.Close();
}
finally
{
if(client.State != CommunicationState.Closed)
client.Abort();
}
I have written a simple base class that handles this. It's available as a NuGet package and it's quite easy to use.
//MemberServiceClient is the class generated by SvcUtil
public class MemberServiceManager : ServiceClientBase<MemberServiceClient>
{
public User GetUser(int userId)
{
return PerformServiceOperation(client => client.GetUser(userId));
}
//you can also check if any error occured if you can't throw exceptions
public bool TryGetUser(int userId, out User user)
{
return TryPerformServiceOperation(c => c.GetUser(userId), out user);
}
}
public static class Service<TChannel>
{
public static ChannelFactory<TChannel> ChannelFactory = new ChannelFactory<TChannel>("*");
public static TReturn Use<TReturn>(Func<TChannel,TReturn> codeBlock)
{
var proxy = (IClientChannel)ChannelFactory.CreateChannel();
var success = false;
try
{
var result = codeBlock((TChannel)proxy);
proxy.Close();
success = true;
return result;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
}
So it allows to write return statements nicely:
return Service<IOrderService>.Use(orderService =>
{
return orderService.PlaceOrder(request);
});
I'd like to add implementation of Service from Marc Gravell's answer for case of using ServiceClient instead of ChannelFactory.
public interface IServiceConnector<out TServiceInterface>
{
void Connect(Action<TServiceInterface> clientUsage);
TResult Connect<TResult>(Func<TServiceInterface, TResult> channelUsage);
}
internal class ServiceConnector<TService, TServiceInterface> : IServiceConnector<TServiceInterface>
where TServiceInterface : class where TService : ClientBase<TServiceInterface>, TServiceInterface, new()
{
public TResult Connect<TResult>(Func<TServiceInterface, TResult> channelUsage)
{
var result = default(TResult);
Connect(channel =>
{
result = channelUsage(channel);
});
return result;
}
public void Connect(Action<TServiceInterface> clientUsage)
{
if (clientUsage == null)
{
throw new ArgumentNullException("clientUsage");
}
var isChanneldClosed = false;
var client = new TService();
try
{
clientUsage(client);
client.Close();
isChanneldClosed = true;
}
finally
{
if (!isChanneldClosed)
{
client.Abort();
}
}
}
}
For those interested, here's a VB.NET translation of the accepted answer (below). I've refined it a bit for brevity, combining some of the tips by others in this thread.
I admit it's off-topic for the originating tags (C#), but as I wasn't able to find a VB.NET version of this fine solution I assume that others will be looking as well. The Lambda translation can be a bit tricky, so I'd like to save someone the trouble.
Note that this particular implementation provides the ability to configure the ServiceEndpoint at runtime.
Code:
Namespace Service
Public NotInheritable Class Disposable(Of T)
Public Shared ChannelFactory As New ChannelFactory(Of T)(Service)
Public Shared Sub Use(Execute As Action(Of T))
Dim oProxy As IClientChannel
oProxy = ChannelFactory.CreateChannel
Try
Execute(oProxy)
oProxy.Close()
Catch
oProxy.Abort()
Throw
End Try
End Sub
Public Shared Function Use(Of TResult)(Execute As Func(Of T, TResult)) As TResult
Dim oProxy As IClientChannel
oProxy = ChannelFactory.CreateChannel
Try
Use = Execute(oProxy)
oProxy.Close()
Catch
oProxy.Abort()
Throw
End Try
End Function
Public Shared ReadOnly Property Service As ServiceEndpoint
Get
Return New ServiceEndpoint(
ContractDescription.GetContract(
GetType(T),
GetType(Action(Of T))),
New BasicHttpBinding,
New EndpointAddress(Utils.WcfUri.ToString))
End Get
End Property
End Class
End Namespace
Usage:
Public ReadOnly Property Jobs As List(Of Service.Job)
Get
Disposable(Of IService).Use(Sub(Client) Jobs = Client.GetJobs(Me.Status))
End Get
End Property
Public ReadOnly Property Jobs As List(Of Service.Job)
Get
Return Disposable(Of IService).Use(Function(Client) Client.GetJobs(Me.Status))
End Get
End Property
Our system architecture often uses the Unity IoC framework to create instances of ClientBase so there's no sure way to enforce that the other developers even use using{} blocks. In order to make it as fool-proof as possible, I made this custom class that extends ClientBase, and handles closing down the channel on dispose, or on finalize in case someone doesn't explicitly dispose of the Unity created instance.
There is also stuff that needed to be done in the constructor to set up the channel for custom credentials and stuff, so that's in here too...
public abstract class PFServer2ServerClientBase<TChannel> : ClientBase<TChannel>, IDisposable where TChannel : class
{
private bool disposed = false;
public PFServer2ServerClientBase()
{
// Copy information from custom identity into credentials, and other channel setup...
}
~PFServer2ServerClientBase()
{
this.Dispose(false);
}
void IDisposable.Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if (!this.disposed)
{
try
{
if (this.State == CommunicationState.Opened)
this.Close();
}
finally
{
if (this.State == CommunicationState.Faulted)
this.Abort();
}
this.disposed = true;
}
}
}
Then a client can simply:
internal class TestClient : PFServer2ServerClientBase<ITest>, ITest
{
public string TestMethod(int value)
{
return base.Channel.TestMethod(value);
}
}
And the caller can do any of these:
public SomeClass
{
[Dependency]
public ITest test { get; set; }
// Not the best, but should still work due to finalizer.
public string Method1(int value)
{
return this.test.TestMethod(value);
}
// The good way to do it
public string Method2(int value)
{
using(ITest t = unityContainer.Resolve<ITest>())
{
return t.TestMethod(value);
}
}
}
I referred few answers on this post and customized it as per my needs.
I wanted the ability to do something with WCF client before using it so the DoSomethingWithClient() method.
public interface IServiceClientFactory<T>
{
T DoSomethingWithClient();
}
public partial class ServiceClient : IServiceClientFactory<ServiceClient>
{
public ServiceClient DoSomethingWithClient()
{
var client = this;
// do somthing here as set client credentials, etc.
//client.ClientCredentials = ... ;
return client;
}
}
Here is the helper class:
public static class Service<TClient>
where TClient : class, ICommunicationObject, IServiceClientFactory<TClient>, new()
{
public static TReturn Use<TReturn>(Func<TClient, TReturn> codeBlock)
{
TClient client = default(TClient);
bool success = false;
try
{
client = new TClient().DoSomethingWithClient();
TReturn result = codeBlock(client);
client.Close();
success = true;
return result;
}
finally
{
if (!success && client != null)
{
client.Abort();
}
}
}
}
And I can use it as:
string data = Service<ServiceClient>.Use(x => x.GetData(7));
I have my own wrapper for a channel which implements Dispose as follows:
public void Dispose()
{
try
{
if (channel.State == CommunicationState.Faulted)
{
channel.Abort();
}
else
{
channel.Close();
}
}
catch (CommunicationException)
{
channel.Abort();
}
catch (TimeoutException)
{
channel.Abort();
}
catch (Exception)
{
channel.Abort();
throw;
}
}
This seems to work well and allows a using block to be used.
The following helper allows to call void and non-void methods. Usage:
var calculator = new WcfInvoker<CalculatorClient>(() => new CalculatorClient());
var sum = calculator.Invoke(c => c.Sum(42, 42));
calculator.Invoke(c => c.RebootComputer());
The class itself is:
public class WcfInvoker<TService>
where TService : ICommunicationObject
{
readonly Func<TService> _clientFactory;
public WcfInvoker(Func<TService> clientFactory)
{
_clientFactory = clientFactory;
}
public T Invoke<T>(Func<TService, T> action)
{
var client = _clientFactory();
try
{
var result = action(client);
client.Close();
return result;
}
catch
{
client.Abort();
throw;
}
}
public void Invoke(Action<TService> action)
{
Invoke<object>(client =>
{
action(client);
return null;
});
}
}
Override the client's Dispose() without the need to generate a proxy class based on ClientBase, also without the need to manage channel creation and caching! (Note that WcfClient is not an ABSTRACT class and is based on ClientBase)
// No need for a generated proxy class
//using (WcfClient<IOrderService> orderService = new WcfClient<IOrderService>())
//{
// results = orderService.GetProxy().PlaceOrder(input);
//}
public class WcfClient<TService> : ClientBase<TService>, IDisposable
where TService : class
{
public WcfClient()
{
}
public WcfClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public WcfClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public WcfClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public WcfClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
protected virtual void OnDispose()
{
bool success = false;
if ((base.Channel as IClientChannel) != null)
{
try
{
if ((base.Channel as IClientChannel).State != CommunicationState.Faulted)
{
(base.Channel as IClientChannel).Close();
success = true;
}
}
finally
{
if (!success)
{
(base.Channel as IClientChannel).Abort();
}
}
}
}
public TService GetProxy()
{
return this.Channel as TService;
}
public void Dispose()
{
OnDispose();
}
}
My method of doing this has been to create an inherited class that explicitly implements IDisposable. This is useful for folks who use the gui to add the service reference ( Add Service Reference ). I just drop this class in the project making the service reference and use it instead of the default client:
using System;
using System.ServiceModel;
using MyApp.MyService; // The name you gave the service namespace
namespace MyApp.Helpers.Services
{
public class MyServiceClientSafe : MyServiceClient, IDisposable
{
void IDisposable.Dispose()
{
if (State == CommunicationState.Faulted)
{
Abort();
}
else if (State != CommunicationState.Closed)
{
Close();
}
// Further error checks and disposal logic as desired..
}
}
}
Note: This is just a simple implementation of dispose, you can implement more complex dispose logic if you like.
You can then replace all your calls made with the regular service client with the safe clients, like this:
using (MyServiceClientSafe client = new MyServiceClientSafe())
{
var result = client.MyServiceMethod();
}
I like this solution as it does not require me to have access to the Interface definitions and I can use the using statement as I would expect while allowing my code to look more or less the same.
You will still need to handle the exceptions which can be thrown as pointed out in other comments in this thread.
You could also use a DynamicProxy to extend the Dispose() method. This way you could do something like:
using (var wrapperdProxy = new Proxy<yourProxy>())
{
// Do whatever and dispose of Proxy<yourProxy> will be called and work properly.
}