【问题标题】:Calling asynchronous library from Dynamics CRM Plugin从 Dynamics CRM 插件调用异步库
【发布时间】:2018-12-07 14:26:01
【问题描述】:

我有一个连接到第三方系统 API 的异步库。我正在尝试在 Dynamics C# 插件中使用此库在第三方系统中创建新记录。只要插件一次只在一个实体上运行,我编写的代码就可以正常工作。但是,如果我同时在两个不同的实体上启动插件,我会收到错误:

更新 Star 失败。错误 - 对象引用未设置为对象的实例。 : System.NullReferenceException : : 在 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;
}

【问题讨论】:

    标签: c# asynchronous plugins dynamics-crm microsoft-dynamics


    【解决方案1】:

    根据Dynamics Developer Guide,你不应该在插件中使用全局变量。我正在使用全局变量来访问导致此问题的第三方库。下面链接文档的相关部分

    为了提高性能,Dynamics 365 for Customer Engagement 缓存插件实例。插件的 Execute(IServiceProvider) 方法应该写成无状态的,因为不是每次调用插件都会调用构造函数。此外,多个系统线程可以同时执行插件。所有每次调用的状态信息都存储在上下文中,因此您不应使用全局变量或尝试将任何数据存储在成员变量中以供下次插件调用期间使用,除非该数据是从提供给构造函数的配置参数中获取的。对插件注册的更改将导致插件重新初始化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多