当前位置: 代码迷 >> 综合 >> Silverlight 2beta2 调用 SharePoint的WebService......
  详细解决方案

Silverlight 2beta2 调用 SharePoint的WebService......

热度:86   发布时间:2024-01-09 23:58:26.0

    由于Silverlight要访问SharePoint里List的数据,所以需要在Silverlight里调用SharePoint的相应的WebService。

  

    一开始我在VS.net2008里Silverlight工程下添加“Service Reference”时,总是出现“Object reference not set to an instance of an object”这样的错误,添加不了WebService引用,后来查找相关资料,解决了这个问题:

 

              若你也遇到了同样的情况,请先去‘添加/删除软件’里看下Silverlight 2 Beta 2 Tools的安装体积,正常的是1.18M,如果你的是1.4M,那么极有可能是安装问题。有可能你安装了去年12月发布的Blend等软件。

              在Silverlight.net论坛找到一种可行的解决办法:

              1):确定所有与Silverlight相关的应用程序都被卸载

              2):删除以下DLL:C:/Program Files/Microsoft Visual Studio 9.0/Common7/IDE/Microsoft.VisualStudio.ServicesProxy.dll

               以上步骤全部完成后,安装Silverlight 2 Beta 2。

 

      成功添加WebService后,尝试用WebService调用SharePoint里的List信息:

           

  1.  BasicHttpBinding bind = new BasicHttpBinding();
  2.             EndpointAddress endpoint = new EndpointAddress( http://localhost/_vti_bin/Lists.asmx);
  3.             SPListService.ListsSoapClient lsc = new MenuControlForSharePoint.SPListService.ListsSoapClient(bind, endpoint);
  4.             lsc.GetListItemsCompleted += new EventHandler<MenuControlForSharePoint.SPListService.GetListItemsCompletedEventArgs>(lsc_GetListItemsCompleted);
  5.             XElement viewFileds = new XElement("ViewFields",
  6.                                                             new XElement("FieldRef"new XAttribute("Name""Title")),
  7.                                                             new XElement("FieldRef"new XAttribute("Name""Hyperlink")),
  8.                                                             new XElement("FieldRef"new XAttribute("Name""TopLevelLink")),
  9.                                                             new XElement("FieldRef"new XAttribute("Name""ParentLink"))
  10.                                               );
  11.             lsc.GetListItemsAsync("MenuList", nullnull, viewFileds, nullnullnull);

     但运行时总是报错“The remote server returned an unexpected response: (404) Not Found.”。通过找资料,怀疑可能是跨域访问的问题,于是将'clientaccesspolicy.xml'文件放在SharePoint中对应站点的域根目录下,该xml文件内容为:

   

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <access-policy>
  3.   <cross-domain-access>
  4.     <policy>
  5.       <allow-from http-request-headers="*">
  6.         <domain uri="*"/>
  7.       </allow-from>
  8.       <grant-to>
  9.         <resource path="/" include-subpaths="true"/>
  10.       </grant-to>
  11.     </policy>
  12.   </cross-domain-access>
  13. </access-policy>

     但是错误仍然存在,且多方查找资料无果。

 

     为了查找错误根源所在,我在.net下创建了一个B/S的项目,并在该项目中添加WebService来访问SharePoint的Lists.asmx:

  1.             localhost.Lists ls = new SharePoint.localhost.Lists();
  2.             ls.Url = "http://localhost/_vti_bin/Lists.asmx";
  3.             
  4.             XmlDocument xmlDoc = new System.Xml.XmlDocument();
  5.             XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query""");
  6.             XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields""");
  7.             XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions""");
  8.             ndQueryOptions.InnerXml = "<IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>" +  "<DateInUtc>TRUE</DateInUtc>";
  9.             ndViewFields.InnerXml = "<FieldRef Name='Title' />";
  10.             ndQuery.InnerXml = "<Where><And><Gt><FieldRef Name='Field1'/>" +
  11.                                                "<Value Type='Number'>5000</Value></Gt><Gt><FieldRef Name='Field2'/>" +
  12.                                                "<Value Type='DateTime'>2003-07-03T00:00:00</Value></Gt></And></Where>";
  13.      
  14.             XmlNode ndListItems =ls.GetListItems("MenuList"nullnull,ndViewFields, null, ndQueryOptions, null);

       运行时报错“请求因 HTTP 状态 401 失败: Unauthorized。”。估计是没有访问WebService的权限,在调用WebService之前做如下设置则可解决该问题:

  1. ls.Credentials = new System.Net.NetworkCredential("username","password","domain");
  2. 或者
  3. ls.UseDefaultCredentials = true;
  4. 或者:
  5. ls.Credentials = System.Net.CredentialCache.DefaultCredentials;

      但是运行时抛出另外一个异常:“Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown.”

 

      后来通过查找,发现我犯了一个很大的错误。我的SharePoint站点地址为http://localhost ,但在该站点下有一个字站点Document Center ( http://localhost/docs ),我的MenuList list是建立在Document Center下的,所以WebService地址应该是http://localhost/Docs/_vti_bin/Lists.asmx,而不应该是http://localhost/_vti_bin/Lists.asmx

 

       在Silverlight工程中修改这个错误后,运行能够成功调用WebService并返回一个XML文本:

  1. <listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
  2. <rs:data ItemCount="11">
  3.    <z:row ows_Title="Menu1" ows_Hyperlink="http://www.baidu.com, http://www.baidu.com" ows_TopLevelLink="1" ows_MetaInfo="1;#" ows__ModerationStatus="0" ows__Level="1" ows_ID="1" ows_owshiddenversion="1" ows_UniqueId="1;#{E937FAC3-5018-4BF3-B05F-7331C94532A8}" ows_FSObjType="1;#0" ows_Created="2008-08-28 17:16:56" ows_FileRef="1;#Docs/Lists/MenuList/1_.000" />
  4.    <z:row ows_Title="Menu2" ows_Hyperlink="http://www.sina.com.cn, http://www.sina.com.cn" ows_TopLevelLink="1" ows_MetaInfo="2;#" ows__ModerationStatus="0" ows__Level="1" ows_ID="2" ows_owshiddenversion="1" ows_UniqueId="2;#{161B5EF0-B3ED-4BF6-984C-F59ECA89E761}" ows_FSObjType="2;#0" ows_Created="2008-08-28 17:17:10" ows_FileRef="2;#Docs/Lists/MenuList/2_.000" />
  5.    <z:row ows_Title="Menu2:Child1" ows_TopLevelLink="0" ows_ParentLink="Menu2" ows_MetaInfo="3;#" ows__ModerationStatus="0" ows__Level="1" ows_ID="3" ows_owshiddenversion="1" ows_UniqueId="3;#{170D7079-A012-4B4D-B64F-DAE701F1B864}" ows_FSObjType="3;#0" ows_Created="2008-08-28 17:17:24" ows_FileRef="3;#Docs/Lists/MenuList/3_.000" />
  6.   
  7. </rs:data>
  8. </listitems>

 

我试图用Linq来查询这些XML数据:doc.Descendants("z:row"),但结果为null或者报错。后来发现应该将前缀替换一下

 

doc.Descendants("{#RowsetSchema}row"), 这样可以正确运行,但我还不知道这是不是标准的写法。

 

最后完整的解析代码如下:         

  1.  void lsc_GetListItemsCompleted(object sender, MenuControlForSharePoint.SPListService.GetListItemsCompletedEventArgs e)
  2.         {
  3.             XDocument doc = XDocument.Parse(e.Result.ToString());
  4.             var lstMenuInfo = from menuInfo in doc.Descendants("{#RowsetSchema}row").ToList()
  5.                               select new MenuInfo
  6.                               {
  7.                                   Title = (string)menuInfo.Attribute("ows_Title"),
  8.                                   Hyperlink = (string)menuInfo.Attribute("ows_Hyperlink"),
  9.                                   TopLevelLink = (int)menuInfo.Attribute("ows_TopLevelLink") == 1,
  10.                                   ParentLink = (string)menuInfo.Attribute("ows_ParentLink"),
  11.                               };
  12.             // Init menu
  13.             InitMenu(lstMenuInfo);
  14.             //create menu
  15.             menu.Render();
  16.             //exapand all menu items
  17.             menu.ExpandAll();
  18.         }

另外,附带一段Mical给我邮简里的一个示例代码:

  1. // get the blog and photo links
  2. XNamespace msn = http://schemas.microsoft.com/msn/spaces/2005/rss;
  3. XElement elem = XElement.Load(reader);
  4. var query = from item in elem.Descendants("item")
  5. where (string)item.Element(msn + "type").Value == "blogentry"

 

  相关解决方案