Introduction
The HttpWebRequest
class is very useful to work with internet data, but it got some problems. When calling different secure endpoints, only the first is working and for the rest the auth is failing. To be honest, it is a bug in the complete net-platform, and I hope it gets fixed sooner than later.
Background
In digest authorization on Windows Phone 8 is a problem which led me to some trouble and headaches before I figured out the solution.
After some days, I found the solution on stackoverflow which got also mentioned on the MSDN blog.
To understand digest authorization, read this.
Using the Code
The provided code consists of three functions. Hint: It isn't a project, but only the 3 functions.
First creating a request, then writing the soap-message, which got refused and then starting the auth with a own digest. In the end is the link to the stackoverflow postings in which a detailed solution is provided.
private void CreateCall()
{
Uri uri = new Uri(m_SoapEndPoint,UriKind.Absolute);
HttpWebRequest request = WebRequest.Create( uri ) as HttpWebRequest;
request.Method = "POST";
request.UserAgent = "UPnP/1.0 Client 1.0";
request.Headers["SOAPACTION"] = NameSpace + "#" + SoapMethod;
request.ContentType = "text/xml;charset=\"utf-8\"";
request.AllowAutoRedirect = false;
request.UseDefaultCredentials = false;
if( Nonce.Length > 0 ) {
String sAuthentification = GetAuthorizationMd5();
request.Headers[HttpRequestHeader.Authorization] = sAuthentification;
}
IAsyncResult asyncResult = request.BeginGetRequestStream(OnRequestStream, request);
}
private void OnRequestStream( IAsyncResult ar )
{
try
{
if( ar.IsCompleted )
{
HttpWebRequest request = (HttpWebRequest) ar.AsyncState;
using( Stream requestStream = request.EndGetRequestStream( ar ) )
{
using( StreamWriter streamWriter = new StreamWriter( requestStream ) )
{
streamWriter.Write( m_SoapBody );
streamWriter.Flush();
streamWriter.Close();
}
}
IAsyncResult result = request.BeginGetResponse( OnResponseStream, request );
}
}
}
catch (WebException we)
{
m_bRunning = false;
Status = "OnRequestStream mit WebException: " + we.Message;
MessageBox.Show( Status );
}
}
private void OnResponseStream( IAsyncResult ar )
{
try
{
if( ar.IsCompleted )
{
HttpWebRequest request = ar.AsyncState as HttpWebRequest;
using( WebResponse response = request.EndGetResponse( ar ) as HttpWebResponse )
{
using( Stream streamResult = response.GetResponseStream() )
{
using( StreamReader reader = new StreamReader( streamResult ) )
{
m_Response = reader.ReadToEnd();
reader.Close();
NotifySoapResponse();
}
}
}
}
}
catch( NotSupportedException nse )
{
Status = nse.Message;
}
catch( SecurityException se )
{
Status = se.Message;
}
catch( WebException we )
{
Debug.WriteLine( "OnResponseStream-WebException: " + we.Message);
if( Nonce.Length == 0 )
{
HttpWebResponse response = (HttpWebResponse) we.Response;
if( response.StatusCode == HttpStatusCode.Unauthorized )
{
WebHeaderCollection coll = response.Headers;
String authHeader = we.Response.Headers["WWW-Authenticate"];
Debug.WriteLine( "Auth Header " + authHeader );
ComputeAuthAndRestartTheCall();
return;
}
}
else
{
Nonce = "";
}
}
catch( InvalidOperationException ie )
{
Status = ie.Message;
}
}
In ComputeAuthAndRestartTheCall();
, you need to do your md5-auth and restart the call.
Points of Interest
This caused me a lot of trouble and I hope that somebody can learn from it. Here are the links to some interesting websites:
History