Silverlight

利用来自 Silverlight 4 的 Dynamics CRM 4.0 API 功能

Mark Beckner

下载代码示例

越来越多的公司正在实现 Microsoft Dynamics CRM 4.0 解决方案和查找构建可与现有的 Web 服务基于 API 集成的外部应用程序所需。

构建的 Silverlight 的应用程序可以直接与 Microsoft Dynamics CRM 4.0 (此后称为起见 CRM 4.0) 可以证明具有挑战性,由于 Silverlight 调用的异步特性和它无法调用 CRM 4.0 Web 服务直接。 在本文中,您将获得深入探讨如何构建的 Silverlight 应用程序可以读取和写入数据通过 CRM 4.0 Web 服务 API。

解决方案概述

Silverlight 4 和 CRM 4.0 是这两种功能强大的技术 — — 但它们仍不能非常方便地集成。 我将介绍一下背后通过探索 Silverlight 和 CRM 4.0 Web 服务 API 之间的异步通信创建这种集成的详细信息。

在典型的非 Silverlight 应用程序中,Web 服务的调用是同步 — 调用转出,并在应用程序一直等待,直到收到响应。 在此期间,用户不能与应用程序交互,并且必须等待完成,完全往返。 在异步应用程序比如 Silverlight,调用服务熄灭,但应用程序继续甚至之前返回响应时,才会完全起作用。 这产生丰富而动态的用户体验,但它将置于开发人员的更高的要求。

若要了解如何发生这种通信,展示多个功能。 首先,我将介绍如何设置 Silverlight 应用程序以及如何通过与 CRM 4.0 api 将充当包装的 Web 服务进行交互所需的步骤。 接下来,我将谈一谈使用 CRM 4.0 API 和如何读取和写入数据使用的 Web 服务包装的详细信息。 我将与核心系统用户实体在 CRM 4.0 中,工作,还将探讨与动态实体使用。 最后,我将介绍如何处理向 Silverlight 返回的结果集。 最后,您可以轻松地构建您自己的 Silverlight/CRM 4.0 集成。

创建 Silverlight 4 应用程序

有几个步骤才能得到一个 Silverlight 的应用程序配置为与 CRM 4.0 交互运用。 虽然可以直接从 Silverlight 项目引用的 CRM 4.0 SDK 或 Web 服务 API,但实际上不能从代码中调用的接口和方法的大多数。 若要与 CRM 4.0 API 进行交互,必须创建 Web 服务的包装。 此 Web 服务将代理 Silverlight 应用程序和 CRM 4.0 API 可以处理的 Silverlight 的格式之间的调用。 包装 Web 服务可以直接添加到 SilverlightCRMDemo.Web 应用程序。

通过创建一个新的 Silverlight 解决方案名为 CRM40SilverlightDemo 的 Visual Studio 2010 年开始此过程。 当在 Visual Studio 中创建 Silverlight 的应用程序,则总是创建两个项目。 一种是核心 Silverlight 应用程序; 第二个是 ASP。NET 嵌入到网页的 Silverlight 应用程序的应用程序。 此 ASP。NET 应用程序也会将与 CRM 4.0 API 进行交互的 Web 服务包装到家庭。 Silverlight 应用程序将引用此 Web 服务通过服务引用。

若要创建 Web 服务包装,将新的 Web 服务添加到 ASP 中。NET 应用程序并调用它 CrmServiceWrapper。 对于此示例,您将向服务中添加两个 Web 方法 — — 一个用于获取 CRM 数据,另一个将 CRM 数据发布。 图 1 显示哪些这些无存根方法应该看起来是现在。 一旦您能够成功地与此包装服务进行通信,您要更新这些方法来调用实际的 CRM 4.0 API 的 Silverlight 应用程序。

图 1 Web 方法存根 (stub)

public class CrmServiceWrapper : System.Web.Services.WebService
{
  [WebMethod]
  public string GetCRMData()
  {
    return "This is the stubbed return for retrieving";
  }
 
  [WebMethod]
  public string PostCRMData()
  {
    return "This is the stubbed return for posting data";
  }
}

一旦添加到 ASP Web 服务包装。NET 应用程序,将引用添加到它的 Silverlight 应用程序从最简单的方法是在调试模式下运行它,并捕获调试器正在从应用程序的 URL (您可以简单地抓取弹出的浏览器窗口中的 URL)。 捕获后,您可以添加新的服务引用名为 CrmServiceReference 的 Silverlight 应用程序和粘贴该 URL 中的。 将自动更正所有相关的配置文件和代码。 如果您决定不想这样做,则必须处理跨域引用异常 — 和相当多的安装程序,以成功地调试应用程序。

既然存在该引用,则在 Silverlight 应用程序内的实际编码即可成功进行。 代码组成,配上每个 Web 方法的事件处理程序并创建两种方法来处理数据,一旦完成了对这些 Web 方法的调用。 中显示的代码图 2 可以直接添加到 Silverlight 应用程序中的 MainPage.xaml.cs 文件。 运行这将导致同时执行这两种方法。

将代码添加到 MainPage.xaml.cs 的图 2

using CRM40SilverlightDemo.CrmServiceReference;
 
public partial class MainPage : UserControl
{
  public MainPage()
  {
    InitializeComponent();
 
    // Call the GetCRMData Web method.
CrmServiceWrapperSoapClient proxyGet =
      new CrmServiceWrapperSoapClient();
    proxyGet.GetCRMDataCompleted +=
      new EventHandler<GetCRMDataCompletedEventArgs>(proxy_GetCRMDataCompleted);
    proxyGet.GetCRMDataAsync();
 
    // Call the PostCRMData Web method.
CrmServiceWrapperSoapClient proxyPost = new CrmServiceWrapperSoapClient();
    proxyPost.PostCRMDataCompleted +=
      new EventHandler<PostCRMDataCompletedEventArgs>(proxy_PostCRMDataCompleted);
    proxyPost.PostCRMDataAsync();
  }
 
  // Called asynchronously when the GetCRMData Web method returns data.
void proxy_GetCRMDataCompleted(object sender, GetCRMDataCompletedEventArgs e)
  {
    // Do something with the data returned.
string result = e.Result.ToString();
  }
 
  // Called asynchronously when the PostCRMData Web method returns data.
void proxy_PostCRMDataCompleted(object sender, PostCRMDataCompletedEventArgs e)
  {
    // Do something with the data returned.
string result = e.Result.ToString();
  }
}

当您已经验证的 Silverlight 应用程序正在运行且没有错误,并且从 Web 服务返回的数据时,您可以打开您注意构建 CRM 4.0 API 的调用。 这些调用将所有包含在 Web 服务包装 GetCRMData 和 PostCRMData Web 方法已创建的。

与 CRM 4.0 API 交互

有两个主要的 Web 服务可通过 CRM 4.0: CRMService 和 MetadataService。 这些 Web 服务通常是可用的任何项目中引用 (但实际上不允许为多引用从 Silverlight 应用程序时的功能)。 使用 API 的最常见和最有效的方法使用 Microsoft Dynamics CRM SDK (可用于在 bit.ly/6M3PvV 下载)。 SDK 包含大量的类和方法,并简化了之间的通信。NET 框架代码和 CRM 4.0 Web 服务。 在本节中,您将学习如何使用 Web 服务包装从 SDK 的 API 与之交互。

第一步是引用相应的 CRM SDK 程序集。 在 ASP。NET 应用程序驻留 Web 服务包装中,添加两个 SDK 程序集的引用: microsoft.crm.sdk.dll 和 microsoft.crm.sdktypeproxy.dll。 将这些已被引用,一旦相应指令添加到 CrmServiceWrapper.asmx 页的顶部,如下所示:

using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;

下一步是编写代码来实例化将允许您连接到 CRM 4.0 实例的客户关系管理服务。 此代码将使用的 GetCRMData 和 PostCRMData Web 方法,因此它将驻留在其自己的方法。 此方法 (所示图 3) 要求两个关键字字段: 您的 CRM 4.0 实例和主 (位于 /MSCRMServices/2007/crmservice.asmx) 的客户关系管理服务的 URL 的组织名称。 请注意这些字段最好位于代码编译后的轻松修改的配置文件。

图 3 GetCRMService 方法

static public CrmService GetCRMService()
{
  CrmService service = new CrmService();
  CrmAuthenticationToken token =
    new Microsoft.Crm.Sdk.CrmAuthenticationToken();
  token.OrganizationName = "Contoso";
  service.Url = "http://localhost:5555/MSCRMServices/2007/crmservice.asmx";
  service.Credentials = System.Net.CredentialCache.DefaultCredentials;
  service.CrmAuthenticationTokenValue = token;
  return service;
}

查询 CRM 数据

您现在可以打开您注意到 CRM 4.0 中查询数据。 务必要知道有两种类型的 CRM 4.0 中的实体: 核心系统实体和自定义实体。 核心系统实体的自定义实体比更轻松地与合作。 默认情况下可以通过在 C# 中的强类型对象检索所有核心实体上的属性。 自定义实体通常作为动态实体,虽然一种替代方法使其可被视为强类型对象,还查询。 我将演示查询与这两种类型的实体的数据。

查询核心系统实体的一个示例 — 系统用户实体 — 所示图 4。 此代码替换已无存根本文内上文中的同名的 Web 方法。 在此新代码中,哪些查询 CRM 4.0 的系统的所有用户,您将看到几个重要的事情。 首先,处理的类型是对象的"systemuser"。所有核心实体具有其自己的类型。 其次,所返回的结果是 XML 文档的字符串表示形式。

图 4 查询系统用户实体

[WebMethod]
public string GetCRMData()
{
  // This will return all users in CRM in a single XML structure.
StringBuilder xml = new StringBuilder();
  CrmService service = GetCRMService();
 
  QueryExpression query = new QueryExpression();
  query.EntityName = "systemuser";
  query.ColumnSet = new AllColumns();
 
  RetrieveMultipleRequest retrieve = new RetrieveMultipleRequest();
  retrieve.Query = query;
  retrieve.ReturnDynamicEntities = false;
 
  RetrieveMultipleResponse retrieved =
    (RetrieveMultipleResponse)service.Execute(retrieve);
 
  xml.Append("<Users>");
 
  for (int i = 0; i <
    retrieved.BusinessEntityCollection.BusinessEntities.Count; i++)
  {
    systemuser user =
      (systemuser)retrieved.BusinessEntityCollection.BusinessEntities[i];
 
    // Create a string represenation to return to Silverlight app.
xml.Append("<User");
    xml.Append(" FirstName ='" + user.firstname + "'");
    xml.Append(" LastName = '" + user.lastname + "'");
    xml.Append(" SystemUserId = '" + user.systemuserid.ToString() + "'");
    xml.Append(" JobTitle = '" + user.jobtitle + "'");
    xml.Append("/>");
  }
 
  xml.Append("</Users>");
 
  return xml.ToString();
}

您会发现用于将数据返回到 Silverlight 的选项都相当有限。 例如,您不能返回来处理,BusinessEntityCollection,因为 Silverlight 不能直接使用该 API。 其次,有一些与传递给 Silverlight 的 XML Web 服务通过的限制。 因此,在结束时,处理一个简单的字符串可能是您的最佳选择。

查询自定义实体可以是有点更为复杂。 检索数据的最常见方式是通过动态实体以检索结果 (这种检索的示例所示图 5)。 这种方法面临的挑战是在处理具有特定属性的查询表达式内的筛选器中。 尽管一切都是可能的 IntelliSense 不能帮助出很多。

图 5 检索使用动态实体

public static DynamicEntity GetCRMEntity(
  CrmService tmpService, String entityId, String entityName)
{
  DynamicEntity crmEntity = null;
 
  TargetRetrieveDynamic targetRetrieve = new TargetRetrieveDynamic();
 
  // Set the properties of the target.
targetRetrieve.EntityName = entityName;
  targetRetrieve.EntityId = new Guid(entityId);
 
  // Create the request object.
RetrieveRequest retrieve = new RetrieveRequest();
 
  // Set the properties of the request object.
retrieve.Target = targetRetrieve;
  retrieve.ColumnSet = new AllColumns();
 
  // Retrieve as a DynamicEntity.
retrieve.ReturnDynamicEntities = true;
 
  // Execute the request.
RetrieveResponse retrieved = (RetrieveResponse)tmpService.Execute(retrieve);
 
  // Extract the DynamicEntity from the request.
DynamicEntity entity = (DynamicEntity)retrieved.BusinessEntity;
 
  crmEntity = entity;
 
  return crmEntity;
}

尽管如果您想要在 Visual Studio 中有您实体的结构的完全可视性并作为标准实体相同的方式与之进行交互,可能最常见的、 动态的实体的方法,但您可以创建 CrmService 的代理。 在许多情况下,这可以极大地改善开发体验并启用更多的灵活性,在可以将如何编写代码。 代理服务器仅仅是生成的 C# 文件,基于 CrmService WSDL 的最新实例。 若要创建主 CrmService 服务的代理类,打开 Visual Studio 命令提示符并键入以下命令,替换相应的链接以 crmservice.asmx 页面的 URL:

wsdl.exe /out:CrmSdk.cs /namespace:CRM40SilverlightDemo.WebReferences.CrmSdkhttp://localhost:5555/mscrmservices/2007/crmservice.asmx?wsdl

此命令将创建一个 C# 文件中,您可在其中运行可执行 wsdl.exe 目录中调用 CrmSdk.cs。 应将此文件添加到您的项目。 添加后,可以使用完全相同的方式,作为核心系统实体中的任何自定义实体。 如果更改了该实体,只需更新您的代理服务器 C# 文件并将提供新的属性 (或其他修改)。 出于对当前练习的目的,不使用代理服务器 C# 文件。

更新 CRM 4.0 数据

需了解了如何从 CRM 4.0 中检索数据,现在就可以处理通过发布数据。 中显示的代码图 6 显示如何更新系统用户记录。 它要求在传递两个属性: CRM 4.0 记录和昵称的唯一标识符。 若要在这些字符串中传递,必须在 MainPage.xaml.cs,此处所示修改一行代码:

proxyPost.PostCRMDataAsync("f04b02d9-ad5f-e011-a513-000c29330bd5","My Nickname");

请注意该 ID PostCRMData 方法调用中的硬编码。 您需要拿出某种机制来动态地抓取 ID。

图 6 过帐 CRM 4.0 数据

 

[WebMethod]
public string PostCRMData(string userId, string nickname)
{
  CrmService service = GetCRMService();
 
  Key kid = new Key();
  kid.Value = new Guid(userId);
  systemuser entity = new systemuser();
  entity.systemuserid = kid;
 
  entity.
nickname = nickname;
 
  service.Update(entity);
 
  return "success";
}

处理在 Silverlight 中的结果

此时,该解决方案应检索并过帐 CRM 4.0 之间进行数据。 但是,执行任何操作是通过向 Silverlight 返回字符串结果。 GetCRMData 方法返回的数据字符串,它包含 XML 文档与所有用户的记录,但可以与该做什么? 具体取决于该控件,您可能能够直接绑定到 XML 或您可能希望通过返回 XML 分析和处理单个数据元素。

循环遍历返回的结果的示例所示图 7。 此代码演示如何加载到 XML 文档,并依次通过数据的字符串。 在使用在 Silverlight 中的 XML 文档时,最常用的功能来自 XDocument 类。 这可以通过在 Silverlight 项目中添加对 System.Xml.Linq 的引用。

图 7 使用 XDocuments

void proxy_GetCRMDataCompleted(object sender, GetCRMDataCompletedEventArgs e)
{
  XDocument xDoc = XDocument.Parse(e.Result);
 
  string firstName;
  string lastName;
  string ID;
  string title;
 
  // Loop through the results.
foreach (XElement element in xDoc.Descendants("User"))
  {
    firstName = GetAttributeValue(element, "FirstName");
    lastName = GetAttributeValue(element, "LastName");
    ID = GetAttributeValue(element, "SystemUserId");
    title = GetAttributeValue(element, "JobTitle");
  }
}
 
private string GetAttributeValue(XElement element, string strAttributeName)
{
  if (element.Attribute(strAttributeName) != null)
  {
    return element.Attribute(strAttributeName).Value;
  }
  return string.Empty;
}

无限可能

当集成两种技术,有无限可能。 立即采取的下一步措施可能要看一看一些异常处理 (许多 Silverlight 控件隐藏异常,所以您需要在具体情况的基础上处理这个) 和各种控件与集成的方法。 不管您采取的方向,您现在已经获得生成的读取和写入数据与 CRM 4.0 Silverlight 解决方案所需的一切。

Mark Beckner是 Inotek Consulting Group LLC 的创始人。他跨 Microsoft 堆栈,包括 BizTalk、 SharePoint、 动态 CRM 和常规工作。NET 框架开发。他可以达到 mmbeckner@inotekgroup.com

这要归功于以下的技术专家审阅这篇文章: Scott Jones