zoukankan      html  css  js  c++  java
  • Dynamics CRM 中Web API中的深度创建(Deep Insert)

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复234或者20161105可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!

    以前没有注意到,Web API提供了深度创建的功能,这个功能我简单理解就是具有父子关系(Master-Detail,1:N) 或者N:N关系的两个实体的记录可以通过一个Web API请求来创建。MSDN上的文章 Create an entity using the Web API 有介绍,它的例子是创建一个客户,同时创建这个客户关联的商机,并为刚才创建的商机创建一个任务。
    POST [Organization URI]/api/data/v8.2/accounts HTTP/1.1
    Content-Type: application/json; charset=utf-8
    OData-MaxVersion: 4.0
    OData-Version: 4.0
    Accept: application/json
    
    {
     "name": "Sample Account",
     "primarycontactid":
     {
         "firstname": "John",
         "lastname": "Smith"
     },
     "opportunity_customer_accounts":
     [
      {
          "name": "Opportunity associated to Sample Account",
          "Opportunity_Tasks":
          [
           { "subject": "Task associated to opportunity" }
          ]
      }
     ]
    }
    我这里用代码也写一个例子吧,创建一个罗勇测试实体,并创建它关联的罗勇测试辅助实体,还创建罗勇测试辅助实体的任务。这个比较难找的就是导航的名称。我这里总结方法如下:
    首先打开Metadata页面,比如我这里是 https://demo.luoyong.me/api/data/v8.1/$metadata ,用类似 EntitySet Name="ly_tests" 去搜索,注意ly_tests换成你的实体的复数名称,全是小写。搜索到以后找到 NavigationPropertyBinding 元素的Target属性值为子实体的那个元素,Path属性值(这里是ly_ly_test_ly_testsub_Test)就是需要的。如下图所示:
     
    还有一种方法,就是打开实体,在主实体的 1:N 关系中找到那个与子实体的关系,名称属性便是。
     
    我这里查到的与任务实体的关系的名称是 ly_testsub_Tasks 。
    下面就是全部的代码了:
    var clientURL = Xrm.Page.context.getClientUrl();
    var req = new XMLHttpRequest()
    req.open("POST", encodeURI(clientURL + "/api/data/v9.0/ly_tests", false));//true是异步请求,false是同步请求
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.onreadystatechange = function () {
        if (this.readyState == 4 /* complete */) {
            req.onreadystatechange = null;
            if (this.status == 204) {//204代表成功无返回值
                Xrm.Utility.alertDialog("创建成功的罗勇测试实体记录成功,点击确定后会打开当前记录。");
                Xrm.Utility.openEntityForm(Xrm.Page.data.entity.getEntityName(), this.getResponseHeader("OData-EntityId").match(/w{8}-w{4}-w{4}-w{4}-w{12}/)[0]);
            }
            else {
                var error = JSON.parse(this.response).error;
                Xrm.Utility.alertDialog("错误:" + error.message);
            }
        }
    };
    var requestmsg = {};
    requestmsg.ly_name = "深度创建的罗勇测试记录";
    requestmsg["ly_Lookup@odata.bind"] = "/accounts(CE23165A-3AA3-E511-80C7-000D3A807EC7)";
    requestmsg.ly_integer = 10;
    requestmsg.ly_ly_test_ly_testsub_Test = [];
    requestmsg.ly_ly_test_ly_testsub_Test.push({ 'ly_name': '深度创建的的罗勇测试辅助实体记录1', 'ly_testsub_Tasks': [] });
    requestmsg.ly_ly_test_ly_testsub_Test[0].ly_testsub_Tasks.push({ "subject": "深度创建的任务1" });
    requestmsg.ly_ly_test_ly_testsub_Test[0].ly_testsub_Tasks.push({ "subject": "深度创建的任务2" });
    requestmsg.ly_ly_test_ly_testsub_Test.push({ 'ly_name': '深度创建的的罗勇测试辅助实体记录2' });
    req.send(JSON.stringify(requestmsg));

    下面代码是C#版本:

                    JObject jObject = new JObject(
                        new JProperty("ly_name", "深度创建的罗勇测试记录"),
                        new JProperty("ly_Lookup@odata.bind", "/accounts(CE23165A-3AA3-E511-80C7-000D3A807EC7)"),
                        new JProperty("ly_integer", 10),
                        new JProperty("ly_ly_test_ly_testsub_Test", new JArray(
                            new JObject(
                                new JProperty("ly_name", "深度创建的的罗勇测试辅助实体记录1")),
                            new JObject(
                                new JProperty("ly_name", "深度创建的的罗勇测试辅助实体记录2")),
                            new JObject(
                                new JProperty("ly_testsub_Tasks", new JArray(
                                            new JObject(new JProperty("subject", "深度创建的任务1")),
                                            new JObject(new JProperty("subject", "深度创建的任务2"))
                                        )
                                    )
                                )
                            )
                        )
                    );
                    var newRecordGuid = CreateRecordByWebApiAsync(jObject, "incidents").Result;
            private static async Task<Guid> CreateRecordByWebApiAsync(JObject jObject,string webApiUrl)
            {
                HttpMessageHandler messageHandler;
                HttpResponseMessage response;
                Guid returnGuid = Guid.Empty;
                NetworkCredential credentials = new NetworkCredential(userName, passWord);
                messageHandler = new HttpClientHandler() {
                    Credentials = credentials
                };
                using (HttpClient httpClient = new HttpClient(messageHandler))
                {
                    httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
                    httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
                    httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
                    httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json; charset=utf-8");
                    var content = new StringContent(JsonConvert.SerializeObject(jObject), Encoding.UTF8, "application/json");
                    response = await httpClient.PostAsync($"{webAPIBaseUrl}{webApiUrl}", content);
                    if (response.IsSuccessStatusCode)
                    {
                        var newRecordUri = response.Headers.GetValues("OData-EntityId").FirstOrDefault();
                        returnGuid = new Guid(newRecordUri.Substring(newRecordUri.Length - 37, 36));
                    }
                    else
                    {
                        var errorMsg = await response.Content.ReadAsStringAsync();
                        throw new Exception(errorMsg);
                    }
                }
                return returnGuid;
            }
  • 相关阅读:
    程序集冲突问题
    Linux 菜鸟学习笔记--系统分区
    gawk
    Ansible
    Linux 网关及路由
    Linux档案与目录管理
    find命令
    sed详解
    FTP服务
    Gentoo安装(虚拟机)
  • 原文地址:https://www.cnblogs.com/luoyong0201/p/Dynamics_365_JavaScript_Deep_Insert_Web_API.html
Copyright © 2011-2022 走看看