从 MS CRM 插件(沙盒)向 Azure 服务总线发送自定义消息

问题描述 投票:0回答:5

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

RemoteExecutionContext

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

我尝试过使用

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

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

有什么办法可以解决上述问题吗?

c# azure dynamics-crm azureservicebus dynamics-crm-online
5个回答
2
投票

这是一种无需额外类且无需使用 ILMerge 即可完成此操作的方法。我验证了这在 CRM 在线版本 9.1.0.646 (Dynamics 365 Customer Engagement) 中有效

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

参考文献: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;
}

1
投票

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

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

这是一个相当不错的样本,尽管有点混乱。尽管如此,它还是展示了如何让基础知识发挥作用,即身份验证和实际调用。

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


1
投票

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

这是一个例子:

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

0
投票

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

您可以采取的一种方法是将构建的 CRM

RemoteExecutionContext
转换为您想要的任何类型。有一个关于如何将 Dynamics 365 与 NServiceBus 集成的示例,它也采用了这种方法。我所指的计算相当于样本中的
CRMAdapterEndpoint
端点。端点使用
Mapper
对象将 JSON 序列化
RemoteExecutionContext
转换为自定义类型
ContactCreate
ContactUpdate
。这将使您实现您想要的目标。


0
投票

是否有人尝试过使用托管身份而不是 sas 令牌执行上述步骤。请分享任何演示。谢谢!!

© www.soinside.com 2019 - 2024. All rights reserved.