Continuing with the last post on authentication issues with wsdl.exe-generated SOAP proxies, you may need to handle HTTP status codes to provide custom exceptions. To do this, the SoapHttpClientProtocol class (actually its parent HttpWebClientProtocol) provides a pair of GetWebResponse() methods for derived classes to override. One method is for synchronous calls and the other for asynchronous.
The following code shows how to generate a custom exception for the HTTP 401 Unauthorized code.
using System;using System.Net; public class MyProxy : WsdlExeGeneratedProxy{ protected override WebRequest GetWebRequest(Uri uri) { HttpWebRequest request = base.GetWebRequest(uri) as HttpWebRequest; request.Headers.Add("accept-language", CultureInfo.CurrentUICulture.Name); request.Credentials = m_state.Credentials; return request; } protected override WebResponse GetWebResponse(WebRequest request) { HttpWebResponse response = base.GetWebResponse(request) as HttpWebResponse; ThrowIfUnauthorized(response); return response; } protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) { HttpWebResponse response = base.GetWebResponse(request, result) as HttpWebResponse; ThrowIfUnauthorized(response); return response; } private void ThrowIfUnauthorized(HttpWebResponse response) { // There are cases where response can be null (dropped network connection is one). if (response != null && response.StatusCode == HttpStatusCode.Unauthorized) { throw new UnauthorizedException(response); } } internal SomeObject m_state;}
public class UnauthorizedException : ApplicationException{ public UnauthorizedException(HttpWebResponse response) { m_response = response; } internal HttpWebResponse m_response;}
In my last post on authentication and SOAP proxies, I mentioned setting the Credentials property on the wsdl.exe-generated proxy object. Another way to do it and do other things is to override the GetWebRequest() method.
In the following example, the culture is set in the standard HTTP header to tell the server what culture to use for any formatted data, and the credentials are set directly from some object in the app that holds the credentials. The advantage of setting the credentials this way is that we don't have to know whether the credentials have changed -- we always get them from the main location before sending each SOAP request.
internal class MyProxy : WsdlExeGeneratedProxy { // Customize the web request. protected override WebRequest GetWebRequest(Uri uri) { HttpWebRequest request = base.GetWebRequest(uri) as HttpWebRequest; request.Headers.Add("accept-language", CultureInfo.CurrentUICulture.Name); request.Credentials = m_state.Credentials; return request; } internal SomeObject m_state; }
If you are using Whidbey Beta 1, check out the article on MSDN about the new SOAP proxy generation options, including generating the proxy assembly at build time (rather than the default of generating and building an assembly at runtime) and how to turn on compression.