从.net 4.5.2更新到.net 4.6.2在xrm sdk

时间:2017-07-06 00:15:23

标签: c# .net wcf dynamics-crm

我们有一个针对.net 4.5.2框架开发的Win 8.1商店应用程序,当计算机更新为.net 4.6.2时,我们收到的对象引用未设置为Object异常的值。 / p>

该应用程序包含两个部分:商店应用程序,其中包含所有UI逻辑;以及代理程序,用于保存与Dynamics CRM Outlook Connector的所有数据层交互。

我在运行第一个WhoAmI请求时已经确定了它在base.ExecuteCore(request)上出错的行。

有趣的是,如果代理在调试模式下启动或在控制台应用程序中使用,则相同的代码可以正常工作。代理由我们的UI应用程序使用应用程序URL启动,并确认已启动。

我尝试了以下内容:

  • 将项目更新为.net 4.6.2
  • 将相关的nuget软件包更新为最新版本,包括xrm sdk dll。
  • 反编译Xrm.SDK dll并检查方法中使用的每个属性以查找错误的位置,并找到要设置的所有相关属性。
  • 绕过outlook连接器并直接转到CRM网络服务

我的想法是.net 4.5.2和.net 4.6.2以不同的方式执行代码会导致错误。

有没有人对如何解决这个问题有任何想法?

供参考:

CRM版本: 8.0.1.90

堆栈跟踪

  

at Microsoft.Xrm.Sdk.Client.OrganizationServiceContextInitializer.Initialize()      在Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.ExecuteCore(OrganizationRequest请求)      at c:\ PGW.Mobility \ PGW.Mobility.CrmProxy \ CrmContextProvider.cs中的CrmProxy.CrmOrganizationProxy.ExecuteCore(OrganizationRequest请求):第127行

类别:

using System;
using System.Collections.Concurrent;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.ServiceModel.Description;
using System.Threading;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using NLog;
using Mobility.Crm.Core;
using Mobility.CrmProxy.Interfaces;

namespace Mobility.CrmProxy
{
    public class CrmContextProvider : ICrmContextProvider
    {
        private readonly IEntityMapper _mapper;
        private readonly ICrmMetadataHolder _metadataHolder;
        private readonly OrganizationProxyPool _proxyPool;

        public CrmContextProvider(IEntityMapper mapper, ICrmMetadataHolder metadataHolder, OrganizationProxyPool proxyPool, ICrmConnectionConfig crmConnectionConfig)
        {
            _proxyPool = proxyPool;
            _mapper = mapper;
            _metadataHolder = metadataHolder;
        }

        public CrmProxyContext Context()
        {
            Contract.Ensures(Contract.Result<CrmProxyContext>() != null);
            var proxy = _proxyPool.Acquire();
            return new CrmProxyContext(_proxyPool, proxy, _mapper, _metadataHolder);
        }
    }

    public interface IOrganizationServiceReleaser
    {
        void Release(IOrganizationService proxy);
    }

    /// <summary>
    /// Pool of expensive organization proxies to improve overall performance
    /// </summary>
    public class OrganizationProxyPool : IOrganizationServiceReleaser
    {
        public static int OrgProxyInstanceCount = 0;

        private readonly Logger _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.FullName);
        private readonly ICrmConnectionConfig _crmConnectionConfig;

        private static readonly ConcurrentBag<IOrganizationService> OrgProxyPool = new ConcurrentBag<IOrganizationService>();

        public OrganizationProxyPool(ICrmConnectionConfig crmConnectionConfig)
        {
             _crmConnectionConfig = crmConnectionConfig;
        }

        public IOrganizationService Acquire()
        {
            IOrganizationService proxy;
            if (!OrgProxyPool.TryTake(out proxy))
            {
                var count = Interlocked.Increment(ref OrgProxyInstanceCount);
                _log.Info("Creating new OrganizationServiceProxy (total count: {0})", count);
                var crmProxy = new CrmOrganizationProxy(_crmConnectionConfig);
                // enable types declared in Crm.Core assembly
                //crmProxy.EnableProxyTypes(typeof(CrmContext).Assembly);   //Removed as per null reference exception with .net 4.6.2??
            crmProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior(Assembly.GetExecutingAssembly()));
                proxy = crmProxy;
            }
            return proxy;
        }

        public void Release(IOrganizationService proxy)
        {
            // ignore failed proxies
            var crmProxy = proxy as CrmOrganizationProxy;
            if (crmProxy != null && !crmProxy.Failed)
                OrgProxyPool.Add(proxy);
        }
    }

    class CrmOrganizationProxy : OrganizationServiceProxy
    {
        private readonly ICrmConnectionConfig _crmConnectionConfig;

        public CrmOrganizationProxy(ICrmConnectionConfig crmConnectionConfig)
            : base(
                new Uri(crmConnectionConfig.CurrentCrmServerUri), null,
                new ClientCredentials
                {
                    Windows = { ClientCredential = crmConnectionConfig.CurrentCredentials }
                },
                null)
        {
            _crmConnectionConfig = crmConnectionConfig;
        }

        public bool Failed { get; private set; }

        protected override void AuthenticateCore()
        {
            if (_crmConnectionConfig.IsOffline)
            {
                // TODO: report bug to XRM team
                // note: this is reflection workaround over bug in Xrm when connecting offline Outlook CRM
                // without this Xrm throws weird "authentication failed!" exception which is wrong because
                // Cassini web server (where offline CRM server hosted) doesn't even support any authentication

                var isAuthPrivateSetter = typeof(ServiceProxy<IOrganizationService>).
                    GetProperty("IsAuthenticated").GetSetMethod(true);
                var proxyBase = (ServiceProxy<IOrganizationService>)this;
                isAuthPrivateSetter.Invoke(proxyBase, new object[] { true });
            }
            else
            {
                base.AuthenticateCore();
            }
        }

        protected override OrganizationResponse ExecuteCore(OrganizationRequest request)
        {
            // Telerik decompiler shows that context ivokes only Execute() method of proxy, 
            // so it is enough to check failures only in ExecuteCore()
            try
            {
                return base.ExecuteCore(request);
            }
            catch (Exception)
            {
                Interlocked.Decrement(ref OrganizationProxyPool.OrgProxyInstanceCount);
                Failed = true;
                throw;
            }
        }
    }
}

更新2017年7月17日

将代码更改为以下后,我现在有了更详细的错误。

错误:

  

LastCrmError =“无法登录Dynamics CRMOrganizationServiceProxy为空”

代码:

var crmProxy = new CrmServiceClient("Url=http://crm/AdventureWorks;");
crmProxy.GetMyCrmUserId();

添加基于文件的日志记录后,我现在得到一个有用的错误

  

OperationContext.Current的值不是此OperationContextScope安装的OperationContext值。

     

堆栈跟踪:在System.ServiceModel.OperationContextScope.PopContext()     在Microsoft.Xrm.Sdk.Client.ServiceContextInitializer1.Dispose(布尔处理)     在Microsoft.Xrm.Sdk.Client.ServiceContextInitializer1.Dispose()     在Microsoft.Xrm.Sdk.Client.DiscoveryServiceProxy.Execute(DiscoveryRequest请求)     在Microsoft.Xrm.Tooling.Connector.CrmWebSvc.DiscoverOrganizations(Uri discoveryServiceUri,Uri homeRealmUri,ClientCredentials clientCredentials,ClientCredentials deviceCredentials)

2 个答案:

答案 0 :(得分:0)

也许尝试使用连接字符串实例化CrmServiceClient。

以下是示例连接字符串...

CRM 2016和Dynamics 365在线:

<add name="dev26" connectionString="Url=https://dev26.crm.dynamics.com; Username=user@dev26.onmicrosoft.com; Password=Pass; AuthType=Office365" />

内部集成安全性:

<add name="prod" connectionString="Url=http://myserver/AdventureWorksCycle;"/>

凭证的内部部署:

<add name="prod" connectionString="Url=http://myserver/AdventureWorksCycle; Domain=mydomain; Username=administrator; Password=password; AuthType=AD;"/>

CRM 2016之前的内部IFD:

<add name="prod" connectionString="Url=https://contoso.litware.com; Username=someone@litware.com; Password=password; AuthType=IFD;"/>

CRM 2016及更高版本的内部部署IFD(v8.0 +)

<add name="prod" connectionString="ServiceUri=https://contoso.litware.com/contoso; Domain=contoso; Username=contoso\administrator; Password=password; AuthType=IFD; LoginPrompt=Never;" />

答案 1 :(得分:0)

这似乎是.net 4.6.2的一个错误。将框架更新到.net 4.7解决了这个问题。

我80%确定它与此错误相关:https://connect.microsoft.com/VisualStudio/Feedback/Details/3118586