【问题标题】:Connecting to CRM Online through CRM 365 Plugin通过 CRM 365 插件连接到 CRM Online
【发布时间】:2017-07-09 04:26:52
【问题描述】:

我需要通过 CRM 365 插件连接和检索 CRM Online 中的记录。我尝试使用xrm.tooling.dll 进行简化连接,但不幸的是它显示Could not load file or assembly 'microsoft.xrm.tooling.connector,当我使用ClientCredential 时,错误显示Metadata contain refereces that cannot be resolved

奇怪的是,我用控制台应用程序尝试了这两种方法,而且效果很好。只是想知道我在这种情况下想念什么?当我想通过插件连接到CRM时,我需要特殊要求吗?请任何人分享您的知识。

编辑

这只是一个示例代码,用于从 CRM Online 获取帐户名称并使用 InvalidPluginExecutionException 显示它:

IOrganizationService _service;

public void Execute(IServiceProvider serviceprovider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceprovider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory servicefactory = (IOrganizationServiceFactory)serviceprovider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = servicefactory.CreateOrganizationService(context.UserId);

            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
           {

                Entity ent = (Entity)context.InputParameters["Target"];

                if (ent.LogicalName != "opportunity")
                    return;

                string connstring = @"Url=https://office.crm5.dynamics.com; Username=username@office.onmicrosoft.com; Password=crmoffice; authtype=Office365";
                CrmServiceClient conn = new Microsoft.Xrm.Tooling.Connector.CrmServiceClient(connstring);
                service = (IOrganizationService)conn.OrganizationWebProxyClient != null ? (IOrganizationService)conn.OrganizationWebProxyClient : 

(IOrganizationService)conn.OrganizationServiceProxy;


                try
                {
                    Guid fabercastel = new Guid("efd566dc-10ff-e511-80df-c4346bdcddc1");
                    Entity _account = new Entity("account");
                    _account = service.Retrieve(_account.LogicalName, fabercastel, new ColumnSet("name"));

                    string x = _account["name"].ToString();


                    throw new InvalidPluginExecutionException("Result of Query : " + x);
                }
                catch (Exception ex)
                {
                    throw new InvalidPluginExecutionException(ex.Message);
                }

【问题讨论】:

  • 您应该已经拥有在插件执行上下文中连接到 CRM 所需的上下文信息。你能出示你的代码吗?
  • @jasonscript hii,“您应该已经拥有连接到 CRM 所需的上下文信息”是什么意思?我以前从未这样做过,通常我创建控制台应用程序来从 CRM 中检索记录。我是新手,请和我一起裸露

标签: dynamics-crm-2011 dynamics-crm crm dynamics-crm-online dynamics-crm-365


【解决方案1】:

您应该能够连接到另一个 CRM 实例,而无需使用 Online Sandbox 之外的任何程序集(Microsoft.Xrm.Sdk 和相关的除外)。

例如,只需使用来自SDK\SampleCode\CS\GeneralProgramming\Authentication\AuthenticateWithNoHelp\AuthenticateWithNoHelp.cs 的 SDK 示例。

【讨论】:

    【解决方案2】:

    您应该能够连接到另一个 CRM 实例,而无需使用 Online Sandbox 之外的任何程序集(Microsoft.Xrm.Sdk 和相关程序除外)。只需使用来自“SDK\SampleCode\CS\GeneralProgramming\Authentication\AuthenticateWithNoHelp\AuthenticateWithNoHelp.cs”的 SDK 示例。连接Office365的简化版如下:

    class AuthenticateWithNoHelp
    {
        private String _discoveryServiceAddress = "https://disco.crm.dynamics.com/XRMServices/2011/Discovery.svc";
        private String _organizationUniqueName = "orgname";
        private String _userName = "admin@orgname.onmicrosoft.com";
        private String _password = "password";
        private String _domain = "domain";
    
        public void Run()
        {
            IServiceManagement<IDiscoveryService> serviceManagement =
                        ServiceConfigurationFactory.CreateManagement<IDiscoveryService>(
                        new Uri(_discoveryServiceAddress));
            AuthenticationProviderType endpointType = serviceManagement.AuthenticationType;
    
            AuthenticationCredentials authCredentials = GetCredentials(serviceManagement, endpointType);
    
    
            String organizationUri = String.Empty;
            using (DiscoveryServiceProxy discoveryProxy =
                GetProxy<IDiscoveryService, DiscoveryServiceProxy>(serviceManagement, authCredentials))
            {
                if (discoveryProxy != null)
                {
                    OrganizationDetailCollection orgs = DiscoverOrganizations(discoveryProxy);
                    organizationUri = FindOrganization(_organizationUniqueName,
                        orgs.ToArray()).Endpoints[EndpointType.OrganizationService];
    
                }
            }
    
            if (!String.IsNullOrWhiteSpace(organizationUri))
            {
                IServiceManagement<IOrganizationService> orgServiceManagement =
                    ServiceConfigurationFactory.CreateManagement<IOrganizationService>(
                    new Uri(organizationUri));
    
                AuthenticationCredentials credentials = GetCredentials(orgServiceManagement, endpointType);
    
                using (OrganizationServiceProxy organizationProxy =
                    GetProxy<IOrganizationService, OrganizationServiceProxy>(orgServiceManagement, credentials))
                {
                    organizationProxy.EnableProxyTypes();
                    Guid userid = ((WhoAmIResponse)organizationProxy.Execute(
                        new WhoAmIRequest())).UserId;
                }
            }
        }
    
        private AuthenticationCredentials GetCredentials<TService>(IServiceManagement<TService> service, AuthenticationProviderType endpointType)
        {
            AuthenticationCredentials authCredentials = new AuthenticationCredentials();
    
            authCredentials.ClientCredentials.UserName.UserName = _userName;
            authCredentials.ClientCredentials.UserName.Password = _password;
    
            return authCredentials;
        }
    
        public OrganizationDetailCollection DiscoverOrganizations(
            IDiscoveryService service)
        {
            if (service == null) throw new ArgumentNullException("service");
            RetrieveOrganizationsRequest orgRequest = new RetrieveOrganizationsRequest();
            RetrieveOrganizationsResponse orgResponse =
                (RetrieveOrganizationsResponse)service.Execute(orgRequest);
    
            return orgResponse.Details;
        }
    
        public OrganizationDetail FindOrganization(string orgUniqueName,
            OrganizationDetail[] orgDetails)
        {
            if (String.IsNullOrWhiteSpace(orgUniqueName))
                throw new ArgumentNullException("orgUniqueName");
            if (orgDetails == null)
                throw new ArgumentNullException("orgDetails");
            OrganizationDetail orgDetail = null;
    
            foreach (OrganizationDetail detail in orgDetails)
            {
                if (String.Compare(detail.UrlName, orgUniqueName,
                    StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    orgDetail = detail;
                    break;
                }
            }
            return orgDetail;
        }
    
        private TProxy GetProxy<TService, TProxy>(
            IServiceManagement<TService> serviceManagement,
            AuthenticationCredentials authCredentials)
            where TService : class
            where TProxy : ServiceProxy<TService>
        {
            Type classType = typeof(TProxy);
    
            if (serviceManagement.AuthenticationType !=
                AuthenticationProviderType.ActiveDirectory)
            {
                AuthenticationCredentials tokenCredentials =
                    serviceManagement.Authenticate(authCredentials);
                return (TProxy)classType
                    .GetConstructor(new Type[] { typeof(IServiceManagement<TService>), typeof(SecurityTokenResponse) })
                    .Invoke(new object[] { serviceManagement, tokenCredentials.SecurityTokenResponse });
            }
    
            return (TProxy)classType
                .GetConstructor(new Type[] { typeof(IServiceManagement<TService>), typeof(ClientCredentials) })
                .Invoke(new object[] { serviceManagement, authCredentials.ClientCredentials });
        }
    
        static public void Main(string[] args)
        {
            AuthenticateWithNoHelp app = new AuthenticateWithNoHelp();
            app.Run();
        }
    }
    

    您可以通过使用 DiscoveryService 删除部分并直接调用来进一步简化它:

    https://orgname.api.crm.dynamics.com/XRMServices/2011/Organization.svc
    

    这应该适用于沙盒插件,因为它只使用 Sdk 程序集。

    【讨论】:

      【解决方案3】:

      您不需要任何额外的库,如 Microsoft.Xrm.Tooling.Connector 或 SDK 中的其他库来使用 CRM Web 服务。与 SOAP / REST 协议相关的标准 .NET 机制就足够了(当然这种方法可能会稍微困难一些)。

      编辑:我进行了一些额外的调查,发现在不使用 SDK 库的情况下为 Office365 身份验证配置自动生成的 OrganizationServiceClient 可能真的很痛苦。我不是说这是不可能的,但是微软没有记录它。添加更多详细信息 Visual Studio 生成的代理类不支持 OAuth 身份验证。

      因此 - 我的第二个建议是使用外观 Web 服务与 CRM OnLine 进行通信。您可以在 Windows Azure 或 Internet 中的任何其他云/托管位置托管此 Web 服务。通过您的 CRM 365 插件,您可以使用您的自定义 Web 服务方法并使用此服务与您的 CRM Online 实例进行通信。我想尝试运行未记录的连接到 CRM Online 的方法会更好。**

      【讨论】:

      • 嗨@piotr,你能告诉我一个小sn-p代码怎么做吗?
      • 我会和我的经理谈谈这个选项。奇怪的是,对方可以通过插件在线连接crm。但我的失败了。无论如何,谢谢你回答我的问题
      【解决方案4】:

      您已经使用您在插件第三行定义的 IOrganizationService 连接到 CRM。除非您需要连接到不同组织中的另一个 CRM 实例,否则不需要或不需要登录。

      基本上只要把你试试上面的4行删掉就行了。

      编辑:

      public void Execute(IServiceProvider serviceprovider)
      {
          IPluginExecutionContext context = (IPluginExecutionContext)serviceprovider.GetService(typeof(IPluginExecutionContext));
          IOrganizationServiceFactory servicefactory = (IOrganizationServiceFactory)serviceprovider.GetService(typeof(IOrganizationServiceFactory));
          IOrganizationService service = servicefactory.CreateOrganizationService(context.UserId);
      
          if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
          {
      
               Entity ent = (Entity)context.InputParameters["Target"];
      
               if (ent.LogicalName != "opportunity")
                   return;
      
               Guid fabercastel = new Guid("efd566dc-10ff-e511-80df-c4346bdcddc1");
               Entity _account = new Entity("account");
               _account = service.Retrieve(_account.LogicalName, fabercastel, new ColumnSet("name"));
      
               string x = _account["name"].ToString();
      
      
               throw new InvalidPluginExecutionException("Result of Query : " + x);
          }
      }
      

      【讨论】:

      • 嗨,达里尔,我应该删除哪些行?是的。我需要在这个插件中连接到另一个 CRM 实例。场景是我在线从 crm 检索数据。本地CRM将使用数据来填写其字段
      • @FikriHailal 试一试。 PS。如果我是你,我会编辑掉你的用户 ID 和密码。
      • 天哪,我忘了那个。谢谢你提醒我。通过像上面的代码一样删除简化的连接,我如何与另一个 CRM 实例进行通信?
      • 啊,@FikriHailal,所以您是“连接到不同组织中的另一个 CRM 实例”?在这种情况下,请保留您的代码,并使用 ILMerge 合并缺少“microsoft.xrm.tooling.connector”的程序集
      • @Daryl 您无需工具即可在线连接到 CRM。我已经在下面发布了我的答案,它没有使用任何工具,并且我成功连接到在线 CRM。
      猜你喜欢
      • 2018-02-07
      • 2017-07-05
      • 2021-12-14
      • 2022-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-27
      相关资源
      最近更新 更多