使用 SignalR 和 Dynamics CRM 进行实时开发





3.00/5 (2投票s)
本教程演示了如何创建使用 ASP.NET SignalR 提供实时消息功能的 Microsoft Dynamics CRM 扩展。
引言
本教程演示了如何创建使用 ASP.NET SignalR 提供实时消息功能的 Microsoft Dynamics CRM 扩展。您将编写插件和 JavaScript 扩展来实时记录联系人实体 (Contact entity) 的更改。
背景
ASP.NET SignalR 是一个促进实时 Web 功能开发的库。它允许客户端和服务器之间的双向通信。SignalR 在可用时使用 WebSockets,并为旧版浏览器回退到其他传输技术。该库基于 OWIN (Open Web Interface for .NET),它定义了 Web 应用程序和服务器之间的抽象层。因此,SignalR 可以托管在您自己的进程中。
创建服务器
首先,您将设置一个托管在 ASP.NET MVC 5 应用程序中的服务器。
- 打开 Visual Studio 2015 并创建一个新的空 ASP.NET MVC 5 项目。
- 通过 Nuget 或包管理器控制台安装 Microsoft.AspNet.SignalR 包。
您的解决方案应已添加包含 SignalR 和 jQuery 脚本的 Script 文件夹。
- 在解决方案资源管理器中,右键单击项目,然后选择“添加”|“新建项”。选择“SignalR Hub 类(v2)”并创建一个名为 LogHub.cs 的新集线器。
- 将文件中的代码替换为以下代码。
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace SignalRHost
{
[HubName("logHub")]
public class LogHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addLog(name, message);
}
}
}
在这里,您定义了客户端将用于调用您的服务器的集线器接口。
- 再次右键单击项目,然后选择“添加”|“新建项”。选择“Owin 启动类”。按照以下代码片段设置启动类。
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SignalRHost.Startup))]
namespace SignalRHost
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR(new HubConfiguration
{
EnableJSONP = true
});
}
}
}
EnableJSONP
参数启用了服务器端跨域调用 (Cross Domain Calls) 的 JSONP。
- 创建一个名为 LogPanel.html 的新 HTML 文件并复制以下代码。
<!DOCTYPE html>
<html>
<head>
<title>Dynamics CRM Log Panel</title>
<meta charset="utf-8" />
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 10px;
}
td {
text-align: center;
}
</style>
</head>
<body>
<div>
<h2>Dynamics CRM Log Panel</h2>
<table border="1" id="logtable">
<tr>
<th>Name</th>
<th>Modified On</th>
</tr>
</table>
</div>
<script src="/Scripts/jquery-1.6.4.min.js"></script>
<script src="/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="http://serverurl/signalr/hubs"></script>
<script src="LogPanel.js"></script>
</body>
</html>
通过此页面,您将能够查看从客户端发送的日志。将 serverurl
替换为您的 SignalR 服务器的地址。
- 创建一个名为 LogPanel.js 的新 JavaScript 文件并复制以下代码。
$(function () {
// Reference the auto-generated proxy for the hub.
var logPanel = $.connection.logHub;
// Create a function that the hub can call back to display messages.
logPanel.client.addLog = function (name, date) {
$('#logtable').append('<tr><td>' + name
+ '</td><td>' + date + '</td></tr>');
};
// Start the connection.
$.connection.hub.start().done(function () {
//calback
});
});
在代码中,您首先引用集线器的自动生成代理。然后,您创建一个回调函数,该函数可以由集线器触发以显示消息。接下来,您启动连接,您还可以在 `done()` 回调函数中添加代码,该函数将在连接启动后触发。
Dynamics CRM 的 JavaScript 扩展
在此部分,您将创建一个 JavaScript 表单扩展,该扩展将在联系人表单 (Contact form) 的 `onSave` 事件上触发。在这里,我们将假设 SignalR 服务器与 CRM 位于不同的域,因为这在专业项目中通常是这种情况。
- 在 Dynamics CRM 中,创建一个名为 SignalR 的新解决方案。
- 将联系人实体和以下文件添加到解决方案。
`new_jquery` 代表 Hub 项目中使用的 jQuery 库,`new_signalr.js` 代表同一项目中的 SignalR 库。
- 在 SignalR 解决方案中,添加一个名为 `new_hubs.js` 的新 Web 资源。转到以下 URL。
http(s)://serverurl/signalr/hubs
将此文件的内容复制到 Dynamics CRM 中的 `new_hubs.js` 资源中。此文件包含自动生成的 Hub 代理,它使您能够使用 Hub 项目中定义的 API 调用服务器。
- 在 SignalR 解决方案中创建一个新的 Web 资源并复制以下代码。
function OnSave() {
var connection = $.connection('http://serverurl/signalr');
$.connection.hub.url = 'http://serverurl/signalr/hubs';
var loghub = $.connection.logHub;
$.connection.hub.start({
jsonp: true
}).done(function () {
var fullname = Xrm.Page.getAttribute("fullname").getValue();
var date = new Date().toLocaleString();
loghub.server.send(fullname, date);
});
}
在前两行中,您定义了与 SignalR 服务器的连接,并提供了指向自动生成集线器的 URL。接下来,您创建一个 Hub 对象。如您所见,集线器的名称由 SignalRHost 项目中的 `HubName` 参数定义。最后一步是建立客户端和服务器之间的连接。由于这是跨域调用,因此在连接参数中启用了 JSONP。在回调函数中,您通过 `LogHub.cs` 中定义的 `Send` 方法调用服务器。
- 在 SignalR 解决方案中,打开“联系人”|“表单”|“联系人(主表单)”|“表单属性”。在“表单库”中,添加以下 JavaScript 文件(顺序很重要)。
- 在“事件处理程序”部分,添加 `OnSave` 事件。
- 现在,每当您修改联系人之一时,您将在 LogPanel.html 中看到新条目。
JavaScript 客户端扩展适用于 Dynamics CRM 的本地版本和在线版本。
Dynamics CRM 的插件扩展
在此部分,您将实现一个插件,该插件将从服务器端记录对联系人记录的更改。
- 在 Visual Studio 中,右键单击解决方案,然后选择“添加”|“新建项目”。选择“类库”并将其命名为 SignalRPlugin。
- 通过 Nuget 或包管理器控制台安装 Microsoft.AspNet.SignalR.Client 包。
- 通过 Nuget 或包管理器控制台安装 MSBuild.ILMerge.Task 包。
在 Dynamics CRM 中,每当您引用外部库时,都必须确保它们在 Dynamics CRM 中可用。有几种方法可以做到这一点。在本教程中,您将使用 ILMerge 工具将外部库合并到插件 DLL 中。借助 MSBuild.ILMerge.Task 包,我们可以自动化整个过程,并在项目构建期间合并库。
- 为了使 SignalR 在插件中工作,您需要合并两个库:Microsoft.AspNet.SignalR.Client 和 NewtonSoft.Json。ILMerge 将自动合并所有 `Copy Local` 属性设置为 `true` 的库。对于其余程序集,`Copy Local` 属性应设置为 `False`。
- 右键单击项目,选择“添加”|“新建类”,然后添加一个名为 SignalRPlugin 的新类。将以下代码复制到文件中。
using Microsoft.AspNet.SignalR.Client;
using Microsoft.Xrm.Sdk;
using System;
namespace SignalRPlugin
{
public class SignalRPlugin : IPlugin
{
private string _serverUrl;
public SignalRPlugin(string serverUrl)
{
if (String.IsNullOrEmpty(serverUrl))
throw new InvalidPluginExecutionException("serverUrl");
_serverUrl = serverUrl;
}
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context.PostEntityImages.Contains("PostImage") &&
context.PostEntityImages["PostImage"] is Entity)
{
var entity = (Entity)context.PostEntityImages["PostImage"];
try
{
var hubConnection = new HubConnection(_serverUrl);
IHubProxy logHubProxy = hubConnection.CreateHubProxy("logHub");
hubConnection.Start().Wait();
logHubProxy.Invoke("Send", entity["fullname"],
DateTime.Now.ToLocalTime().ToString());
}
catch (Exception e)
{
tracingService.Trace("Exception: {0}", e.ToString());
throw;
}
}
}
}
}
与 JavaScript 实现类似,首先您必须建立与 SignalR 服务器的连接,并为 LogHub 代理创建一个对象。连接建立后,您就可以将数据发送到集线器。服务器 URL 通过构造函数提供,该构造函数允许您在插件注册过程中进行设置。
- 使用强名称密钥文件对插件项目进行签名。只有签名插件程序集才能由 Dynamics CRM 执行。
- 构建插件项目后,打开 Dynamics CRM SDK 中的插件注册工具,并为联系人实体的 Update 步骤注册插件。将 SignalR 服务器 URL 添加到“非安全配置”框中。
- 为联系人实体的 Update 步骤注册 Post Image。您需要确保始终可以访问联系人姓名。
- 更新您的一个联系人进行测试,您将在 LogPanel.html 表中看到新条目。
SignalR 插件扩展仅适用于 Dynamics CRM 的本地版本,因为插件程序集必须在沙盒 (Sandbox) 外部注册。
摘要
本教程演示了在 Dynamics CRM 中利用 SignalR 的两种方法。文章中介绍的示例演示了如何轻松地在 CRM 系统中提供实时功能,包括服务器端和客户端。SignalR 提供客户端和服务器之间的双向通信,因此可以将此研究扩展到在 Dynamics CRM 端接收消息的功能。
您可以在我的 github 仓库 中找到包含最新更新的整个项目。