I'm setting a custom StatusDescription in a RESTful WCF service when an exception is thrown. It's meant to provide the caller with a friendly description of why they got the failure status code.
The following is the response I see in Fiddler. So I know that my custom message is getting pushed back through to the caller. What I can't figure out is how to retrieve that message from .NET. The StatusDescription does not contain this string.
If you could provide a simple bit of sample code that would be great.
HTTP/1.1 500 Message: "Exception of type 'Exceptions.DataSourceNotFoundException' was thrown." Uri: http://www.test1.com/
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 20 Apr 2009 07:13:40 GMT
UPDATE
The answer to this question does not work in Silverlight. Tested in Silverlight 2 and 3 beta.
-
Not a .NET programmer, Found this on msdn
catch(WebException ex) { string message = ((HttpWebResponse)ex.Response).StatusDescription; }Arjan : @spoon16, care to explain why you've changed this wrong answer and then accepted it as the best answer? -
I've not used .NET in many years, but in Java people often expect to get a HTTP code and message for 404 Not Found errors, while 404s actually make Java throw a FileNotFoundException. For those situations, in Java one should use
HttpURLConnection#getErrorStreamrather than#getResponseMessage.So: maybe something similar is happening in a .NET client for 500 responses? Indeed the documentation for
HttpWebRequeststates:The HttpWebRequest class throws a WebException when errors occur while accessing a resource. The WebException.Status property contains a WebExceptionStatus value that indicates the source of the error. When WebException.Status is WebExceptionStatus.ProtocolError, the Response property contains the HttpWebResponse received from the resource.
Detail: the link to
Responseabove refers toWebException.Response, not toHttpWebRequest.GetResponse. So,WebExceptionhas its ownResponseproperty. The following example is based on theWebException.Responsedocumentation, but I did not test it.IMPORTANT: note that this does NOT use
GetResponsefromHttpWebRequest, butResponsefromWebException:try { HttpWebRequest myHttpWebRequest = (HttpWebRequest) WebRequest.Create("http://www.example.org/not_found"); HttpWebResponse myHttpWebResponse = (HttpWebResponse) myHttpWebRequest.GetResponse(); myHttpWebResponse.Close(); } catch(WebException e) { Console.WriteLine("Exception Message: " + e.Message); if(e.Status == WebExceptionStatus.ProtocolError) { Console.WriteLine("Status Code: {0}", ((HttpWebResponse)e.Response).StatusCode); Console.WriteLine("Status Description: {0}", ((HttpWebResponse)e.Response).StatusDescription); } } catch(Exception e) { Console.WriteLine(e.Message); } -
I think your issue is that your status code is 500. When the status code isn't OK (200 or some type of redirect), WebRequest.GetResponse() call throws a WebException in .NET.
This exception will actually contain the HttpWebResponse object with the StatusDescription set. The samples below are from MSDN:
public static void GetPage(String url) { try { // Creates an HttpWebRequest for the specified URL. HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url); // Sends the HttpWebRequest and waits for a response. HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse(); if (myHttpWebResponse.StatusCode == HttpStatusCode.OK) Console.WriteLine("\r\nResponse Status Code is OK and StatusDescription is: {0}", myHttpWebResponse.StatusDescription); // Releases the resources of the response. myHttpWebResponse.Close(); } catch(WebException e) { Console.WriteLine("\r\nWebException Raised. The following error occured : {0}",e.Status); } catch(Exception e) { Console.WriteLine("\nThe following Exception was raised : {0}",e.Message); } }Source: http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.statuscode.aspx
To actually get at the status, you'll need to get the HttpWebResponse object from the exception itself:
try { // Create a web request for an invalid site. Substitute the "invalid site" strong in the Create call with a invalid name. HttpWebRequest myHttpWebRequest = (HttpWebRequest) WebRequest.Create("invalid site"); // Get the associated response for the above request. HttpWebResponse myHttpWebResponse = (HttpWebResponse) myHttpWebRequest.GetResponse(); myHttpWebResponse.Close(); } catch(WebException e) { Console.WriteLine("This program is expected to throw WebException on successful run."+ "\n\nException Message :" + e.Message); if(e.Status == WebExceptionStatus.ProtocolError) { Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode); Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription); } } catch(Exception e) { Console.WriteLine(e.Message); }Source: http://msdn.microsoft.com/en-us/library/system.net.webexception.status.aspx
Arjan : Errrr, how is this any different from earlier answers? -
I can't tell if it's a copy/paste thing, but the "Uri:" header is on the same line as the status code -- that could be an issue.
Most reason codes are a few words without a ":" and without quotes: http://tools.ietf.org/html/rfc2616#section-6.1.1 So I suspect that the header parser thinks that "Message:" is the start of an HTTP header (check webResponse.Headers["Message"]).
You could add a header (say, X-Error-Details) instead.
0 comments:
Post a Comment