I added a service reference to a silverlight app. When I want to call a method in the service I use those lines :
CustomServiceClient proxy = new CustomServiceClient();
proxy.GetDataCompleted += new EventHandler<GetDataCompletedEventArgs>(Proxy_GetDataCompleted);
try
{
proxy.GetDataAsync(appUser.Id);
proxy.CloseAsync();
}
catch (TimeoutException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
proxy.Abort();
}
catch (CommunicationException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
proxy.Abort();
}
The problem is that every time I need to call a method I am duplicating this code. I can't figure out an elegant way to reuse it (I can use inheritance and make a new class for each method, but it's very ugly).
Sounds like you are looking for something similar to what is described in this CodeProject article.
The answer in this msdn forum post seems to have an elegant solution to this by using extension methods.
Related
I have the below code to call a WCF proxy:-
var client = new ServiceClientProxy();
try
{
var documents = client.GetDocuments();
client.Close();
if(documents.Length > 50)
{
throw new Exception("Too many Documents");
}
else if(documents.Length <10)
{
throw new Exception("Too many Documents");
}
else
{
return documents;
}
}
catch(exception ex)
{
client.Abort();
}
Here If the documents count that we get from service is more than 50 or less than 10, in that case we will be calling both Close() as well as the Abort functions on client.Is this expected way of calling WCF service proxy?
Anyone please suggest if there is some better way handling this.
Also is it a better approach to close the client connection immediately after the call or do we need to wait till we have completely used the response properties and close the connection at end?
Also is it a better approach to close the client connection
immediately after the call or do we need to wait till we have
completely used the response properties and close the connection at
end?
Depends on if you need to make subsequent calls to the service. If not then by all means close the connection.
Is this expected way of calling WCF service proxy? Anyone please
suggest if there is some better way handling this.
No. To handle a problem that is baked into WCF you could should actually be structured like this:
Documents documnts = null;
try
{
var client = new ServiceClientProxy();
documents = client.GetDocuments();
}
finally
{
try
{
if (client.State != CommunicationState.Closed)
client.Close();
}
catch
{
client.Abort();
};
};
if (documents.Length > 50)
{
throw new Exception("Too many Documents");
}
else if (documents.Length < 10)
{
throw new Exception("Too many Documents");
}
else
{
return documents;
}
If you want to truly understand the 'why' I would highly recommend reading this series of articles. They will clear up the Close / Abort portion of your problem.
http://blogs.msmvps.com/p3net/2014/02/02/a-smarter-wcf-service-client-part-1/
http://blogs.msmvps.com/p3net/2014/02/09/a-smarter-wcf-service-client-part-2/
http://blogs.msmvps.com/p3net/2014/02/23/a-smarter-wcf-service-client-part-3/
http://blogs.msmvps.com/p3net/2014/03/15/a-smarter-wcf-service-client-part-4/
Another other things I should point out with the code you've provided is exceptions should be exceptional.
Using exceptions for what I would considered to be business logic is usually not the right thing to do. Consider the approach where you return a structured result instead. Perhaps in your case it make sense though.
HTH
I am running Silverlight 4 with a MVVM framework. From time to time, but not always, during a detail page load, I get a XamlParseException. Since it works 99% of the time, I'm pretty sure the xaml page is fine.
Is it possible to do something similar to the following in my code behind page?
public DetailView() {
try {
InitializeComponent();
} catch (XamlParseException e) {
Debugger.Break();
}
}
In other words, how do I catch the XamlParseException?
You cannot catch this exception using try-catch when the parsing is being handled by the runtime.
The only way to catch this exception is when you are using XamlReader like in this discussion:
http://social.msdn.microsoft.com/Forums/da-DK/wpf/thread/02679567-1bd3-41d1-bfd1-326f646d95d1
You can try handling it on Application_UnhandledException.
More info here: http://msdn.microsoft.com/en-us/library/system.windows.application.unhandledexception(v=vs.95).aspx
And some more info here: http://msdn.microsoft.com/en-us/library/cc189070(v=vs.95).aspx
I have a class that handles all the interaction in my application with my WCF service and it seems that MSDN say that the use of Using)_ statement with WCF is bad - I can see why this is bad and agree with it (http://msdn.microsoft.com/en-us/library/aa355056.aspx)
my problem is that their suggested method of implementation will mean that i have 10 methods [as 10 public methods in my service] that will have the same structure code and this of course does not follow the DRY principal - the code looks similar to the following:
try
{
results = _client.MethodCall(input parameteres);
_client.Close();
}
catch (CommunicationException)
{
if (_client != null && _client.State != CommunicationState.Closed)
{
_client.Abort();
}
}
catch (TimeoutException)
{
if (_client != null && _client.State != CommunicationState.Closed)
{
_client.Abort();
}
}
catch (Exception ex)
{
if (_client != null && _client.State != CommunicationState.Closed)
{
_client.Abort();
}
throw;
}
This doesn't have any logging yet but of course when I do come to start logging it then I will have to add the logging work in almost 10 different places
does anyone have any tips on how I can be a bit more resourceful here in reusing code
thanks
paul
I would use some general-purpose, configurable exception handling component that allows basic exception handling processing like logging, re-throwing etc. to be decoupled from the actual place of handling. One example of such a component is Microsoft's Exception Handling Application Block.
Then you could end up with a code like this:
try
{
results = _client.MethodCall(input parameteres);
_client.Close();
}
catch (Exception ex)
{
_client.CloseIfNeeded();
if (!ex.Handle("Wcf.Policy")) throw;
}
where CloseIfNeeded denotes a custom extension method encapsulating the WCF channel closing logic, and the Handle exception method calls the exception handling mechanism, passing in a name of the exception policy that shall be applied on this place.
In most cases, you can reduce exception handling logic to a decent one or two lines of code, giving you several benefits:
instant configurability of exception handling behavior (policies)
extensibility with custom exception handlers bound to specific types of exceptions and exception policies
better manageability and readability of code
Let's say I have this in an implementation of IInstanceProvider:
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
try
{
unitOfWork.Commit();
}
catch (Exception)
{
unitOfWork.Rollback();
throw;
}
finally
{
unitOfWork.Dispose();
}
}
That throw; will never be returned to the client because it is being called after the service has done it's work and returned data to the client, and is therefore done. How else can I return the exception? Or is there a better place to do this?
I think you are looking in the wrong place to do this. I think a better choice would be to implement the IDispatchMessageInspector interface and attach it to the collection exposed by the MessageInspectors property on the DispatchRuntime (through a behavior, most likely).
With this, you can inspect messages coming in and going out, and modify them if need be (which is how your exception would be realized, as a fault in the return message). Because of this, you will not just let the exception bubble up, but rather, you would change it to a fault message and set the return message to that.
I'm not as familiar with transactions in WCF as I should be. What in the above code returns the results to the client? Is it the rollback?
Before I call Close() on my WCF service, should I check to see if it is not already closed?
i.e.
myWCFService.State != System.ServiceModel.CommunicationState.Closed
My code looks like:
MyServiceClient myWCFClient = null;
try
{
myWCFClient = new .....();
}
catch
{
}
finally
{
myWCFClient.Close();
}
A WCF client is disposable, so except for a few caveats you can use using:
using(MyClient client = new MyClient()) {
client.DoStuff();
// etc
}
But there is a big problem with this; the Dispose on the WCF client actually throws if it is faulted (losing the original exception). There is a good workaround, here, or I've blogged on this here.
Take a look at this question: What is the best workaround for the WCF client using block issue? Although it isn't word for word what you are looking for, I think his examples will help you out.