Вызов асинхронной библиотеки из плагина Dynamics CRM - PullRequest
0 голосов
/ 07 декабря 2018

У меня есть асинхронная библиотека, которая подключается к стороннему системному API.Я пытаюсь использовать эту библиотеку в плагине Dynamics C # для создания новой записи в сторонней системе.Код, который я написал, прекрасно работает, когда плагин работает только с одной сущностью за раз.Однако, если я одновременно запускаю плагин для двух разных объектов, я получаю сообщение об ошибке:

Не удалось обновить Star.Ошибка - ссылка на объект не установлена ​​для экземпляра объекта.: System.NullReferenceException:: at COHEN.APIConnector.Connectors.StarConnector.d__2`1.MoveNext ()

Я не совсем уверен, что является причиной этой ошибки или как ее устранить.Кажется, что-то связано с асинхронной природой библиотеки, которую я написал для подключения к API.Что может вызвать эту ошибку и какие варианты ее устранения?

Код плагина

APIResponse<COHEN.APIConnector.Model.Entity.ContractJob> response = new APIResponse<COHEN.APIConnector.Model.Entity.ContractJob>();

Task.WaitAll(Task.Run(async () => response = await starConnector.Create(starJob))); 

Код библиотеки

public async Task<APIResponse<T>> Create<T>(T entity) where T : EntityBase
{
    APIResponse<T> response = new APIResponse<T>();

    try
    {
        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri(Helpers.GetSystemUrl(Application.Star));
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml"));

            response.RequestURL = "Calling ToJSON";

            string json = await entity.ToJSON(Application.Star);

            response.RequestURL = "JSON: " + json;

            response.RequestURL = "RunTask?taskid=" + (int)TaskID.CREATE + "&entity=" +
                await MapSingleton.Instance.GetFieldName(Application.Star, entity.Type, FieldType.EntityName) +
                "&json=" + json;

            using (HttpResponseMessage responseMessage = await client.GetAsync(
                "RunTask?taskid=" + (int)TaskID.CREATE + "&entity=" +
                await MapSingleton.Instance.GetFieldName(Application.Star, entity.Type, FieldType.EntityName) +
                "&json=" + json
            ))
            {
                // Check TaskCentre response
                if (responseMessage.StatusCode == HttpStatusCode.OK)
                {
                    XmlDocument xmlDocument = new XmlDocument();
                    xmlDocument.LoadXml(await responseMessage.Content.ReadAsStringAsync());

                    // Check API Response
                    string responseStatusCode = xmlDocument.GetElementsByTagName("StatusCode").Item(0).InnerText;
                    if (responseStatusCode != "")
                    {
                        StatusCode statusCode = (StatusCode)Convert.ToInt32(responseStatusCode);
                        string statusMessage = xmlDocument.GetElementsByTagName("StatusMessage").Item(0).InnerText;

                        if (statusCode == StatusCode.Created)
                        {
                            XmlDocument xmlData = new XmlDocument();
                            xmlData.LoadXml("<data>" + xmlDocument.InnerText.Substring(0, xmlDocument.InnerText.Length - (xmlDocument.InnerText.Length - xmlDocument.InnerText.LastIndexOf("row") - 4)) + "</data>");
                            JObject data = JObject.Parse(JsonConvert.SerializeXmlNode(xmlData));

                            await response.SetValues(Application.Star, entity.Type, data["data"]["row"], entity.ID);
                        }

                        response.StatusCode = statusCode;
                        response.StatusReason = statusMessage;
                    }
                    else
                    {
                        response.StatusCode = StatusCode.Error;
                        response.StatusReason = "No Status Code Returned - " + response.StatusReason;
                    }
                }
                else
                {
                    response.StatusCode = (StatusCode)responseMessage.StatusCode;
                    response.StatusReason = responseMessage.ReasonPhrase;
                }
            }
        }
    }
    catch (Exception e)
    {
        response.StatusCode = StatusCode.Error;
        response.StatusReason = e.Message + " : " + e.GetType().ToString() + " : " + e.InnerException + " : " + e.StackTrace;
    }

    return response;
}

1 Ответ

0 голосов
/ 21 декабря 2018

В соответствии с Руководством разработчика по , вам не следует использовать глобальные переменные в плагинах.Я использовал глобальную переменную для доступа к моей сторонней библиотеке, которая вызывала эту проблему.Соответствующий раздел связанной документации ниже

Для повышения производительности Dynamics 365 для экземпляров подключаемых модулей кэша взаимодействия с клиентами.Метод Execute (IServiceProvider) плагина должен быть написан так, чтобы он не имел состояния, поскольку конструктор вызывается не для каждого вызова плагина.Кроме того, несколько системных потоков могут выполнять плагин одновременно.Вся информация о состоянии вызова вызывается в контексте, поэтому вы не должны использовать глобальные переменные или пытаться хранить какие-либо данные в переменных-членах для использования во время следующего вызова плагина, если только эти данные не были получены из параметра конфигурации, предоставленного конструктору.Изменения в регистрации подключаемых модулей приведут к его повторной инициализации.

...