MS CRM 2011 如何從外部連接CRM


 

原創地址:http://www.cnblogs.com/jfzhu/admin/EditPosts.aspx?postid=2752006

轉載請注明出處

 

本文要講解,在CRM應用之外,不具有CRM context的情況下,如何連接到CRM,獲得CRM的相關數據。如果你有耐心的話,也可以仔細研究一下SDK中Sample: Simplified Connection Quick Start using Microsoft Dynamics CRM 2011 and Microsoft Dynamics CRM Online。

 

CRM 2011提供了一個Assembly microsoft.xrm.client.dll,如果從客戶端連接CRM的話,可以使用該Assembly中的OrganizationService類。我在本文中以一個控制台程序來演示如何連接到CRM 2011。首先程序需要使用到的引用如下圖。有關CRM的引用都可以在sdk的bin文件夾中找到。

image

Program.cs的代碼為:

using System;
using Microsoft.Xrm.Client.Services;
using Microsoft.Xrm.Client;
using Microsoft.Crm.Sdk.Messages;
using System.ServiceModel;
using System.Configuration;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;

namespace ConsoleApplication3
{
    public class SimplifiedConnection
    {
        #region Class Level Members
        
        private OrganizationService _orgService;

        #endregion Class Level Members

        public void Run(String connectionString, bool promptforDelete)
        {
            try
            {
                // Establish a connection to the organization web service using CrmConnection.
                Microsoft.Xrm.Client.CrmConnection connection = CrmConnection.Parse(connectionString);

                // Obtain an organization service proxy.
                // The using statement assures that the service proxy will be properly disposed.
                using (_orgService = new OrganizationService(connection))
                {
                    // Obtain information about the logged on user from the web service.
                    Guid userid = ((WhoAmIResponse)_orgService.Execute(new WhoAmIRequest())).UserId;
                    Entity systemUser = _orgService.Retrieve("systemuser", userid,
                        new ColumnSet(new string[] { "firstname", "lastname" }));
                    Console.WriteLine("Logged on user is {0} {1}.",
                        systemUser["firstname"].ToString(), systemUser["lastname"].ToString());                    
                }
            }

            // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
            catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
            {
                // You can handle an exception here or pass it back to the calling method.
                throw;
            }
        }

        #region Public Methods



        #endregion Public Methods

        #region Private Methods

        /// <summary>
        /// Gets web service connection information from the app.config file.
        /// If there is more than one available, the user is prompted to select
        /// the desired connection configuration by name.
        /// </summary>
        /// <returns>A string containing web service connection configuration information.</returns>
        private static String GetServiceConfiguration()
        {
            var connection = ConfigurationManager.ConnectionStrings["CrmConnection"];
            return connection.ConnectionString;            
        }


       
        #endregion Private Methods

        #region Main method

        /// <summary>
        /// Standard Main() method used by most SDK samples.
        /// </summary>
        /// <param name="args"></param>
        static public void Main(string[] args)
        {
            try
            {
                // Obtain connection configuration information for the Microsoft Dynamics
                // CRM organization web service.
                String connectionString = GetServiceConfiguration();

                if (connectionString != null)
                {
                    SimplifiedConnection app = new SimplifiedConnection();
                    app.Run(connectionString, true);
                }
            }

            catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> ex)
            {
                Console.WriteLine("The application terminated with an error.");
                Console.WriteLine("Timestamp: {0}", ex.Detail.Timestamp);
                Console.WriteLine("Code: {0}", ex.Detail.ErrorCode);
                Console.WriteLine("Message: {0}", ex.Detail.Message);
                Console.WriteLine("Trace: {0}", ex.Detail.TraceText);
                Console.WriteLine("Inner Fault: {0}",
                    null == ex.Detail.InnerFault ? "Has Inner Fault" : "No Inner Fault");
            }
            catch (System.TimeoutException ex)
            {
                Console.WriteLine("The application terminated with an error.");
                Console.WriteLine("Message: {0}", ex.Message);
                Console.WriteLine("Stack Trace: {0}", ex.StackTrace);
                Console.WriteLine("Inner Fault: {0}",
                    null == ex.InnerException.Message ? "Has Inner Fault" : "No Inner Fault");
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("The application terminated with an error.");
                Console.WriteLine(ex.Message);

                // Display the details of the inner exception.
                if (ex.InnerException != null)
                {
                    Console.WriteLine(ex.InnerException.Message);

                    FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> fe = ex.InnerException
                        as FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>;
                    if (fe != null)
                    {
                        Console.WriteLine("Timestamp: {0}", fe.Detail.Timestamp);
                        Console.WriteLine("Code: {0}", fe.Detail.ErrorCode);
                        Console.WriteLine("Message: {0}", fe.Detail.Message);
                        Console.WriteLine("Trace: {0}", fe.Detail.TraceText);
                        Console.WriteLine("Inner Fault: {0}",
                            null == fe.Detail.InnerFault ? "Has Inner Fault" : "No Inner Fault");
                    }
                }
            }

            // Additional exceptions to catch: SecurityTokenValidationException, ExpiredSecurityTokenException,
            // SecurityAccessDeniedException, MessageSecurityException, and SecurityNegotiationException.

            finally
            {
                Console.WriteLine("Press <Enter> to exit.");
                Console.ReadLine();
            }
        }
        #endregion Main method
    }
}

上面的程序需要從配置文件讀取ConnectionString。一個范例app.config文件如下所示。

<?xml version="1.0"?>
<configuration>
  <connectionStrings>

    <!-- Online using Office 365 -->
    <!-- <add name="CrmConnection"
         connectionString="Url=https://contoso.crm.dynamics.com; 
         Username=someone@contoso.onmicrosoft.com; 
         Password=password;"/> -->

    <!-- Online using Windows Live ID -->
     <add name="CrmConnection"
         connectionString="Url=https://aaronbabbitt.api.crm4.dynamics.com/XRMServices/2011/Organization.svc; 
         Username=username@aaronbabbitt.onmicrosoft.com; Password=password; DeviceID=11hfn41bbqrg580vyvoea05abc; 
         DevicePassword=fuqNIlx%e$.l*+ax_#8O4abc;"/>

    <!--On-premises with provided user credentials-->
    <!--<add name="CrmConnection"
         connectionString="Url=http://servername/orgname; Domain=domainname; Username=username; 
         Password=password;"/>-->

    <!-- On-premises using Windows integrated security -->
    <!--<add name="CrmConnection"
         connectionString="Url=http://servername/orgname;"/>-->

    <!-- On-Premises (IFD) with claims -->
    <!--<add name="CrmConnection"
         connectionString="Url=https://url.xxx/XRMServices/2011/Organization.svc; 
         Username=username@xxx.local; Password=password;"/>-->
  </connectionStrings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

這段代碼完成的事情很簡單,就是使用OrganizationService類來執行一個WhoAmIRequest。如果成功就表示控制台成功連接到了CRM。配置文件中一共有5個connection string 的樣例。分別用來連接:

(1) 使用Office 365 ID 的 CRM Online;

(2) 使用Windows Live ID的 CRM Online;

(3) CRM On-Premises;

(4)CRM On-Premises,使用當前Windows integrated security來登錄,所以不需要提供用戶密碼;

(5) 使用了IFD的CRM On-Premises。

上面除了(1)我沒有進行測試,其他四種CRM都通過了該段代碼的測試。在Connection String中,對於CRM Online和IFD On-Premises,URL需要使用Organization Service 的 URL。要查看CRM的Organization Service的URL,可以在Settings –> Customization –> Customizations –> Developer Resources中查看

image

連接CRM Online的時候,需要DeviceID和DevicePassword。很多人不懂DeviceID是干什么用的。DeviceID的目的就是注冊一個設備,使這個設備可以使用Windows Live ID。當你注冊了這個設備后,任何用戶就都可以使用這個設備了。所以如果這個是一個從未注冊過的設備,你首先要注冊它。關於如何注冊一個設備,可以使用sdk帶的deviceregistration工具。具體的命令是DeviceRegistration.exe /operation:Register。命令運行成功后,你就可以拷貝生成的Device ID和Device Password了。

image

最后再說一下,因為在配置文件中,我們保存了用戶登錄信息,這樣很容易泄露用戶名和密碼,所以我再說一下如何對配置文件的Connection string進行加密。對配置文件加密可以使用aspnet_regiis.exe工具,Visual Studio自帶這個工具。如果沒有Visual Studio,.Net中也包含了這個工具。可以在%windows root directory%\Microsoft.NET\%Framework\%version 中找到該工具。首先將app.config另存為文件名為web.config的文件,假如我將該文件保存到我的C:\temp目錄中。文件的內容為:

<?xml version="1.0"?>
<configuration>
  <connectionStrings>

    <!-- Online using Windows Live ID -->
    <add name="CrmConnection"
        connectionString="Url=https://aaronbabbitt.api.crm4.dynamics.com/XRMServices/2011/Organization.svc; 
         Username=username@aaronbabbitt.onmicrosoft.com; Password=password; DeviceID=11hfn41bbqrg580vyvoea05abc; 
         DevicePassword=fuqNIlx%e$.l*+ax_#8O4abc;"/>
   
  </connectionStrings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>


運行命令 aspnet_regiis -pef "connectionStrings" "C:\temp",打開web.config文件,發現加密后的內容為:

 

<?xml version="1.0"?>
<configuration>
  <connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
      <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
          xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
              <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
                  <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
                  <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                      <KeyName>Rsa Key</KeyName>
                  </KeyInfo>
                  <CipherData>
                      <CipherValue>ll2Y+mC2QlqQ/xhj4jpTu4IQwYVoXjJ7ZVomJvWTtfo5f1o8N46lEPED5Z8k4RrSoJWlk2CKsmxIW8Y5soBlsckEe8ZAGfAHezynUXI1X3QNXLX7qm6F2A7NPuZxpEjKv1JEWOKpTxwo3MMXZwiKjuw3e/puOqKYsrfqT+wHK1E=</CipherValue>
                  </CipherData>
              </EncryptedKey>
          </KeyInfo>
          <CipherData>
              <CipherValue>1+ugw1BnAfPhQW3AXtWnjn+KjYFdD4xz56ue8RFjATaNw0HbdyoYm4F+R1zKQP7iqWIebD/gNoYNARFiF7BwHtgOO+7nJsSzkH5i6FgkNaJtvIPUMK7dXF9kCbXEB1MGmnSnjgb8AHhvy68k+Ib1HuWeSvlRDzHuLAOWQ4iM6+Impdcoe27Rs02tRs3a/Jy0NPFhUS+Ps0tTsMJQO5uztcjPbmaNx/jOoxHWaUDWpSx7ucaOK1p/Ko4aN29W1y7iCvvi0wFAOXPi1oega5qSXFnyIADekuPRXxM1vNvKHXBuemxslqtNfazTeY/NxkJ/qRYUbPfdxJRk2MaBZtPOS57nqTWxiRGQJtsUliw4Y0x8sfj/wO0/aDD7T/zFVOj9Ayk15bTNQ2Kpu8qM+DpiUkg/I6l0HDDYz1BZlgItGEjykDjgE6QrB6Woq+svAukEt7bbCitdPPSbliE7d1lxw6VktjQ9/3A1</CipherValue>
          </CipherData>
      </EncryptedData>
  </connectionStrings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

然后你可以將該內容拷貝到你的app.config文件中去。

 

解密的命令為aspnet_regiis -pef "connectionStrings" "C:\temp"。當然解密與加密必須是在同一電腦上進行的,如果某個惡意用戶獲取了你加密后的app.config文件,在他自己的電腦上運行該命令是無法解密該文件的。

 

總結:從CRM外部連接CRM,可以使用上面的CRM“萬能”連接程序,基本上各種deployment方式的CRM,都可以使用它來連接。該程序使用了Assembly microsoft.xrm.client.dll中的OrganizationService類。你需要在app.config或web.config中配置connection string。最后基於安全性,要對配置文件的connectionStrings section進行加密。加密可以使用aspnet_regiis 工具。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM