需要帮助获取高于8.0.0的EpiServer CMS版本的JSON帖子工作

时间:2016-09-23 14:33:00

标签: c# json episerver

我们有多个EpiServer站点,我们正在添加将JSON发布到站点监控API的功能。我能够在我们的EpiServer CMS 8.0.0版本站点上成功运行JSON帖子,但遇到了CMS版本8.8.1及更高版本的问题。

以下是我们成功的工作代码的样子。

private async Task SendMaintenanceEvent(object maintenanceEvent)
{
    string endpoint = "https://OurEndpointURL.com/omitted/";
    string endpointDirectory = "target";

    // Provide basic authorization. Credentials must be base-64 encoded to be recognized.
    string credentials = "AuthCredentialsOmitted";
    string credentialsBase64 = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(credentials));

    // Convert the maintenanceEvent object to consumable JSON.
    string maintenanceEventJson = System.Web.Helpers.Json.Encode(maintenanceEvent);
    StringContent content = new StringContent(maintenanceEventJson, Encoding.UTF8, "application/json");

    using (HttpClient httpClient = new HttpClient())
    {
        httpClient.BaseAddress = new Uri(endpoint);
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentialsBase64);
        HttpResponseMessage response = await httpClient.PostAsJsonAsync(endpointDirectory, content);
        if (!response.IsSuccessStatusCode)
        {
            throw new System.Exception("Error sending maintenance event.");
        }
    }
}

上面的方法取决于几个using语句也在这个类中。

using System.Net.Http;
using System.Net.Http.Headers;

上述内容在我们的EpiServer CMS 8.0.0解决方案中取得了成功。但是当我们将相同的代码移植到一个较高的CMS版本时,帖子就会停留在这一行:

HttpResponseMessage response = await httpClient.PostAsJsonAsync(access.EndpointDirectory, content);

被卡住了#34;我的意思是Visual Studio调试器在该行停止,并且永远不会进入下一行。

研究这一点,我发现了使用PostAsync代替PostAsJsonAsync的建议。所以这是我对EpiServer 9解决方案的一次尝试。但最终会以text/plain而不是application/json发布。

private async Task SendMaintenanceEvent(object maintenanceEvent)
{               
    string endpointAddress = "https://OurEndpointURL.com/omitted/";
    string endpointDirectory = "target";

    // Provide basic authorization. Credentials must be base-64 encoded to be recognized.
    string credentials = "AuthCredentialsOmitted";
    string credentialsBase64 = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(credentials));

    // Convert the maintenanceEvent object to consumable JSON.
    //string maintenanceEventToPost = System.Web.Helpers.Json.Encode(maintenanceEvent);
    //StringContent stringContent = new StringContent(maintenanceEventToPost, Encoding.UTF8, "application/json");
    string jsonMaintenanceEvent = JsonConvert.SerializeObject(maintenanceEvent);
    StringContent stringContent = new StringContent(jsonMaintenanceEvent, Encoding.UTF8, "application/json");

    using (HttpClient httpClient = new HttpClient())
    {   
        httpClient.BaseAddress = new Uri(endpointAddress);
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentialsBase64);
        HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(endpointDirectory, stringContent);
        if (!httpResponseMessage.IsSuccessStatusCode)
        {
            throw new System.Exception("Error sending maintenance event to Monitor.");
        }   
    }
}

比较Fiddler中的帖子,成功的代码的内容类型为application/json。但是,不成功的代码块的Content-Type为text/plain。我认为Content-Type基于StringContent对象,我已按如下方式设置ContentType:

StringContent stringContent = new StringContent(jsonMaintenanceEvent, Encoding.UTF8, "application/json");

我不明白为什么PostAsync无视这种设定。该对象的mediaType为application/json

如果我将帖子从PostAsync更改为PostAsJsonAsync,那么帖子就会卡住,如上所述。

最终我只需要让JSON帖子在高于8.0.0的EpiServer版本中工作。在这个工作了好几天后,这简直令人费解。谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

我不知道调用代码是什么样的,但发生了什么是死锁,你可以通过.ConfigureAwait(false)调用PostAsJsonAsync来避免这种情况:

HttpResponseMessage response = await httpClient.PostAsJsonAsync(access.EndpointDirectory, content).ConfigureAwait(false);

在此处使用async / await时,您可以阅读有关死锁的更多信息:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

他的例子看起来很像你的问题。

  
      
  1. 顶级方法调用GetJsonAsync(在UI / ASP.NET上下文中)。
  2.   
  3. GetJsonAsync(在UI / ASP.NET上下文中)。   GetJsonAsync通过调用HttpClient.GetStringAsync(仍然在上下文中)启动REST请求。
  4.   
  5. GetStringAsync返回未完成的任务,表示REST请求未完成。
  6.   
  7. GetJsonAsync等待GetStringAsync返回的任务。捕获上下文,稍后将用于继续运行GetJsonAsync方法。 GetJsonAsync返回未完成的Task,表示GetJsonAsync方法未完成。
  8.   
  9. 顶级方法同步阻止GetJsonAsync返回的任务。   这会阻止上下文线程。
  10.   
  11. ...最终,REST请求将完成。这样就完成了GetStringAsync返回的任务。
  12.   
  13. GetJsonAsync的延续现在已准备好运行,它等待上下文可用,以便它可以在上下文中执行。
  14.   
  15. 死锁。顶级方法是阻塞上下文线程,等待GetJsonAsync完成,GetJsonAsync正在等待上下文空闲,以便它可以完成。
  16.   
斯蒂芬列出了两种避免死锁的方法

  

在“库”异步方法中,尽可能使用 ConfigureAwait(false)

  

不要阻止任务;一直使用async。

如果没有看到实际调用SendMaintenanceEvent方法的代码,就很难分辨实际导致死锁的原因。