Web API 機能およびアクションのサンプル (C#)

注意

エンティティとテーブルの違いがわかりませんか? Microsoft Dataverse で「開発者: 用語を理解する」を参照してください。

このサンプルは、バインドされた関数とバインドされていない関数およびアクションを実行する方法を示します。このアクションには、Microsoft Dataverse Web API を使用するカスタム アクションが含まれます。

注意

このサンプルは、Web API 機能およびアクションのサンプル で説明されている操作を提供します。 このサンプルでは、メッセージング、パフォーマンス強化、およびエラー処理のための CDSWebApiService クラス メソッドも使用します。

前提条件

すべての Dataverse Web API C# サンプルの前提条件は、親トピックの Web API サンプル (C#)前提条件 セクションで説明されています。

このサンプルを実行する方法

PowerApps - サンプル GitHub リポジトリに移動して、サンプル リポジトリをクローンもしくはダウンロードし、ローカル フォルダに内容を解凍してください。 cds/webapi/C#/FunctionsAndActions フォルダに移動します。 このフォルダには、次のファイルが含まれている必要があります。

ファイル 目的/説明
Program.cs このサンプルのプライマリ ソース コードが含まれます。
App.config プレースホルダー Dataverse サーバー接続情報を含むアプリケーション構成ファイルです。 このファイルはリポジトリのいくつかの Web API のサンプルと共有されます。 ひとつのサンプル用に接続情報を構成する場合、同じ構成の他のサンプルを実行できます。
FunctionsAndActions.sln
FunctionsAndActions.csproj
Packages.config
AssemblyInfo.cs
このサンプルの標準 Visual Studio 2019 ソリューション、プロジェクト、 NuGet パッケージ構成、およびアセンブリ情報ファイルです。
WebAPIFunctionsandActions_1_0_0_0_managed.zip このサンプルによって追加された 2 つのカスタム アクションを含むカスタム管理ソリューション。

次に、以下の手順を使用して、このサンプルを実行します。

  1. Dynamics 365 Customer Engagement (設定 > ソリューション)、または Power Apps (ソリューション) を使用して、提供されたソリューション (.zip) ファイルをテスト環境にインポートします。

  2. ソリューション ファイル FunctionsAndActions.sln を探しダブル クリックして、ソリューションを Visual Studio に読み込みます。 FunctionsAndActions ソリューションを構築します。 これにより、見あたらないまたはアップグレードする必要がある必要なすべての NuGet パッケージは自動的にダウンロードされ、インストールされます。

  3. アプリケーション構成ファイル、App.config を編集し、Dataverse サーバーに接続情報を指定します。

  4. Visual Studio 内から FunctionsAndActions プロジェクトをビルドして実行します。 すべてのサンプル ソリューションは、既定では、デバッグ モードで実行するように構成されています。

コード一覧

Program.cs 部分一覧

sing System;
using System.Collections.Generic;
using System.Configuration;
using System.Net;

namespace PowerApps.Samples
{
    /// <summary>
    /// This program demonstrates use of functions and actions with the 
    /// Power Platform data service Web API.
    /// </summary>
    /// <remarks>Be sure to fill out App.config with your test environment information
    /// and import the provided managed solution into your test environment using the web app
    /// before running this program.</remarks>
    /// <see cref="Https://docs.microsoft.com/powerapps/developer/data-platform/webapi/samples/functions-actions-csharp"/>
    public class Program
    {
        public static void Main()
        {
            Console.Title = "Function and Actions demonstration";

            // Track entity instance URIs so those records can be deleted prior to exit.
            Dictionary<string, Uri> entityUris = new Dictionary<string, Uri>();
            
            try
            {
                // Get environment configuration information from the connection string in App.config.
                ServiceConfig config = new ServiceConfig(
                    ConfigurationManager.ConnectionStrings["Connect"].ConnectionString);

                // Use the service class that handles HTTP messaging, error handling, and
                // performance optimizations.
                using (CDSWebApiService svc = new CDSWebApiService(config))
                {
                    // Create any entity instances required by the program code that follows
                    CreateRequiredRecords(svc, entityUris);

                    #region Call an unbound function with no parameters
                    Console.WriteLine("\n* Call an unbound function with no parameters.");

                    // Retrieve the current user's full name from the WhoAmI function:
                    Console.Write("\tGetting information on the current user..");
                    JToken currentUser = svc.Get("WhoAmI");

                    // Obtain the user's ID and full name
                    JToken user = svc.Get("systemusers(" + currentUser["UserId"] + ")?$select=fullname");

                    Console.WriteLine("completed.");
                    Console.WriteLine("\tCurrent user's full name is '{0}'.", user["fullname"]);
                    #endregion Call an unbound function with no parameters

                    #region Call an unbound function that requires parameters
                    Console.WriteLine("\n* Call an unbound function that requires parameters");

                    // Retrieve the code for the specified time zone
                    int localeID = 1033;
                    string timeZoneName = "Pacific Standard Time";

                    // Define the unbound function and its parameters
                    string[] uria = new string[] {
                        "GetTimeZoneCodeByLocalizedName",
                        "(LocalizedStandardName=@p1,LocaleId=@p2)",
                        "?@p1='" + timeZoneName + "'&@p2=" + localeID };

                    // This would also work:
                    // string[] uria = ["GetTimeZoneCodeByLocalizedName", "(LocalizedStandardName='" + 
                    //    timeZoneName + "',LocaleId=" + localeId + ")"]; 

                    JToken localizedName = svc.Get(string.Join("", uria));
                    string timeZoneCode = localizedName["TimeZoneCode"].ToString();

                    Console.WriteLine(
                        "\tThe time zone '{0}' has the code '{1}'.", timeZoneName, timeZoneCode);
                    #endregion Call an unbound function that requires parameters

                    #region Call a bound function   
                    Console.WriteLine("\n* Call a bound function");

                    // Retrieve the total time (minutes) spent on all tasks associated with 
                    // incident "Sample Case".
                    string boundUri = entityUris["Sample Case"] +
                        @"/Microsoft.Dynamics.CRM.CalculateTotalTimeIncident()";

                    JToken cttir = svc.Get(boundUri);
                    string totalTime = cttir["TotalTime"].ToString();

                    Console.WriteLine("\tThe total duration of tasks associated with the incident " +
                        "is {0} minutes.", totalTime);
                    #endregion Call a bound function 

                    #region Call an unbound action that requires parameters
                    Console.WriteLine("\n* Call an unbound action that requires parameters");

                    // Close the existing opportunity "Opportunity to win" and mark it as won.
                    JObject opportClose = new JObject()
                    {
                        { "subject", "Won Opportunity" },
                        { "opportunityid@odata.bind", entityUris["Opportunity to win"] }
                    };

                    JObject winOpportParams = new JObject()
                    {
                        { "Status", "3" },
                        { "OpportunityClose", opportClose }
                    };

                    JObject won = svc.Post("WinOpportunity", winOpportParams);

                    Console.WriteLine("\tOpportunity won.");
                    #endregion Call an unbound action that requires parameters

                    #region Call a bound action that requires parameters
                    Console.WriteLine("\n* Call a bound action that requires parameters");

                    // Add a new letter tracking activity to the current user's queue.
                    // First create a letter tracking instance.
                    JObject letterAttributes = new JObject()
                    {
                        {"subject", "Example letter" },
                        {"description", "Body of the letter" }
                    };

                    Console.Write("\tCreating letter 'Example letter'..");

                    Uri letterUri = svc.PostCreate("letters", letterAttributes);
                    entityUris.Add("Example letter", letterUri);

                    Console.WriteLine("completed.");

                    //Retrieve the ID associated with this new letter tracking activity.
                    JToken letter = svc.Get(letterUri + "?$select=activityid,subject");
                    string letterActivityId = (string)letter["activityid"];

                    // Retrieve the URL to current user's queue.
                    string myUserId = (string)currentUser["UserId"];

                    JToken queueRef = svc.Get("systemusers(" + myUserId + ")/queueid/$ref");
                    string myQueueUri = (string)queueRef["@odata.id"];

                    //Add the letter activity to current user's queue, then return its queue ID.
                    JObject targetUri = JObject.Parse(
                      @"{activityid: '" + letterActivityId + @"', '@odata.type': 'Microsoft.Dynamics.CRM.letter' }");

                    JObject addToQueueParams = new JObject()
                    {
                        { "Target", targetUri }
                    };

                    string queueItemId = (string)svc.Post(
                        myQueueUri + "/Microsoft.Dynamics.CRM.AddToQueue", addToQueueParams)["QueueItemId"];

                    Console.WriteLine("\tLetter 'Example letter' added to current user's queue.");
                    Console.WriteLine("\tQueueItemId returned from AddToQueue action: {0}", queueItemId);
                    #endregion Call a bound action that requires parameters

                    #region Call a bound custom action that requires parameters
                    Console.WriteLine("\n* Call a bound custom action that requires parameters");

                    // Add a note to a specified contact. Uses the custom action sample_AddNoteToContact, which
                    // is bound to the contact to annotate, and takes a single param, the note to add. It also  
                    // returns the URI to the new annotation. 

                    JObject note = JObject.Parse(
                        @"{NoteTitle: 'Sample note', NoteText: 'The text content of the note.'}");
                    string actionUri = entityUris["Jon Fogg"].ToString() + "/Microsoft.Dynamics.CRM.sample_AddNoteToContact";

                    JObject contact = svc.Post(actionUri, note);
                    Uri annotationUri = new Uri(svc.BaseAddress + "annotations(" + contact["annotationid"] + ")");
                    entityUris.Add((string)note["NoteTitle"], annotationUri);

                    Console.WriteLine("\tA note with the title '{0}' was created and " +
                        "associated with the contact 'Jon Fogg'.", note["NoteTitle"]);
                    #endregion Call a bound custom action that requires parameters

                    #region Call an unbound custom action that requires parameters
                    Console.WriteLine("\n* Call an unbound custom action that requires parameters");

                    // Create a customer of the specified type, using the custom action sample_CreateCustomer,
                    // which takes two parameters: the type of customer ('account' or 'contact') and the name of 
                    // the new customer.
                    string customerName = "New account customer (sample)";
                    JObject customerAttributes = JObject.Parse(
                        @"{CustomerType: 'account', AccountName: '" + customerName + "'}");

                    JObject response = svc.Post("sample_CreateCustomer", customerAttributes);
                    Console.WriteLine("\tThe account '" + customerName + "' was created.");

                    // Because the CreateCustomer custom action does not return any data about the created instance, 
                    // we must query the customer instance to figure out its URI.
                    JToken customer = svc.Get("accounts?$filter=name eq 'New account customer (sample)'&$select=accountid&$top=1");
                    Uri customerUri = new Uri(svc.BaseAddress + "accounts(" + customer["value"][0]["accountid"] + ")");
                    entityUris.Add( customerName, customerUri );

                    // Try to call the same custom action with invalid parameters, here the same name is
                    // not valid for a contact. (ContactFirstname and ContactLastName parameters are  
                    // required when CustomerType is contact.
                    customerAttributes = JObject.Parse(
                        @"{CustomerType: 'contact', AccountName: '" + customerName + "'}");

                    try
                    {
                        customerUri = svc.PostCreate("sample_CreateCustomer", customerAttributes);
                        Console.WriteLine("\tCall to the custom CreateCustomer action succeeded, which was not expected.");
                    }
                    catch (AggregateException e)
                    {
                        Console.WriteLine("\tCall to the custom CreateCustomer action did not succeed (as was expected).");
                        foreach (Exception inner in (e as AggregateException).InnerExceptions)
                        { Console.WriteLine("\t  -" + inner.Message); }
                    }
                    #endregion Call an unbound custom action that requires parameters

                    DeleteEntityRecords(svc, entityUris);
                }
            }
            catch (Exception e)
            {
                Console.BackgroundColor = ConsoleColor.Red; // Highlight exceptions
                if ( e is AggregateException )
                {
                    foreach (Exception inner in (e as AggregateException).InnerExceptions)
                    { Console.WriteLine("\n" + inner.Message); }
                }
                else if ( e is ServiceException)
                {
                    var ex = e as ServiceException;
                    Console.WriteLine("\nMessage send response: status code {0}, {1}",
                        ex.StatusCode, ex.ReasonPhrase);
                }
                Console.ReadKey(); // Pause terminal
            }
        }
    }
}

関連項目

Dataverse Web API を使用する
Web API 関数の使用
Web API アクションの使用
Web API のサンプル
Web API 機能およびアクションのサンプル

注意

ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)

この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。