2016-09-23 1 views
0

У нас есть несколько сайтов EpiServer, где мы добавляем возможность отправлять JSON API-интерфейсу мониторинга сайта. Мне удалось получить сообщения JSON, успешно работающие на наших сайтах EMSServer 8.0.0, но столкнулись с проблемами с версиями 8.8.1 и выше.Нужна помощь в получении сообщения JSON для версии CMS EpiServer выше 8.0.0

Ниже приведен пример нашего успешного рабочего кода.

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 System.Net.Http; 
using System.Net.Http.Headers; 

Вышеупомянутый преуспевает в наших решениях EpiServer CMS 8.0.0. Но когда мы порт тот же код к одному из высших версий CMS, посты застревают на этой линии:

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

К «застревает» Я имею в виду 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. Я думал, что ТипСодержимого был основан на StringContent объекта, и я задал ContentType следующим образом:

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

Я не понимаю, почему PostAsync пренебрегает, что установка. Объект имеет mediaType application/json.

И если я заменю сообщение от PostAsync до PostAsJsonAsync, сообщение просто застревает, как упоминалось выше.

В конечном счете мне просто нужно получить сообщение JSON, работающее в версиях EpiServer выше 8.0.0. После работы над этим несколько дней, это просто озадачивает. Спасибо за вашу помощь.

+1

Кажется, как тупик, что произойдет, если вы добавите .ConfigureAwait (false), как это? 'HttpResponseMessage response = wait httpClient.PostAsJsonAsync (access.EndpointDirectory, content) .ConfigureAwait (false); ' Btw, вы не должны создавать новые HttpClient: http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ – JOSEFtw

+0

Спасибо @JOSEFtw. Сообщение удаётся после применения ConfigureAwait (false). Мне нужно в этом углубиться. Кроме того, спасибо за открытие статьи на HttpClient. –

+0

Как выглядит код, называемый 'SendMaintananceEvent'? Всегда рекомендуется использовать 'ConfigureAwait (false)', если вам не нужен доступ к тому же контексту дальше по вашему методу. – JOSEFtw

ответ

1

Я не знаю, что код вызова выглядит, но то, что происходит тупиковый, вы можете избежать этого с помощью .ConfigureAwait(false) на ваш PostAsJsonAsync вызова, как это:

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

Вы можете прочитать больше о тупиках, когда используя async/ждут здесь: http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

Его пример очень похож на вашу проблему.

метод
  1. верхнего уровня вызывает GetJsonAsync (в пределах контекста/ASP.NET UI).
  2. GetJsonAsync (в контексте UI/ASP.NET). GetJsonAsync запускает запрос REST, вызывая HttpClient.GetStringAsync (все еще в контексте).
  3. GetStringAsync возвращает незавершенную задачу, указывающую, что запрос REST не завершен.
  4. GetJsonAsync ожидает задачу, возвращенную GetStringAsync. Контекст захвачен и будет использоваться для продолжения использования метода GetJsonAsync позже. GetJsonAsync возвращает незавершенную задачу, указывая, что метод GetJsonAsync не завершен.
  5. Метод верхнего уровня синхронно блокирует задачу, возвращенную GetJsonAsync. Это блокирует контекстную нить.
  6. ... В конце концов, запрос REST будет завершен. Это завершает задачу, которая была возвращена GetStringAsync.
  7. Продолжение для GetJsonAsync теперь готово к запуску и ожидает, что контекст будет доступен, чтобы он мог выполняться в контексте.
  8. Тупик. Метод верхнего уровня блокирует поток контекста, ожидая завершения GetJsonAsync, и GetJsonAsync ожидает, что контекст будет бесплатным, чтобы он мог завершить.

Стивен перечисляет 2 способ избежать тупикового

В ваших «библиотеке» асинхронных методы, использует ConfigureAwait (ложь) везде, где это возможно.

и

Не блокируйте на задачи; используйте async полностью вниз.

Не видя кода, который фактически вызывает ваш метод SendMaintenanceEvent, сложно сказать, что на самом деле вызывает тупик.