Link to home
Start Free TrialLog in
Avatar of Ron_Monteclavo
Ron_Monteclavo

asked on

Exchange Public Folder Query Using VB.NET

Hello,

I have a problem that I have been trying to resolve for a bit but cannot seem to find any good source examples or reasons why I keep getting an error with the code below.  The code is simply to query the Public Folders of an Exchange server for a specific folder and get its size in order to assign the size value to the text of the label on the form.  So far I am constantly getting a Forbidden error also shown below.  The credentials I am passing are of an account that has basically 'god' access to Exchange just so I can be sure the permissions are not the issue.

My final goal is not only to be able to get this working correctly, but to also remove the need to pass a username and password and to rather have the credentials of the identity used running the website.

Thanks in Advance.

### Start Code
Imports System.Net
Imports System.Web
Imports System.IO


Partial Class applications_user_testpf
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        ' Variables.
        Dim Request As System.Net.HttpWebRequest
        Dim Response As System.Net.HttpWebResponse
        Dim MyCredentialCache As System.Net.CredentialCache
        Dim strPassword As String
        Dim strDomain As String
        Dim strUserName As String
        Dim strSrcURI As String
        Dim strBody As String
        Dim bytes() As Byte
        Dim RequestStream As System.IO.Stream
        Dim ResponseStream As System.IO.Stream
        Dim ResponseXmlDoc As System.Xml.XmlDocument
        Dim DisplayNameNodes As System.Xml.XmlNodeList

        ' Initialize variables.
        strUserName = "account"
        strPassword = "password"
        strDomain = "corp"
        strSrcURI = "http://server/Exadmin/admin/org/PUBLIC%20FOLDERS/Test"

        ' Build the PROPFIND request body.
        strBody = "<?xml version=""1.0"" ?><D:propfind xmlns:D=""DAV:"" xmlns:E=""http://schemas.microsoft.com/mapi/proptag/""><D:prop><E:x0e080014 /></D:prop></D:propfind>"

        ' Create a new CredentialCache object and fill it with the network
        ' credentials required to access the server.
        MyCredentialCache = New System.Net.CredentialCache
        MyCredentialCache.Add(New System.Uri(strSrcURI), "NTLM", New System.Net.NetworkCredential(strUserName, strPassword, strDomain))

        ' Create the PUT HttpWebRequest object.
        Request = CType(System.Net.WebRequest.Create(strSrcURI),  _
        System.Net.HttpWebRequest)

        ' Add the network credentials to the request.
        Request.Credentials = MyCredentialCache

        ' Specify the PROPFIND method.
        Request.Method = "PROPFIND"

        ' Encode the body using UTF-8.
        bytes = System.Text.Encoding.UTF8.GetBytes(strBody)

        ' Set the content header length.  This must be
        ' done before writing data to the request stream.
        Request.ContentLength = bytes.Length

        ' Get a reference to the request stream.
        RequestStream = Request.GetRequestStream()

        ' Write the message body to the request stream.
        RequestStream.Write(bytes, 0, bytes.Length)

        ' Close the Stream object to release the connection
        ' for further use.
        RequestStream.Close()

        ' Set the Content Type header.
        Request.ContentType = "text/xml"

        ' Set the Depth header.
        Request.Headers.Add("Depth", "0")

        ' Set the Translate header.
        Request.Headers.Add("Translate", "F")

        ' Send the PROPFIND method request and get the
        ' response from the server.
        Response = CType(Request.GetResponse(), System.Net.HttpWebResponse)

        ' Get the XML response stream.
        ResponseStream = Response.GetResponseStream()

        ' Create the XmlDocument object from the XML response stream.
        ResponseXmlDoc = New System.Xml.XmlDocument
        ResponseXmlDoc.Load(ResponseStream)

        ' Build a list of the DAV:href XML nodes, corresponding to the folders
        ' in the mailbox.  The DAV: namespace is typically assgigned the a:
        ' prefix in the XML response body.
        DisplayNameNodes = ResponseXmlDoc.GetElementsByTagName("E:x0e080014")

        ' Display the item's display name.
        Label1.Text = DisplayNameNodes(0).InnerText

        ' Clean up.
        ResponseStream.Close()
        Response.Close()

    End Sub

End Class
### End Code

### Error Received
The remote server returned an error: (403) Forbidden.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Net.WebException: The remote server returned an error: (403) Forbidden.

Source Error:


Line 76:         ' Send the PROPFIND method request and get the
Line 77:         ' response from the server.
Line 78:         Response = CType(Request.GetResponse(), System.Net.HttpWebResponse)
Line 79:
Line 80:         '
### End Error
 
Avatar of LeeDerbyshire
LeeDerbyshire
Flag of United Kingdom of Great Britain and Northern Ireland image

There are about 20 different types of 403 response in IIS, but the most common is 403.4 - SSL Required.  If you have SSL required on the exadmin VDir in IIS, then you will need to have https at the beginning of your strSrcURI .
Avatar of Ron_Monteclavo
Ron_Monteclavo

ASKER

No this is not the case, SSL is not required.  However, I did finally figure out why it was having an issue connecting.  I was getting a 403.6 error, the IP address needed to be added to the grant access list of the IIS server for the webite.
That leaves me with one error still and one question.  The question is how can I make this call with just using the credentials of the identity the web site is running under?
The error I get now though is:
### BEGIN ERROR
Object reference not set to an instance of an object. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error:

Line 91: Line 92: ' Display the item's display name. Line 93: Label1.Text = DisplayNameNodes(0).InnerText Line 94: Line 95: ' Clean up.
###END ERROR
I can only assume maybe I am using the wrong property tags for the query or maybe innnertext is not the correct porperty to check.  I will see if I can find additional information on the property tags to verify I have the right ones.
If you have anonymous access enabled on the page, then it will try to access Exchange anonymously, which doesn't usually work (unless you allow anonymous access on that particular folder), otherwise you will need to have the credentials in the script.  If the page is protected by some kind of authentication, it should use the credentials supplied when you accessed it.

As far as the error you are seeing is concerned, I would make sure that you are actuallt getting a good XML response to the query before actually trying to get the node and display it.  Try displaying the ResponseStream and then stopping execution.
Sorry for the delay in this, but was pulled away for another project.  I was able to get back to this and currently I am able to get this as an output:
http://<server>/Exadmin/admin/domain.com/PUBLIC%20FOLDERS/Wintel%20Messaging/Voltage/HTTP/1.1 200 OK3191034
However, I am trying to get just the value, which is 3191034 rather than the full string of text.  Do I need to change the way I am calling the tag?
ASKER CERTIFIED SOLUTION
Avatar of LeeDerbyshire
LeeDerbyshire
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial