通过C#代码调用Dynamics 365 Web API执行批量操作
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复356或者20190830可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!
之前的文章 使用JS通过Web API执行批量操作,多个操作是一个事务! 讲的是JavaScript的做法,今天我实验了一阵子终于搞定了C#做法。
不多说,上代码,这个代码的用途简单,就是新建一个注释,然后将某个注释的stepid字段值设置为Y,两个操作做成一个事务:
private static async Task<string> ExecuteBatch(string ODataBaseUrl)
{
Guid batchId = Guid.NewGuid();
Guid changesetId = Guid.NewGuid();
string returnVal = string.Empty;
StringBuilder requestBody = new StringBuilder();
requestBody.Append($"--batch_{batchId}");
requestBody.Append("\n");
requestBody.Append($"Content-Type: multipart/mixed;boundary=changeset_{changesetId}");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"--changeset_{changesetId}");
requestBody.Append("\n");
requestBody.Append("Content-Type: application/http");
requestBody.Append("\n");
requestBody.Append("Content-Transfer-Encoding:binary");
requestBody.Append("\n");
requestBody.Append("Content-ID: 1");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"POST {ODataBaseUrl}annotations HTTP/1.1");
requestBody.Append("\n");
requestBody.Append("Content-Type: application/json;type=entry");
requestBody.Append("\n");
requestBody.Append("\n");
JObject jObject = new JObject(
new JProperty("subject", "克隆出来的记录"),
new JProperty("filename", "MSFTDynamics365erLuoYong.jpg"),
new JProperty("filesize", ),
new JProperty("documentbody", "/9j/4AAQSkZJRgAB2cFFABRRRQAUUUUAf//Z"
requestBody.Append("\n");
requestBody.Append($"--changeset_{changesetId}");
requestBody.Append("\n");
requestBody.Append("Content-Type: application/http");
requestBody.Append("\n");
requestBody.Append("Content-Transfer-Encoding:binary");
requestBody.Append("\n");
requestBody.Append("Content-ID: 2");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"PUT {ODataBaseUrl}annotations(4B502B89-4520-E911-B0C6-E05D5152C120)/stepid HTTP/1.1");
requestBody.Append("\n");
requestBody.Append("Content-Type: application/json;type=entry");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append("{\"value\":\"Y\"}");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"--changeset_{changesetId}--");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"--batch_{batchId}--");
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create($"{ODataBaseUrl}$batch");
request.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["userName"], ConfigurationManager.AppSettings["passWord"]);
request.Method = "POST";
request.ContentType = $"multipart/mixed;boundary=batch_{batchId}";
request.Accept = "application/json";
request.Headers.Add("OData-MaxVersion", "4.0");
request.Headers.Add("OData-Version", "4.0");
byte[] buffer = Encoding.UTF8.GetBytes(requestBody.ToString());
request.ContentLength = buffer.Length;
using (Stream stream = await request.GetRequestStreamAsync())
{
stream.Write(buffer, , buffer.Length);
stream.Flush();
}
using (WebResponse response = await request.GetResponseAsync())
{
var webResponse = response as HttpWebResponse;
if (webResponse.StatusCode == HttpStatusCode.OK)
{
Stream Answer = response.GetResponseStream();
StreamReader _Answer = new StreamReader(Answer);
returnVal = _Answer.ReadToEnd();
}
else
{
throw new Exception($"Error. {webResponse.StatusCode}");
}
}
return returnVal;
}
我的执行效果如下,我这里是执行成功HTTP STATUS CODE = 200)后显示了返回内容:

如果改成用 HttpClient 来发起请求,代码如下,个人推荐使用这种:
private static async Task<string> ExecuteBatch(string ODataBaseUrl)
{
Guid batchId = Guid.NewGuid();
Guid changesetId = Guid.NewGuid();
string returnVal = string.Empty;
StringBuilder requestBody = new StringBuilder();
requestBody.Append($"--batch_{batchId}");
requestBody.Append("\n");
requestBody.Append($"Content-Type: multipart/mixed;boundary=changeset_{changesetId}");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"--changeset_{changesetId}");
requestBody.Append("\n");
requestBody.Append("Content-Type: application/http");
requestBody.Append("\n");
requestBody.Append("Content-Transfer-Encoding:binary");
requestBody.Append("\n");
requestBody.Append("Content-ID: 1");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"POST {ODataBaseUrl}annotations HTTP/1.1");
requestBody.Append("\n");
requestBody.Append("Content-Type: application/json;type=entry");
requestBody.Append("\n");
requestBody.Append("\n");
JObject jObject = new JObject(
new JProperty("subject", "克隆出来的记录"),
new JProperty("filename", "MSFTDynamics365erLuoYong.jpg"),
new JProperty("filesize", ),
new JProperty("documentbody", "/9j/4AAQSkZJRRRQAUUUUAf//Z"),
new JProperty("isdocument", true),
new JProperty("mimetype", "image/jpeg"),
new JProperty("notetext", "罗勇测试用的"),
new JProperty("objectid_account@odata.bind", "/accounts(C543D891-9FBD-E911-B0D1-8280A40FB795)")
);
requestBody.Append(JsonConvert.SerializeObject(jObject));
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"--changeset_{changesetId}");
requestBody.Append("\n");
requestBody.Append("Content-Type: application/http");
requestBody.Append("\n");
requestBody.Append("Content-Transfer-Encoding:binary");
requestBody.Append("\n");
requestBody.Append("Content-ID: 2");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"PUT {ODataBaseUrl}annotations(85412E8C-B08D-E911-B0C9-C8187530CEF1)/stepid HTTP/1.1");
requestBody.Append("\n");
requestBody.Append("Content-Type: application/json;type=entry");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append("{\"value\":\"Y\"}");
requestBody.Append("\n");
requestBody.Append("\n");
requestBody.Append($"--changeset_{changesetId}--");
NetworkCredential credentials = new NetworkCredential(ConfigurationManager.AppSettings["userName"], ConfigurationManager.AppSettings["passWord"]);
HttpMessageHandler 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");
MultipartContent mainContent = new MultipartContent("mixed", $"batch_{batchId.ToString().Replace("\"","")}");
StringContent sc = new StringContent(requestBody.ToString());
sc.Headers.Clear();
sc.Headers.Add("Content-Type", $"multipart/mixed;boundary={changesetId.ToString()}");
mainContent.Add(sc);
var response = await httpClient.PostAsync($"{ODataBaseUrl}$batch", mainContent);
if (response.IsSuccessStatusCode)
{
returnVal = await response.Content.ReadAsStringAsync();
}
else
{
var errorMsg = await response.Content.ReadAsStringAsync();
throw new Exception(errorMsg);
}
return returnVal;
}
}
通过C#代码调用Dynamics 365 Web API执行批量操作的更多相关文章
- 使用JS通过Web API执行批量操作,多个操作是一个事务!
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复235或者20161105可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- Dynamics 365 Web Api之基于single-valued navigation property的filter查询
本篇要讲的是dynamics 新版本中web api的一个改进功能,虽然改进的很有限,但至少是改进了. 举个例子,我们现在知道联系人的名字vic,我们想找出客户记录中主要联系人名字为vic的所有客户, ...
- 利用Fiddler修改请求信息通过Web API执行Dynamics 365操作(Action)实例
本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复261或者20170724可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me ...
- 不借助工具在浏览器中通过Web API执行Dynamics 365操作(Action)实例
摘要: 本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复262或者20170727可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyon ...
- Dynamics CRM Web API中的and和or组合的正确方式!
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复243或者20170111可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- MVC项目实践,在三层架构下实现SportsStore-09,ASP.NET MVC调用ASP.NET Web API的查询服务
ASP.NET Web API和WCF都体现了REST软件架构风格.在REST中,把一切数据视为资源,所以也是一种面向资源的架构风格.所有的资源都可以通过URI来唯一标识,通过对资源的HTTP操作(G ...
- Dynamics CRM2016 Web Api之分页查询
在dynamics crm web api还没出现前,我们是通过fetchxml来实现的,当然这种方式依旧可行,那既然web api来了我们就拥抱新的方式. web api中我们通过指定查询的条数来实 ...
- 延迟调用或多次调用第三方的Web API服务
当我们调用第三方的Web API服务的时候,不一定每次都是成功的.这时候,我们可能会再多尝试几次,也有可能延迟一段时间再去尝试调用服务. Task的静态方法Delay允许我们延迟执行某个Task,此方 ...
- 利用Fiddler修改请求信息通过Web API执行操作(Action)实例
本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复261或者20170724可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me ...
随机推荐
- 如何在阿里云服务器上搭建wordpress个人网站
1.购买云服务器.域名.域名解析.配置linux系统上的web环境.FTP等参照下面的链接. https://www.cnblogs.com/smyhvae/p/4965163.html?tdsour ...
- 使用SQL生成指定数据库的数据字典(MSSQL)
USE DBNAME --指定要生成数据字典的数据库 GO SELECT 表名= CASE WHEN a.colorder= 1 THEN d.name ELSE '' END, 表说明= CASE ...
- Leetcode刷题笔记(Python 找出所有相加之和为n的k个组合,组合中只允许含有1-9的正整数,并且每种组合中不存在重复的数字。)
eg:输入:k=3,n=9 输出: [[1,2,6],[1,3,5],[2,3,4]] 输入:k=2,n=5 输出:[[1,4][2,3]] #!/usr/bin/env python # -*- c ...
- Java 9 ← 2017,2019 → Java 13,来看看Java两年来的变化
距离 2019 年结束,只剩下 33 天了.你做好准备迎接 2020 年了吗? 一到年底,人就特别容易陷入回忆和比较之中,比如说这几天的对比挑战就火了! 这个话题登上了微博的热搜榜,也刷爆了朋友圈, ...
- 技术分享预告丨k3s在边缘计算中的应用实践
技术分享是在[Rancher官方微信技术交流群]里以图文直播+QA实时互动的方式,邀请国内已落地经验的公司或团队负责人分享生产落地的最佳实践.记得添加微信小助手(微信号:rancher2)入群,实时参 ...
- QGIS练手 - 标注
又熬夜了... QGIS的标注就是标签,在QGIS3.x中有了改进. 不得不说,就光速度这一项,就能把ArcMap按在地上摩擦,更别说各种高级的标注样式了——除了标注功能面板UI有点“缺审美化”就是了 ...
- Mac-关于升级macOS Catalina后,终端试用问题
xcrun: error 在终端输入 git clone *****后,提示: xcrun: error: invalid active developer path (/Library/Develo ...
- 3、nio中的selector使用
通过编写一个客户端和服务器端的例子来熟悉selector的使用 服务端逻辑: 1. 绑定一个端口号2. channel注册到selector中3. 用死循环来监听如果有时间发生,遍历selection ...
- LeetCode刷题191125
博主渣渣一枚,刷刷leetcode给自己瞅瞅,大神们由更好方法还望不吝赐教.题目及解法来自于力扣(LeetCode),传送门. 今天状态不好,划一下水. 算法: 给定一个整数数组 nums 和一个目标 ...
- 用PYTHON首选的GUI库WXPYTHON做程序界面
大家好,我是A8U神经网络,今天又要跟大家分享一下wxWidgets开发神经网络程序界面的一些经验,希望对开发有兴趣的朋友有所帮助.跨平台的GUI工具库以GTK +,Qt和wxWidgets闻名. G ...