Skip to main content

Microsoft Silverlight

Answered Question Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)RSS Feed

(0)

spoo
spoo

Member

Member

21 points

43 Posts

Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

I'm calling a web service from my Silverlight application, but if any of the web service methods throw an Exception, I'm just getting a ProtocolException in the BeginInvoke() call for the generated proxy code for the web service method, instead of the actual Exception the web service threw.

E.g.the method could be something like:

 

[WebMethod]
public void GetItem(/* some parameters */)
{
if (checkAccess()) throw new Exception("you're not allowed to do this");
else
{
doWhateverIfAllowed();
}
}
The .InnerException is null. 

The .Message property will be: "The remote server returned an unexpected response: (404) Not Found."

The .StackTrack will be something like:

"   at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result)\r\n   at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)\r\n   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)\r\n   at System.ServiceModel.ClientBase`1.ChannelBase`1.EndInvoke(String methodName, Object[] args, IAsyncResult result)\r\n   at Schedule.ScheduleProxyServiceReference.ScheduleProxyWebServiceSoapClient.ScheduleProxyWebServiceSoapClientChannel.EndAddItem(IAsyncResult result)\r\n   at Schedule.ScheduleProxyServiceReference.ScheduleProxyWebServiceSoapClient.Schedule.ScheduleProxyServiceReference.ScheduleProxyWebServiceSoap.EndAddItem(IAsyncResult result)\r\n   at Schedule.ScheduleProxyServiceReference.ScheduleProxyWebServiceSoapClient.EndAddItem(IAsyncResult result)\r\n   at Schedule.ScheduleProxyServiceReference.ScheduleProxyWebServiceSoapClient.OnEndAddItem(IAsyncResult result)\r\n   at System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult result)"

(ScheduleProxyService is the web service)

And before someone starts suggesting this; NO, it's not a missing cross-domain policy file. The web services work fine as long as they don't throw any exceptions.

Is there no way of getting the actual Exception from the web service?

(And why am I getting a 404 here?? Shouldn't the WS return a 501 if there's was an internal error? :P)

Edit: if I open up the WS in IE and call the method that throws an exception, I'm actually getting a "500" response. Is there something else I have to do to make the WS pass on the exceptions? (This is through SOAP)

sladapter
sladapter

All-Star

All-Star

17439 points

3,172 Posts

Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

In this thread we talked about how to catch WCF exception and pass it back to Silverlight. For WCF it's little easier because we can add CustomException filed to all the return object from WCF so we do not need to do any seralization.  For asmx call you also need to catch the exception at all your WebMethod and serialize it to some form. If all your returning data is packaged in xml, you can always insert a error element and error message in that xml so you can parse it back on Silverlight side.

 http://silverlight.net/forums/p/17944/60019.aspx#60019

Some one also suggested using a out paramter to pass exception back in all WCF call. You can try the same in asxm call, I don't think you can pass the custom exception object back, but you can try to pass the error message (string type) back.

http://silverlight.net/forums/p/18885/64303.aspx#64303


sladapter
Software Engineer
Aprimo, Inc

Please remember to mark the replies as answers if they answered your question

spoo
spoo

Member

Member

21 points

43 Posts

Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

Hm, well so, testing the .asmx from the browser gives this text only, not even enveloped in XML - but literally just this - as content-type text/plain. Why doesn't the WS envelope this in a SOAP fault message?  (Output of:   throw new Exception("failed!") )

System.Exception: failed!
at Schedule_Web.MiscWebService.DummyFail() in C:\work\dotnet_sl_schedule\Schedule\Schedule_Web\MiscWebService.asmx.cs:line 152
I see what you're saying with wrapping it in a result -- sure.... I could do that.
But aren't there any ways of getting this eveloped as a SOAP-fault response?
E.g. http://msdn.microsoft.com/en-us/library/aa480514.aspx says I should be getting that message wrapped something like:
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>System.Web.Services.Protocols.SoapException: Server was
unable to process request. ---&gt; System.Exception: Something bad
happened at AYS17Sept2002.Service1.CallFault() in
c:\inetpub\wwwroot\AYS17Sept2002\Service1.asmx.vb:line 49
--- End of inner exception stack trace ---</faultstring>
<detail />
</soap:Fault>
Is this some configuration error from my side, or is it some attributes I have to decorate the WS with, or what? 
I'll admit I'm a noob at doing WSes from .NET based stuff. :)
 

sladapter
sladapter

All-Star

All-Star

17439 points

3,172 Posts

Answered Question

Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

spoo:

But aren't there any ways of getting this eveloped as a SOAP-fault response?

Not with current Silverlight. Maybe later, I don't know. I wish they do.

 

 

 

 

 

sladapter
Software Engineer
Aprimo, Inc

Please remember to mark the replies as answers if they answered your question

spoo
spoo

Member

Member

21 points

43 Posts

Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

Ok, thanks for the answer.

This is - to speak honestly - rather lame, but oh well. I'll just have to resort to passing the error string as part of the result set then.

Thanks.

 

sravoux
sravoux

Member

Member

4 points

2 Posts

Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

My solution is :

  • to memorize the WCF exception on the session and rethrow it ("as is" or a FaultException)
  • to implement a GetLastError method on my WCF service that gives the exception's details
  • to catch the ProtocolException on the SL2 client and recall the server to know what happened

Something like this :

[OperationContract]
public void Hello()
{
try { … }
catch (Exception ex)
{
// NB: I give a nice context's message in UserState parameter
HandleError("The hello method failed", ex);
}
}

[DataContract]
public class ErrorInfos
{
[DataMember]
public string Message;

[DataMember]
public string Details;
}

private void HandleError(string message, Exception ex)
{
var error = new ErrorInfos() { Message = message , Details = null };
if (ex != null)
{
// Ajout du détails de l'exception
error.Details = ex.ToString();

// Ajout du message de la premiere exception dans le message
while (ex.InnerException != null)
{
ex = ex.InnerException;
}
error.Message += " (" + ex.Message + ")";
}

// Mémorisation de l'erreur en session (Workaround du bug SL2 Beta 2)
if (HttpContext.Current != null)
{
HttpContext.Current.Session["LastError"] = error;
}

// Génération d'une faute SOAP (NB: pas géré par SL2 Beta2)
throw new FaultException(new FaultReason(error.Message));
}

[OperationContract]
public ErrorInfos GetLastError()
{
ErrorInfos error = null;
if (HttpContext.Current != null)
{
error = (ErrorInfos)HttpContext.Current.Session["LastError"];
return error;
}
}

 

On the SL2 client :

private void OnXxxCompleted(object sender, AsyncCompletedEventArgs e)
{
try
{
var result = e.Result;
//…
}
catch (ProtocolException ex)
{
CompleteAndDisplayError(ex);
}
}

public static void CompleteAndDisplayError(string msg, Exception e)
{
var client = ServicesManager.GetClient();
client.GetLastErrorCompleted += new EventHandler(OnGetLastErrorCompleted);
client.GetLastErrorAsync(msg);
}

private static void OnGetLastErrorCompleted(object sender, GetLastErrorCompletedEventArgs e)
{
if (!e.Cancelled && e.Error == null)
{
DisplayError(e.Result.Message, e.Result.Details);
}
else
{
DisplayError(e.UserState as string);
}
}
 

ticcoid
ticcoid

Member

Member

10 points

31 Posts

Re: Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

hey, thank you for that code. i rebuilt it but there is always a runtime error. something like the exceptions are not handling by usercode. sry this is not the exact error because i translate it from german. but maybe you know what it can be. thank you

sladapter
sladapter

All-Star

All-Star

17439 points

3,172 Posts

Re: Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

The best solution for catching Exception thrown in WCF is given in this blog:  http://blogs.msdn.com/silverlightws/

The sample code can download from here: http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=silverlightws&DownloadId=3473

The code they provided is very straightforward without having to change much of the current code. You do not have to do anything on the WCF end. All you need to do to create BasicHttpMessageInspectorBinding instead of BasicHttpBinding and pass it to the Service constructor. Then the e.Error should return the exceptions thrown from the Service end.

 


sladapter
Software Engineer
Aprimo, Inc

Please remember to mark the replies as answers if they answered your question

ticcoid
ticcoid

Member

Member

10 points

31 Posts

Re: Re: Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

thank you, i tested your approach from an other thread and it works fine. you said that the solution in that blog is the best. but which do you mean? i cant find catching exception in this blog. thank you

sladapter
sladapter

All-Star

All-Star

17439 points

3,172 Posts

Re: Re: Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

You need to download the sample code from this link:

http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=silverlightws&DownloadId=3473

And run the SilverlightRawFault sample project you can see what I mean this is the best solution so far for handling the error thrown from WCF.  If you take a look at WCF Service.svc.cs code you can see the DoWork function just throw an exception. There is nothing special in the service code. You just write your service code as you normally do. But the error thrown from WCF will be catched in the Silverlight end. All you need to do is the following:

1) Add reference of SilverlightFaultBehavior.dll (which is included in the sample files) to the Web project, and add the following behavior to the Web.config file:

<system.serviceModel>
        <extensions>
            <behaviorExtensions>
                <add name="silverlightFaults" type="Microsoft.Silverlight.Samples.SilverlightFaultBehavior, SilverlightFaultBehavior, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
            </behaviorExtensions>
        </extensions>
        <behaviors>
            <endpointBehaviors>
              
  <behavior name="SilverlightFaultBehavior">
                    <silverlightFaults/>
              
  </behavior>
            </endpointBehaviors>

           ...

</system.serviceModel>

 2) Add reference of SilverlightMessageInspector.dll (included in the sample) to the Silverlight project.

3) Add SilverlightFaultMessageInspector.cs (included in the sample) to your Silverlight project or your Silverlight Library project.

4) Change your WCF calling code to the following:

            YourServiceClient proxy = new YourServiceClient();  // Your WCF service default consturctor
 

            EndpointAddress address = new EndpointAddress("http://localhost:52620/Service.svc");
            BasicHttpMessageInspectorBinding binding = new BasicHttpMessageInspectorBinding(new SilverlightFaultMessageInspector());

            ServiceClient proxy = new ServiceClient(binding, address);  // Use this WCF service constructor, pass new binding

            proxy.DoWorkCompleted += new System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(proxy_DoWorkCompleted);
            proxy.DoWorkAsync(); //code to call WCF

 void proxy_DoWorkCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (e.Error != null)

            {

               if(e.Error is RawFaultException)  // Now you can catch the Exception thrown from WCF
               {
                RawFaultException exception = (RawFaultException)e.Error;
                MessageBox.Show("Service says: " + exception.FaultMessage + Environment.NewLine +
                    "Exception type: " + exception.FaultType + Environment.NewLine +
                    "Stack trace: " + exception.StackTrace);
               }

             else // None WCF error

                   MessageBox.Show(e.Message);

 
         }

sladapter
Software Engineer
Aprimo, Inc

Please remember to mark the replies as answers if they answered your question

ticcoid
ticcoid

Member

Member

10 points

31 Posts

Re: Re: Re: Re: Getting the actual Exception thrown from a WebService (not just a 404 / ProtocolException)

big big thank you sladapter. works very good.

  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities