简体   繁体   English

从Dynamics CRM插件调用异步库

[英]Calling asynchronous library from Dynamics CRM Plugin

I have an asynchronous library that connects to a third party system API. 我有一个异步库,可连接到第三方系统API。 I am trying to use this library within a Dynamics C# plugin to create a new record in the third party system. 我正在尝试在Dynamics C#插件中使用此库在第三方系统中创建新记录。 The code I have written works fine whenever the plugin only runs on one entity at a time. 只要插件一次只在一个实体上运行,我编写的代码就可以正常工作。 However, if I kick off the plugin on two different entities at the same time I receive the error: 但是,如果我同时在两个不同实体上启动插件,则会收到错误消息:

Failed to update Star. 无法更新星标。 Error - Object reference not set to an instance of an object. 错误-对象引用未设置为对象的实例。 : System.NullReferenceException : : at COHEN.APIConnector.Connectors.StarConnector.d__2`1.MoveNext() :System.NullReferenceException::位于COHEN.APIConnector.Connectors.StarConnector.d__2`1.MoveNext()

I'm not quite sure what is causing this error or how to resolve it. 我不太确定是什么导致了此错误或如何解决该错误。 It seems to have something to do with the asynchronous nature of the library I have written to connect to the API. 似乎与我编写的用于连接到API的库的异步特性有关。 What would cause this error and what are some options to resolve it? 是什么会导致此错误,有哪些解决方案?

Plugin Code 插件代码

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

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

Library Code 图书馆代码

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;
}

According to the Dynamics Developer Guide , you should not use global variables in plugins. 根据《 Dynamics开发人员指南》 ,您不应在插件中使用全局变量。 I was using a global variable to access my third party library which was causing this issue. 我使用全局变量访问导致此问题的第三方库。 Relevant section of linked documentation below 以下链接文档的相关部分

For improved performance, Dynamics 365 for Customer Engagement caches plug-in instances. 为了提高性能,Dynamics 365 for Customer Engagement会缓存插件实例。 The plug-in's Execute(IServiceProvider) method should be written to be stateless because the constructor is not called for every invocation of the plug-in. 应当将插件的Execute(IServiceProvider)方法编写为无状态的,因为并非每次调用该插件时都会调用该构造函数。 Also, multiple system threads could execute the plug-in at the same time. 同样,多个系统线程可以同时执行插件。 All per invocation state information is stored in the context, so you should not use global variables or attempt to store any data in member variables for use during the next plug-in invocation unless that data was obtained from the configuration parameter provided to the constructor. 每次调用的所有状态信息都存储在上下文中,因此,除非该数据是从提供给构造函数的配置参数中获取的,否则您不应使用全局变量或尝试将任何数据存储在成员变量中供下次插件调用时使用。 Changes to a plug-ins registration will cause the plug-in to be re-initialized. 插件注册的更改将导致该插件被重新初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM