WebDAV Issues After Upgrade to Exchange 2003

G

George Durzi

We recently upgraded to Exchange2K3/W2K3 from Exchange2K/W2K, and some of my
c# code that I used to access users' contacts using WebDAV has stopped
working. I'm getting a 401 unauthorized error. Hopefully, I can explain this
adequately.

Prior to the upgrade the following code was working properly.
FYI: The site was running in the context of the domain administrator, and
was also using the Administrator account to create a CredentialCache to
access Exchange

This function accepts my URI:
http://myMailServer/exchange/userLogin/contacts/?Cmd=contents

#region FetchContactsXml
private string FetchContactsXml(string sSourceURL)
{
StringBuilder sbPayload = new StringBuilder();
sbPayload.Append("<?xml version=\"1.0\"?>");
sbPayload.Append("<a:searchrequest xmlns:a=\"DAV:\">");
sbPayload.Append("<sql> SELECT \"urn:schemas:contacts:fileas\" ");
sbPayload.Append(", \"urn:schemas:contacts:givenName\" ");
sbPayload.Append(", \"urn:schemas:contacts:sn\" ");
sbPayload.Append(", \"urn:schemas:contacts:blush:\" ");
sbPayload.Append("FROM Scope('SHALLOW TRAVERSAL OF \"\"') ");
sbPayload.Append("Where \"DAV:isfolder\" = false AND \"DAV:contentclass\"
");
sbPayload.Append("= 'urn:content-classes:person'");
sbPayload.Append(" ORDER BY \"urn:schemas:contacts:fileas\" ASC");
sbPayload.Append("</>");
sbPayload.Append("</>");

// Array to hold Xml Payload
byte[] arPayload = null;

try
{
// Get Payload and Encode it to utf-8
arPayload = Encoding.UTF8.GetBytes((string)sbPayload.ToString());

// Create HTTP Web Request & Set Properties
HttpWebRequest oWebRequest =
(System.Net.HttpWebRequest)HttpWebRequest.Create(sSourceURL);
oWebRequest.Method = "SEARCH";
oWebRequest.ContentType = "text/xml";
oWebRequest.ContentLength = arPayload.Length;

// Inject the Search Payload into the RequestStream
Stream oRequestStream = oWebRequest.GetRequestStream();
oRequestStream.Write(arPayload, 0, arPayload.Length);
oRequestStream.Close();

// Set Credentials to Access Exchange Store
oWebRequest.Credentials = CreateCredentialCache(sSourceURL);

// Create the Web Response Object
System.Net.WebResponse oWebResponse = (System.Net.WebResponse)
oWebRequest.GetResponse();
// Get the Xml Response Stream
Stream oStream = oWebResponse.GetResponseStream();
// utf-8 handle it
Encoding oEncoding = System.Text.Encoding.GetEncoding("utf-8");
StreamReader oStreamReader = new StreamReader(oStream, oEncoding);
// Get the WebDAV Xml into a string
string sXmlData = oStreamReader.ReadToEnd();

// Clean Up
oStreamReader.Close();
oStream.Close();
oWebResponse.Close();

// Return the Xml string
return sXmlData;
}
catch (Exception oException)
{
ExceptionManager.Publish(oException);
throw(oException);
}
}
#endregion

#region CreateCredentialCache
private CredentialCache CreateCredentialCache(string sSourceURL)
{
try
{
CredentialCache oCredentialCache = new CredentialCache();
oCredentialCache.Add(
new System.Uri(sSourceURL),
"NTLM",
new NetworkCredential(
ConfigurationSettings.AppSettings["ExchangeAdminAccount"].ToString(),
@ConfigurationSettings.AppSettings["ExchangeAdminAccountPwd"].ToString(),
ConfigurationSettings.AppSettings["DomainName"].ToString()));

return oCredentialCache;
}
catch (Exception oException)
{
ExceptionManager.Publish(oException);
throw(oException);
}
}
#endregion

As I said, all of this worked perfectly before the upgrade. Now apparently
Exchange 2003 doesn't allow the Administrator account to have permissions on
all other account by default - which is a good thinkg since I shouldn't have
been using that anyway. So our exchange admin created an account for me to
use with the necessary permissions.

I verified that the account he created can access a user's contacts folder
by browsing to http://myMailServer/exchange/userLogin/contacts/?Cmd=contents
and logging in as DOMAIN\account, password. I was able to open any user's
contacts folder that I wanted to.


Ok, so after the upgrade, the code breaks at the following spot:
Stream oRequestStream = oWebRequest.GetRequestStream();

I noticed that this is before I even attached the CredentialCache, so I
tried moving that to above that point in code, but no change.

The exact exception is:

The remote server returned an error: (401) Unauthorized.


When building the CredentialCache in the CreateCredentialCache function, I
am using that new account I noted that our exchange admin created.

Any help is appreciated.
 
T

Tom Rizzo [MSFT]

And you're not running forms-based authentication or frontend/backend OWA or
anything like that? See if the Exchange Explorer can access your folders
since that's a WebDAV client as well.

Tom

--
Looking for a good book on programming Exchange, Outlook, ADSI and
SharePoint? Check out http://www.microsoft.com/MSPress/books/5517.asp



George Durzi said:
We recently upgraded to Exchange2K3/W2K3 from Exchange2K/W2K, and some of
my c# code that I used to access users' contacts using WebDAV has stopped
working. I'm getting a 401 unauthorized error. Hopefully, I can explain
this adequately.

Prior to the upgrade the following code was working properly.
FYI: The site was running in the context of the domain administrator, and
was also using the Administrator account to create a CredentialCache to
access Exchange

This function accepts my URI:
http://myMailServer/exchange/userLogin/contacts/?Cmd=contents

#region FetchContactsXml
private string FetchContactsXml(string sSourceURL)
{
StringBuilder sbPayload = new StringBuilder();
sbPayload.Append("<?xml version=\"1.0\"?>");
sbPayload.Append("<a:searchrequest xmlns:a=\"DAV:\">");
sbPayload.Append("<sql> SELECT \"urn:schemas:contacts:fileas\" ");
sbPayload.Append(", \"urn:schemas:contacts:givenName\" ");
sbPayload.Append(", \"urn:schemas:contacts:sn\" ");
sbPayload.Append(", \"urn:schemas:contacts:blush:\" ");
sbPayload.Append("FROM Scope('SHALLOW TRAVERSAL OF \"\"') ");
sbPayload.Append("Where \"DAV:isfolder\" = false AND
\"DAV:contentclass\" ");
sbPayload.Append("= 'urn:content-classes:person'");
sbPayload.Append(" ORDER BY \"urn:schemas:contacts:fileas\" ASC");
sbPayload.Append("</>");
sbPayload.Append("</>");

// Array to hold Xml Payload
byte[] arPayload = null;

try
{
// Get Payload and Encode it to utf-8
arPayload = Encoding.UTF8.GetBytes((string)sbPayload.ToString());

// Create HTTP Web Request & Set Properties
HttpWebRequest oWebRequest =
(System.Net.HttpWebRequest)HttpWebRequest.Create(sSourceURL);
oWebRequest.Method = "SEARCH";
oWebRequest.ContentType = "text/xml";
oWebRequest.ContentLength = arPayload.Length;

// Inject the Search Payload into the RequestStream
Stream oRequestStream = oWebRequest.GetRequestStream();
oRequestStream.Write(arPayload, 0, arPayload.Length);
oRequestStream.Close();

// Set Credentials to Access Exchange Store
oWebRequest.Credentials = CreateCredentialCache(sSourceURL);

// Create the Web Response Object
System.Net.WebResponse oWebResponse = (System.Net.WebResponse)
oWebRequest.GetResponse();
// Get the Xml Response Stream
Stream oStream = oWebResponse.GetResponseStream();
// utf-8 handle it
Encoding oEncoding = System.Text.Encoding.GetEncoding("utf-8");
StreamReader oStreamReader = new StreamReader(oStream, oEncoding);
// Get the WebDAV Xml into a string
string sXmlData = oStreamReader.ReadToEnd();

// Clean Up
oStreamReader.Close();
oStream.Close();
oWebResponse.Close();

// Return the Xml string
return sXmlData;
}
catch (Exception oException)
{
ExceptionManager.Publish(oException);
throw(oException);
}
}
#endregion

#region CreateCredentialCache
private CredentialCache CreateCredentialCache(string sSourceURL)
{
try
{
CredentialCache oCredentialCache = new CredentialCache();
oCredentialCache.Add(
new System.Uri(sSourceURL),
"NTLM",
new NetworkCredential(
ConfigurationSettings.AppSettings["ExchangeAdminAccount"].ToString(),

@ConfigurationSettings.AppSettings["ExchangeAdminAccountPwd"].ToString(),
ConfigurationSettings.AppSettings["DomainName"].ToString()));

return oCredentialCache;
}
catch (Exception oException)
{
ExceptionManager.Publish(oException);
throw(oException);
}
}
#endregion

As I said, all of this worked perfectly before the upgrade. Now apparently
Exchange 2003 doesn't allow the Administrator account to have permissions
on all other account by default - which is a good thinkg since I shouldn't
have been using that anyway. So our exchange admin created an account for
me to use with the necessary permissions.

I verified that the account he created can access a user's contacts folder
by browsing to
http://myMailServer/exchange/userLogin/contacts/?Cmd=contents and logging
in as DOMAIN\account, password. I was able to open any user's contacts
folder that I wanted to.


Ok, so after the upgrade, the code breaks at the following spot:
Stream oRequestStream = oWebRequest.GetRequestStream();

I noticed that this is before I even attached the CredentialCache, so I
tried moving that to above that point in code, but no change.

The exact exception is:

The remote server returned an error: (401) Unauthorized.


When building the CredentialCache in the CreateCredentialCache function, I
am using that new account I noted that our exchange admin created.

Any help is appreciated.
 
G

George Durzi

Tom,
Sorry, I'm not too experienced with administering Exchange. Is the Exchange
Explorer when you actually browse in IE to
http:\\exchserver\exchange\login\Inbox, etc..?

If so, yes it works

Tom Rizzo said:
And you're not running forms-based authentication or frontend/backend OWA
or anything like that? See if the Exchange Explorer can access your
folders since that's a WebDAV client as well.

Tom

--
Looking for a good book on programming Exchange, Outlook, ADSI and
SharePoint? Check out http://www.microsoft.com/MSPress/books/5517.asp



George Durzi said:
We recently upgraded to Exchange2K3/W2K3 from Exchange2K/W2K, and some of
my c# code that I used to access users' contacts using WebDAV has stopped
working. I'm getting a 401 unauthorized error. Hopefully, I can explain
this adequately.

Prior to the upgrade the following code was working properly.
FYI: The site was running in the context of the domain administrator, and
was also using the Administrator account to create a CredentialCache to
access Exchange

This function accepts my URI:
http://myMailServer/exchange/userLogin/contacts/?Cmd=contents

#region FetchContactsXml
private string FetchContactsXml(string sSourceURL)
{
StringBuilder sbPayload = new StringBuilder();
sbPayload.Append("<?xml version=\"1.0\"?>");
sbPayload.Append("<a:searchrequest xmlns:a=\"DAV:\">");
sbPayload.Append("<sql> SELECT \"urn:schemas:contacts:fileas\" ");
sbPayload.Append(", \"urn:schemas:contacts:givenName\" ");
sbPayload.Append(", \"urn:schemas:contacts:sn\" ");
sbPayload.Append(", \"urn:schemas:contacts:blush:\" ");
sbPayload.Append("FROM Scope('SHALLOW TRAVERSAL OF \"\"') ");
sbPayload.Append("Where \"DAV:isfolder\" = false AND
\"DAV:contentclass\" ");
sbPayload.Append("= 'urn:content-classes:person'");
sbPayload.Append(" ORDER BY \"urn:schemas:contacts:fileas\" ASC");
sbPayload.Append("</>");
sbPayload.Append("</>");

// Array to hold Xml Payload
byte[] arPayload = null;

try
{
// Get Payload and Encode it to utf-8
arPayload = Encoding.UTF8.GetBytes((string)sbPayload.ToString());

// Create HTTP Web Request & Set Properties
HttpWebRequest oWebRequest =
(System.Net.HttpWebRequest)HttpWebRequest.Create(sSourceURL);
oWebRequest.Method = "SEARCH";
oWebRequest.ContentType = "text/xml";
oWebRequest.ContentLength = arPayload.Length;

// Inject the Search Payload into the RequestStream
Stream oRequestStream = oWebRequest.GetRequestStream();
oRequestStream.Write(arPayload, 0, arPayload.Length);
oRequestStream.Close();

// Set Credentials to Access Exchange Store
oWebRequest.Credentials = CreateCredentialCache(sSourceURL);

// Create the Web Response Object
System.Net.WebResponse oWebResponse = (System.Net.WebResponse)
oWebRequest.GetResponse();
// Get the Xml Response Stream
Stream oStream = oWebResponse.GetResponseStream();
// utf-8 handle it
Encoding oEncoding = System.Text.Encoding.GetEncoding("utf-8");
StreamReader oStreamReader = new StreamReader(oStream, oEncoding);
// Get the WebDAV Xml into a string
string sXmlData = oStreamReader.ReadToEnd();

// Clean Up
oStreamReader.Close();
oStream.Close();
oWebResponse.Close();

// Return the Xml string
return sXmlData;
}
catch (Exception oException)
{
ExceptionManager.Publish(oException);
throw(oException);
}
}
#endregion

#region CreateCredentialCache
private CredentialCache CreateCredentialCache(string sSourceURL)
{
try
{
CredentialCache oCredentialCache = new CredentialCache();
oCredentialCache.Add(
new System.Uri(sSourceURL),
"NTLM",
new NetworkCredential(
ConfigurationSettings.AppSettings["ExchangeAdminAccount"].ToString(),

@ConfigurationSettings.AppSettings["ExchangeAdminAccountPwd"].ToString(),
ConfigurationSettings.AppSettings["DomainName"].ToString()));

return oCredentialCache;
}
catch (Exception oException)
{
ExceptionManager.Publish(oException);
throw(oException);
}
}
#endregion

As I said, all of this worked perfectly before the upgrade. Now
apparently Exchange 2003 doesn't allow the Administrator account to have
permissions on all other account by default - which is a good thinkg
since I shouldn't have been using that anyway. So our exchange admin
created an account for me to use with the necessary permissions.

I verified that the account he created can access a user's contacts
folder by browsing to
http://myMailServer/exchange/userLogin/contacts/?Cmd=contents and logging
in as DOMAIN\account, password. I was able to open any user's contacts
folder that I wanted to.


Ok, so after the upgrade, the code breaks at the following spot:
Stream oRequestStream = oWebRequest.GetRequestStream();

I noticed that this is before I even attached the CredentialCache, so I
tried moving that to above that point in code, but no change.

The exact exception is:

The remote server returned an error: (401) Unauthorized.


When building the CredentialCache in the CreateCredentialCache function,
I am using that new account I noted that our exchange admin created.

Any help is appreciated.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top