【问题标题】:Send custom messages to Azure Service Bus from MS CRM Plugins (Sandbox)从 MS CRM 插件(沙盒)向 Azure 服务总线发送自定义消息
【发布时间】:2017-09-02 11:55:37
【问题描述】:

我知道我可以在 MS CRM 中注册一个新的“服务端点”并使用它向 Azure 服务总线发送消息,但这...并不是我真正想要的。上述方法最终发送一个序列化的RemoteExecutionContext

就我而言,我希望完全控制服务总线消息将包含的内容。这意味着序列化我自己的类。

我尝试使用WindowsAzure.ServiceBus nugget(和 ILmerging 新 DLL),但这仅适用于非沙盒设置(本地 CRM),但我也希望我的解决方案在 CRM 中工作在线的。当尝试在 CRM Online 中使用相同的代码然后尝试创建 TopicClient 时会引发错误:

System.Security.SecurityException:该程序集不允许部分受信任的调用者

有没有办法解决上述问题?

【问题讨论】:

  • WindowsAzure.ServiceBus 在 GitHub 上有开源。是否有任何特殊原因导致您无法获取源代码并仅将其与您的 CRM 插件一起编译?
  • @PawelGradecki 嗯,我可以试试,但我怀疑这是否能解决问题。这可能是因为 CRM 沙盒不信任 System.Web(例如,即使您甚至不能使用 UrlEncode)。顺便说一句:问题不在于合并外部 DLL。我在沙盒模式下运行的 CRM 解决方案中成功使用了大量外部 DLL。
  • 我知道线程很旧,我遇到了同样的问题。正如在回答中提到的使用 Rest api 进行服务总线和发送/使用消息的简单方法,但我希望注册端点而不是插件步骤。注意只注册 Endpoint,然后在我的插件中我可以使用 iserviceendpointnotificationservice execute 方法来发送插件的上下文。但我希望发送自定义消息而不是上下文。有什么想法可以做到吗?
  • @AnkUser 这是一个完全不同的问题,超出了这里讨论的范围。
  • 我明白了。我正在从 MS CRM 插件发送自定义消息是这里讨论的内容,我认为我有几乎相似的请求,实际上可行的解决方案是我所倾向于的,但需要了解更多关于 iserviceendpointnotificationservice 的信息,它来自 plugincontext

标签: c# azure dynamics-crm azureservicebus dynamics-crm-online


【解决方案1】:

这是一种无需额外类且不使用 ILMerge 的方法。我在 CRM 在线版本 9.1.0.646(Dynamics 365 Customer Engagement)中验证了此功能

您的插件项目将需要以下引用和 using 语句。

参考:System.Net、System.Net.Http 使用:System.Net、System.Net.Http、System.Security.Cryptography、System.Globalization

在这个示例代码中,我构建了一个名为 json 的字符串变量,它是我要发布的 JSON 消息。然后下面的代码会发送消息。

string asbUri = 
    "https://<azurenamespace>.servicebus.windows.net/<topicname>/messages";
TimeSpan ts = new TimeSpan(0, 0, 90);
string sasToken = GetSASToken("sb://<azurenamespace>.servicebus.windows.net", " 
    <nameofSASkey>", "<SASKeyValue>", ts);

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", sasToken);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, asbUri)
{
    Content = new StringContent(json, Encoding.UTF8, "application/json")
};
HttpResponseMessage response = client.SendAsync(request).Result;

private static string GetExpiry(TimeSpan ttl)
{
   TimeSpan expirySinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1) + ttl;
   return Convert.ToString((int)expirySinceEpoch.TotalSeconds);
}

public static string GetSASToken(string resourceUri, string keyName, string key, 
TimeSpan ttl)
{
   var expiry = GetExpiry(ttl);
   //string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
   //NOTE: UrlEncode is not supported in CRM, use System.Uri.EscapeDataString instead
   string stringToSign = Uri.EscapeDataString(resourceUri).ToLowerInvariant() + "\n" 
        + expiry;
        HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));

   var signature = 
   Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
   var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature 
       sr={0}&sig={1}&se={2}&skn={3}",
       Uri.EscapeDataString(resourceUri).ToLowerInvariant(), 
       Uri.EscapeDataString(signature), expiry, keyName);
   return sasToken;
}

【讨论】:

    【解决方案2】:

    我找到了一种与 Sandboxed MS CRM 兼容的方法。

    这个想法是使用 Azure REST 端点向其发送消息。验证和使用相当容易......至少如果你有一个工作示例,我能够找到here

    这是一个相当不错的样本,虽然有点乱。尽管如此,它仍然展示了如何让基础工作,即身份验证和实际调用。

    (次要注意:根据示例从 ASB 读取主题消息对我来说无法可靠地工作 - 它会工作一次,然后在身份验证密钥超时之前无法工作......这并没有因为我需要而困扰我仅发送消息,但如果这是您需要的功能,那么这可能不那么简单。)

    【讨论】:

      【解决方案3】:

      我知道这是一个老问题,但我最近不得不做一些类似的事情,我使用 SharedVariable Collection 将其他详细信息和参数传递给 ServiceBus。

      这是一个例子:

      context.SharedVariables.Add("AttachmentType", attachmentType);
      

      【讨论】:

      • 这并没有解决如何将自定义数据类型作为消息实际发送到服务总线的问题,因为它仍然使用RemoteExecutionContext 作为 SB 调用的基础......
      【解决方案4】:

      对于 CRM Online,您可以将消息转换/处理的逻辑置于沙盒之外。它需要有一些外部计算。考虑到您已经在线使用 CRM,这应该不是问题。

      您可以采取的一种方法是将 CRM 构造的 RemoteExecutionContext 转换为您想要的任何类型。有一个sample 介绍如何将 Dynamics 365 与 NServiceBus 集成,它也采用这种方法。我所指的计算相当于示例中的CRMAdapterEndpoint 端点。端点使用Mapper 对象将JSON 序列化RemoteExecutionContext 转换为自定义类型ContactCreateContactUpdate。这样你就可以实现你想要的。

      【讨论】:

      • 虽然技术上是正确的,但我试图简化解决方案,而不是让它变得更复杂。 :/ 控制消息的需要正是源于这个事实——我可以使用RemoteExecutionContext,但是发送一个序列化的模型类似乎更容易以后使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-19
      • 1970-01-01
      相关资源
      最近更新 更多