2017-01-31 28 views
0

我正尝试使用HttpClient.PostAsync将json发送到Web API。它可以从控制台应用程序运行,但不能从我的CRM插件运行。做了一些研究,我注意到它可能与插件运行和线程的上下文有关。反正这是我的调用代码:HttpClient PostAsync在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; 
    } 
} 

将引发异常,消息“正在中止线程”。谁能告诉我我做错了什么?

+0

更新:不仅不能在调试。当我从CRM运行它时,它确实有效。 – gareth99

回答

6

我猜这是怎么回事基于使用的异步/等待对该有些随机失败。我不认为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完成
我的异步完成

+0

我同意这个答案,并将第二个建议移动到一个异步插件 - 如果你担心延迟返回给用户。如果你看看CRM的插件体系结构,在插件中使用async/await调用没有任何意义。由于管道是同步的,你已经有一个执行它的线程,所以你没有真正从等待中获得用户或系统资源的好处。 – Nicknow