コード スニペット: クライアントの外部リストからアイテム データを取得する

最終更新日: 2010年4月19日

適用対象: SharePoint Server 2010

この記事の内容
説明
前提条件
この例を使用するには

説明

次のコード スニペットは、SharePoint クライアント オブジェクト モデルを使用して、外部リストのリスト アイテム データをクライアント コンピューターから取得する方法を示します。

重要重要

外部リストの ListItem データの "既定の" ClientContext.Load を使用すると、"指定されたキーはディレクトリ内に存在しませんでした。" というエラーが表示されます。代わりに、使用するフィールドを CamlQuery メソッドと、さらに ClientContext.Load メソッドで明示的に指定する必要があります。

前提条件

  • サーバー上の Microsoft SharePoint Server 2010 あるいは Microsoft SharePoint Foundation 2010。

  • サーバー上の少なくとも 1 つの外部リスト。

  • クライアント コンピューター上の Microsoft Office Professional Plus 2010 と Microsoft .NET Framework 3.5。

  • Microsoft Visual Studio。

この例を使用するには

  1. クライアント コンピューターで Visual Studio を開始し、C# コンソール アプリケーション プロジェクトを作成します。プロジェクトを作成するときに、[.NET Framework 3.5] を選択します。

  2. [表示] メニューから、[プロパティ ページ] をクリックしてプロジェクト プロパティを表示します。

  3. [ビルド] タブから、[プラットフォーム ターゲット] で、[Any CPU] を選択します。

  4. プロジェクト プロパティ ウィンドウを閉じます。

  5. [ソリューション エクスプローラー] の [参照設定] で、[System] と [System.Core] を除いて、すべてのプロジェクト参照を削除します。

  6. プロジェクトに以下の参照を追加します。

    1. Microsoft.SharePoint.Client

    2. Microsoft.SharePoint.Client.Runtime

    3. System.Data.Linq

    4. System.XML

  7. この手順の最後に示すコードで、Program.cs で自動生成されたコードを置換します。

  8. <TargetSiteUrl> と <TargetListName> の値を有効な値で置換します。

  9. プロジェクトを保存します。

  10. プロジェクトをコンパイルして、実行します。

using System;
using Microsoft.SharePoint.Client;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.Xml;
using System.IO;
using System.Text;
using System.Globalization;

namespace Microsoft.SDK.Sharepoint.Samples
{
    /// <summary>
    /// This example shows how to retrieve list item data 
    /// from an external list.
    /// 
    /// You'll need to explicitly specify the field data in both
    /// the CAML query and also ClientContext.Load.
    /// </summary>
    class Program
    {
        // Note: Replace these with your actual Site URL and List name.
        private static string TargetSiteUrl = "<TargetSiteUrl>";
        private static string TargetListName = "<TargetListName>";

        /// <summary> 
        /// Example to show using CSOM to retrieve external List data.        
        /// </summary>        
        static void Main(string[] args)
        {
            ClientContext clientContext = new ClientContext(TargetSiteUrl);

            List externalList = clientContext.Web.Lists.GetByTitle(
                TargetListName);

            // To properly construct the CamlQuery and 
            // ClientContext.LoadQuery,
            // we need some View data of the Virtual List.
            // In particular, the View will give us the CamlQuery 
            // Method and Fields.
            clientContext.Load(
                externalList.Views,
                viewCollection => viewCollection.Include(
                    view => view.ViewFields,
                    view => view.HtmlSchemaXml));

            // This tells us how many list items we can retrieve.
            clientContext.Load(clientContext.Site,
                s => s.MaxItemsPerThrottledOperation);

            clientContext.ExecuteQuery();

            // Let's just pick the first View.
            View targetView = externalList.Views[0];
            string method = ReadMethodFromViewXml(
                targetView.HtmlSchemaXml);
            ViewFieldCollection viewFields = targetView.ViewFields;

            CamlQuery vlQuery = CreateCamlQuery(
                clientContext.Site.MaxItemsPerThrottledOperation,
                method,
                viewFields);

            Expression<Func<ListItem, object>>[] listItemExpressions =
                CreateListItemLoadExpressions(viewFields);

            ListItemCollection listItemCollection =
                externalList.GetItems(vlQuery);

            // Note: Due to limitation, you currently cannot use 
            // ClientContext.Load.
            //       (you'll get InvalidQueryExpressionException)
            IEnumerable<ListItem> resultData = clientContext.LoadQuery(
                listItemCollection.Include(listItemExpressions));

            clientContext.ExecuteQuery();

            foreach (ListItem li in resultData)
            {
                // Now you can use the ListItem data!

                // Note: In the CamlQuery, we specified RowLimit of 
                // MaxItemsPerThrottledOperation.
                // You may want to check whether there are other rows 
                // not yet retrieved.                
            }
        }

        /// <summary>
        /// Parses the viewXml and returns the Method value.
        /// </summary>        
        private static string ReadMethodFromViewXml(string viewXml)
        {
            XmlReaderSettings readerSettings = new XmlReaderSettings();
            readerSettings.ConformanceLevel = ConformanceLevel.Fragment;

            XmlReader xmlReader = XmlReader.Create(
                new StringReader(viewXml), readerSettings);
            while (xmlReader.Read())
            {
                switch (xmlReader.NodeType)
                {
                    case XmlNodeType.Element:
                        if (xmlReader.Name == "Method")
                        {
                            while (xmlReader.MoveToNextAttribute())
                            {
                                if (xmlReader.Name == "Name")
                                {
                                    return xmlReader.Value;
                                }
                            }
                        }
                        break;
                }
            }

            throw new Exception("Unable to find Method in View XML");
        }

        /// <summary>
        /// Creates a CamlQuery based on the inputs.
        /// </summary>        
        private static CamlQuery CreateCamlQuery(
            uint rowLimit, string method, ViewFieldCollection viewFields)
        {
            CamlQuery query = new CamlQuery();

            XmlWriterSettings xmlSettings = new XmlWriterSettings();
            xmlSettings.OmitXmlDeclaration = true;

            StringBuilder stringBuilder = new StringBuilder();
            XmlWriter writer = XmlWriter.Create(
                stringBuilder, xmlSettings);

            writer.WriteStartElement("View");

            // Specifies we want all items, regardless of folder level.
            writer.WriteAttributeString("Scope", "RecursiveAll");

            writer.WriteStartElement("Method");
            writer.WriteAttributeString("Name", method);
            writer.WriteEndElement();  // Method

            if (viewFields.Count > 0)
            {
                writer.WriteStartElement("ViewFields");
                foreach (string viewField in viewFields)
                {
                    if (!string.IsNullOrEmpty(viewField))
                    {
                        writer.WriteStartElement("FieldRef");
                        writer.WriteAttributeString("Name", viewField);
                        writer.WriteEndElement();  // FieldRef
                    }
                }
                writer.WriteEndElement();  // ViewFields
            }

            writer.WriteElementString(
                "RowLimit", rowLimit.ToString(CultureInfo.InvariantCulture));

            writer.WriteEndElement();  // View

            writer.Close();

            query.ViewXml = stringBuilder.ToString();

            return query;
        }

        /// <summary>
        /// Returns an array of Expression used in 
        /// ClientContext.LoadQuery to retrieve 
        /// the specified field data from a ListItem.        
        /// </summary>        
        private static Expression<Func<ListItem, object>>[]
            CreateListItemLoadExpressions(
            ViewFieldCollection viewFields)
        {
            List<Expression<Func<ListItem, object>>> expressions =
                new List<Expression<Func<ListItem, object>>>();

            foreach (string viewFieldEntry in viewFields)
            {
                // Note: While this may look unimportant, 
                // and something we can skip, in actuality,
                //       we need this step.  The expression should 
                // be built with local variable.                
                string fieldInternalName = viewFieldEntry;

                Expression<Func<ListItem, object>>
                    retrieveFieldDataExpression =
                    listItem => listItem[fieldInternalName];

                expressions.Add(retrieveFieldDataExpression);
            }

            return expressions.ToArray();
        }
    }
}