HttpClient PostAsync在CRM插件中不起作用

gar*_*h99 0 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);
                    }
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

以下是发送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;
    }
}
Run Code Online (Sandbox Code Playgroud)

抛出异常并显示消息"正在中止线程".谁能告诉我我做错了什么?

Mat*_*ing 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个会打印:

CRM完成了
我的异步完成