流星小筑
火流星一闪即逝,只留给人们许下心愿的瞬间

导航

 
                   90%使用WebDAV开发的Exchange邮件管理(二)
                                                                     ——Hello,获取未读邮件数!
    
        但凡学习一种新的编程语言,书中的第一个范例都是经典的“Hello,World”。初次尝试使用WebDAV,也得找一个基本的例子试试,以对其有一个感性的认识,我的例子是用来获取未读邮件数目的,所以就有了如上的小标题。
        首先在SDK中搜索WebDAV,找到一些范例,看了看,有一个Getting a List of Folders (WebDAV) ,和所要实现的功能有点贴近。不管三七二十一。运行一下代码吧: 
  1using System;
  2using System.Net;
  3using System.IO;
  4using System.Text;
  5using System.Xml;
  6
  7namespace ExchangeSDK.Snippets.CSharp
  8{
  9   class GettingListOfFoldersWebDAV
 10   {
 11      [STAThread]
 12      static void Main(string[] args)
 13      {
 14         // Variables.
 15         System.Net.HttpWebRequest Request;
 16         System.Net.WebResponse Response;
 17         System.Net.CredentialCache MyCredentialCache;
 18         string strRootURI = "http://server/TestStore/TestStoreFolder/";
 19         string strUserName = "UserName";
 20         string strPassword = "!Password";
 21         string strDomain = "Domain";
 22         string strQuery ="";
 23         byte[] bytes = null;
 24         System.IO.Stream RequestStream = null;
 25         System.IO.Stream ResponseStream = null;
 26         System.Xml.XmlTextReader XmlReader = null;
 27
 28         try
 29         {
 30            // Build the SQL query.
 31            strQuery = "<?xml version=\"1.0\"?><D:searchrequest xmlns:D = \"DAV:\" >";
 32            strQuery += "<D:sql>SELECT \"DAV:href\" FROM scope('hierarchical traversal of \"";
 33            strQuery += strRootURI + "\"')</D:sql></D:searchrequest>";
 34
 35            // Create a new CredentialCache object and fill it with the network
 36            // credentials required to access the server.
 37            MyCredentialCache = new System.Net.CredentialCache();
 38            MyCredentialCache.Add( new System.Uri(strRootURI),
 39               "NTLM",
 40               new System.Net.NetworkCredential(strUserName, strPassword, strDomain)
 41               );
 42
 43            // Create the HttpWebRequest object.
 44            Request = (System.Net.HttpWebRequest)HttpWebRequest.Create(strRootURI);
 45
 46            // Add the network credentials to the request.
 47            Request.Credentials = MyCredentialCache;
 48
 49            // Specify the method.
 50            Request.Method = "SEARCH";
 51
 52            // Encode the body using UTF-8.
 53            bytes = Encoding.UTF8.GetBytes((string)strQuery);
 54
 55            // Set the content header length.  This must be
 56            // done before writing data to the request stream.
 57            Request.ContentLength = bytes.Length;
 58
 59            // Get a reference to the request stream.
 60            RequestStream = Request.GetRequestStream();
 61
 62            // Write the SQL query to the request stream.
 63            RequestStream.Write(bytes, 0, bytes.Length);
 64
 65            // Close the Stream object to release the connection
 66            // for further use.
 67            RequestStream.Close();
 68
 69            // Set the content type header.
 70            Request.ContentType = "text/xml";
 71
 72            // Send the SEARCH method request and get the
 73            // response from the server.
 74            Response = (HttpWebResponse)Request.GetResponse();
 75
 76            // Get the XML response stream.
 77            ResponseStream = Response.GetResponseStream();
 78
 79            // Create the XmlTextReader object from the XML
 80            // response stream.
 81            XmlReader = new XmlTextReader(ResponseStream);
 82
 83            // Read through the XML response, node by node.
 84            while(XmlReader.Read())
 85            {
 86               // Look for the opening DAV:href node.  The DAV: namespace is
 87               //typically assigned the a: prefix in the XML response body.
 88               if(XmlReader.Name == "a:href")
 89               {
 90                  // Advance the reader to the text node.
 91                  XmlReader.Read();
 92
 93                  // Display the value of the DAV:href text node.
 94                  Console.WriteLine("Value: " + XmlReader.Value);
 95                  Console.WriteLine("");
 96
 97                  //Advance the reader to the closing DAV:href node.
 98                  XmlReader.Read();
 99               }

100            }

101
102            // Clean up.
103            XmlReader.Close();
104            ResponseStream.Close();
105            Response.Close();
106
107         }

108         catch(Exception ex)
109         {
110            // Catch any exceptions. Any error codes from the SEARCH
111            // method request on the server will be caught here, also.
112            Console.WriteLine(ex.Message);
113         }

114      }

115   }

116}

117
118
        31~33行构造了Web Storage System SQL查询的XML,去头去尾,对我们比较关键就是SELECT "DAV:href" FROM scope('hierarchical traversal of "+strRootURI+')。SQL查询相信大家都会的了。“DAV:href”是DAV属性,表示条目的URL。其他的还包括:DAV:displayname(条目通用名称)、DAV:isfolder(表示这个条目是否文件夹),DAV:则是Web Storage System(WSS)的名称空间了,当然还有如下的名称空间:“http://schemas.microsoft.com/exchange/”,“urn-schemas:calendar:”,“Urn:schemas:httpmail:”等等。各项具体属性可以在Exchange SDK中根据索引查找。scope是用于指定查询的位置和深度。而strRootURI则是要查询条目的路径。在Exchange中的每个条目都可以通过URL访问,其所有编程任务也是以URL为基础的。URL分为文件URL和HTTP URL,形式分别如下:
file://./backofficestorage/<domain-name>/<public -folder-tree-name>/<path>
http://<server-name>/<virtual-directory>/<virtual-path> 
        因此,我们可以拼接查询未读邮件数的查询语句
    strQuery = "<?xml version=\"1.0\"?><D:searchrequest xmlns:D = \"DAV:\" >"
                    
+ "<D:sql>SELECT \"DAV:displayname\",\"urn:schemas:httpmail:unreadcount\" FROM \"" + strRootURI + "\""
                    
+ "WHERE \"DAV:ishidden\" = false AND \"DAV:isfolder\" = false"
                    
+ "</D:sql></D:searchrequest>";
其中strRootURI="http://servername/exchagne/useralias" 。
        37~41行创建了用于访问资源的NTLM的凭据。60行以后则是通过将服务器返回XML解析,通过查找XML节点中的属性得到查询结果。在这里,我实在搞不清楚XML节点属性名称有哪些,且在不同的方法下,形如a:displayname的前缀到底是指DAV:还是其他的名称空间,就干脆把后半段的方法改写了,直接将XML输出到文件中,方便查看。(顺便也学习了一下System.IO)
    // Get the XML response stream.
                ResponseStream = Response.GetResponseStream();


                System.IO.StreamReader reader 
= new StreamReader(ResponseStream);
                
string xml = reader.ReadToEnd();
                
                FileInfo textfile
=new FileInfo(@"C:\1.xml");
            
                
                StreamWriter outStream
=textfile.CreateText();    
                    
                outStream.Write(xml);
                outStream.Close();
最后,根据各种不同查询的尝试,及得到的XML文件的反馈,最终得到完整的查询未读邮件代码如下:
private int GetUnReadMailCount()
        
{
            
string url=ConfigurationSettings.AppSettings["ExchangeServer"];    
            System.Net.HttpWebRequest Request;
            System.Net.WebResponse Response;
            System.Net.CredentialCache MyCredentialCache;
            
string strRootURI = url+"/"+User.Identity.Name;
            
string strUserName = User.Identity.Name;
            
string strPassword = DAL.Data.UserModel.SelectByUserId(User.Identity.Name).Password.Trim();
            
string strDomain = ConfigurationSettings.AppSettings["ExchangeDomain"];
            
string strQuery ="";
            
byte[] bytes = null;
            System.IO.Stream RequestStream 
= null;
            System.IO.Stream ResponseStream 
= null;
            XmlDocument ResponseXmlDoc 
= null;
            XmlNodeList HrefNodes
= null;
            XmlNodeList SizeNodes
= null;
            
int count=0;
            
try
            
{
                
// Build the SQL query.
                strQuery = "<?xml version=\"1.0\"?><D:searchrequest xmlns:D = \"DAV:\" >"
                    
+ "<D:sql>SELECT \"DAV:displayname\",\"urn:schemas:httpmail:unreadcount\" FROM \"" + strRootURI + "\""
                    
//    +"where \"DAV:contentclass\"=\"urn:schemas:httpmail:read \""            
                    
//        + "WHERE \"DAV:ishidden\" = false AND \"DAV:isfolder\" = false"
                    + "</D:sql></D:searchrequest>";

                
// 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(strRootURI),
                    
"NTLM",
                    
new System.Net.NetworkCredential(strUserName, strPassword, strDomain)
                    );

                
// Create the HttpWebRequest object.
                Request = (System.Net.HttpWebRequest)HttpWebRequest.Create(strRootURI);

                
// Add the network credentials to the request.
                Request.Credentials = MyCredentialCache;

                
// Specify the method.
                Request.Method = "SEARCH";

                
// Encode the body using UTF-8.
                bytes = Encoding.UTF8.GetBytes((string)strQuery);

                
// 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 SQL query 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";

                
// Send the SEARCH method request and get the
                
// response from the server.
                Response = (HttpWebResponse)Request.GetResponse();
        
                
// Get the XML response stream.
                ResponseStream = Response.GetResponseStream();
            
                
// Create the XmlDocument object from the XML response stream.
                ResponseXmlDoc = new XmlDocument();
                ResponseXmlDoc.Load(ResponseStream);
                HrefNodes 
= ResponseXmlDoc.GetElementsByTagName("a:displayname");
                SizeNodes 
= ResponseXmlDoc.GetElementsByTagName("d:unreadcount");
                
for(int i=0;i<HrefNodes.Count;i++)
                
{
                    
if(HrefNodes[i].InnerText=="收件箱")
                        count
=int.Parse(SizeNodes[i].InnerText);
                }

                ResponseStream.Close();
                Response.Close();
            }

            
catch(Exception)
            
{
                
// Catch any exceptions. Any error codes from the SEARCH
                
// method request on the server will be caught here, also.
                return -1;
            }

            
return count;
        }


名词解释:
Web Storage System:是一项数据库技术,随着Windows2000操作系统引入的,可用于存储、共享和管理很多类型的数据。WSS被组织为文件夹体系的形式。

posted on 2005-10-09 11:25  风渐寒pro  阅读(1378)  评论(2编辑  收藏  举报