HttpClient PostAsync在CRM插件中不起作用

时间:2017-01-31 22:10:21

标签: c# json dynamics-crm

我正在尝试使用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;。谁能告诉我我做错了什么?

2 个答案:

答案 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