我正在尝试使用HttpClient.PostAsync将json发送到Web API。它适用于控制台应用程序,但不适用于我的CRM插件。做一些研究我注意到它可能与插件运行和线程化的上下文有关。无论如何这里是我的呼叫代码:
public async void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context.InputParameters.Contains("Target"))
{
if (context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
if (entity.LogicalName == "new_product")
{
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
if (entity.Contains("new_begindate") && entity.Contains("new_expirationdate"))
{
await OnlineSignUp(entity, service);
}
}
catch (InvalidPluginExecutionException)
{
throw;
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(OperationStatus.Failed, "Error signing up: " + e.Message);
}
}
}
}
}
以下是发送json的相关代码:
private async Task<HttpResponseMessage> OnlineSignUp(Entity license, IOrganizationService service)
{
...
var json = JsonConvert.Serialize(invitation);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", "token=7d20f3f09ef24067ae64f4323bc95163");
Uri uri = new Uri("http://signup.com/api/v1/user_invitations");
var response = await httpClient.PostAsync(uri, content).ConfigureAwait(false);
int n = 1;
return response;
}
}
抛出异常并显示消息&#34;线程正在中止&#34;。谁能告诉我我做错了什么?
答案 0 :(得分:6)
我猜这会因为使用async / await而有些随机失败。我不认为CRM真的支持插件在完成之前返回控制。当它失败时,看起来该线程正在幕后进行清理。
CRM已经在处理插件的多线程,并且支持将插件步骤注册为异步(如果它们长时间运行(或者不需要在同步管道中运行))。在这里使用同步HTTP调用更有意义,如:
var response = httpClient.PostAsync(uri, content).Result;
编辑:为了说明这一点,这是一个过分夸大的例子,说明当CRM启动你的插件并且你正在使用async / await(来自LinqPad)时最有可能发生的事情。
static async void CrmInternalFunctionThatKicksOffPlugins()
{
var plugin = new YourPlugin();
//NOTE Crm is not going to "await" your plugin execute method here
plugin.Execute();
"CRM is Done".Dump();
}
public class YourPlugin
{
public async void Execute()
{
await OnlineSignUp();
}
private async Task<HttpResponseMessage> OnlineSignUp()
{
var httpClient = new HttpClient();
var r = await httpClient.PostAsync("http://www.example.com", null);
"My Async Finished".Dump();
return r;
}
}
将打印:
CRM完成了我的异步完成
答案 1 :(得分:-2)
看起来你正在使用Json.NET,当你使用外部程序集时,有一些事情需要处理(合并)并且结果并不总是有效。
尝试使用DataContractJsonSerializer序列化
示例:http://www.crmanswers.net/2015/02/json-and-crm-sandbox-plugins.html