【问题标题】:DocuSign Connect Webhook with .Net Core 3DocuSign 使用 .Net Core 3 连接 Webhook
【发布时间】:2019-10-17 20:25:44
【问题描述】:

我正在为 DocuSign Connect 在 .Net Core 3 Web API 中创建一个 webhook,以调用我的应用程序创建的信封中的状态更新 + 签名文档并为我提供状态更新。 https://www.docusign.com/blog/dsdev-adding-webhooks-application 的 C# 示例非常有助于让我几乎实现目标。示例中的代码是:

[HttpPost("api/[controller]/ConnectWebHook")]
public void ConnectWebHook(HttpRequestMessage request)
{
    XmlDocument xmldoc = new XmlDocument();
    xmldoc.Load(request.Content.ReadAsStreamAsync().Result);

    var mgr = new XmlNamespaceManager(xmldoc.NameTable);
    mgr.AddNamespace("a", "http://www.docusign.net/API/3.0");

    XmlNode envelopeStatus = xmldoc.SelectSingleNode("//a:EnvelopeStatus", mgr);
    XmlNode envelopeId = envelopeStatus.SelectSingleNode("//a:EnvelopeID", mgr);
    XmlNode status = envelopeStatus.SelectSingleNode("./a:Status", mgr);

    var targetFileDirectory = @"\\my-network-share\";

    if (envelopeId != null)
    {
        System.IO.File.WriteAllText($"{targetFileDirectory}{envelopeId.InnerText}_{status.InnerText}_.xml", xmldoc.OuterXml);
    }

    if (status.InnerText == "Completed")
    {
        // Loop through the DocumentPDFs element, storing each document.

        XmlNode docs = xmldoc.SelectSingleNode("//a:DocumentPDFs", mgr);
        foreach (XmlNode doc in docs.ChildNodes)
        {
            string documentName = doc.ChildNodes[0].InnerText; // pdf.SelectSingleNode("//a:Name", mgr).InnerText;
            string documentId = doc.ChildNodes[2].InnerText; // pdf.SelectSingleNode("//a:DocumentID", mgr).InnerText;
            string byteStr = doc.ChildNodes[1].InnerText; // pdf.SelectSingleNode("//a:PDFBytes", mgr).InnerText;

            System.IO.File.WriteAllText($"{targetFileDirectory}{envelopeId.InnerText}_{documentId}_{documentName}", byteStr);
        }
    }
}

出于测试目的,我的 Web API 允许所有来源并通过 NGROK 暴露给外部世界,并且我可以访问其他测试端点(GET 和 POST),但由于某种原因,当我的信封上有一个值得通知的事件。

我可以在 DocuSign 管理门户日志中看到 Connect 调用了我的 webhook 但得到了远程服务器返回错误:(415) Unsupported Media Type.。这导致我像这样将 [FromBody] 属性添加到我的方法签名中,但是当我的 webhook 被 Connect 调用时,我仍然遇到同样的错误。

[HttpPost("api/[controller]/ConnectWebHook")]
public void ConnectWebHook([FromBody] HttpRequestMessage request)
{
    // ... rest of the method was unchanged, removed for brevity
}

我以前从未使用过HttpRequestMessage,但它看起来很简单。我在 DocuSign 管理门户日志中注意到 Connect 尝试发送到 webhook 的数据只是 XML。我可以尝试更改 webhook 的签名以查找 XmlDocument 而不是 HttpRequestMessage 但我不确定我会错过什么(如果有的话)。

最近有没有其他人通过 webhook 与 Connect 集成?你能让HttpRequestMessage 为你工作吗?

于 2019 年 10 月 18 日添加:

DocuSign 提到内容类型是 XML。内容如下:

<DocuSignEnvelopeInformation 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://www.docusign.net/API/3.0">
  <EnvelopeStatus>...</EnvelopeStatus>
  <DocumentPDFs>...</DocumentPDFs>
</DocuSignEnvelopeInformation>

我在Startup.csConfigureServices 方法中添加了AddXmlSerializerFormatters()。这是 .Net Core 3,我必须按照 https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio 将其设置为 services.AddControllers().AddXmlSerializerFormatters() 而不是 services.AddMVC().AddXmlSerializerFormatters()

随着这一变化,我现在尝试像这样使用[FromForm],并且我的 webhook IS 被击中,但request 输入参数基本上是空的...request.Content = null:

[HttpPost("api/[controller]/ConnectWebHook")]
public void ConnectWebHook([FromForm] HttpRequestMessage request)
{
    // ... rest of the method was unchanged, removed for brevity
}

由于请求是从 DocuSign Connect 发送的,因此我无法控制标头/格式/内容。据我所知,他们没有提交 XML 对象,而不是表单,所以[FromForm] 可能不是要走的路。

【问题讨论】:

  • DocuSign 是否提及内容类型?你可以试试[FromForm],也许...?
  • 该链接示例不适用于 .net 核心。 HttpRequestMessage 不再是 .net 核心框架中的一等公民。
  • 你有xml序列化设置好吗? (AddXmlSerializerFormatters() 在启动等...)
  • stackoverflow.com/questions/44538772/… 建议 ne1410s 建议 FromForm 而不是 FromBody
  • @ne1410s,我更新了帖子以表明 [FromForm] 没有帮助,而且可能不适合我收到的内容。

标签: c# .net-core docusignapi webhooks


【解决方案1】:

该链接示例不适用于 .net 核心。 HttpRequestMessage 不再是 asp.net-core 框架中的一等公民,将被视为普通模型。

只需直接从请求的正文中提取内容,其余部分应与示例中的内容相同。

[HttpPost("api/[controller]/ConnectWebHook")]
public IActionResult ConnectWebHook() {

    Stream stream = Request.Body;

    XmlDocument xmldoc = new XmlDocument();
    xmldoc.Load(stream);

    var mgr = new XmlNamespaceManager(xmldoc.NameTable);
    mgr.AddNamespace("a", "http://www.docusign.net/API/3.0");

    XmlNode envelopeStatus = xmldoc.SelectSingleNode("//a:EnvelopeStatus", mgr);
    XmlNode envelopeId = envelopeStatus.SelectSingleNode("//a:EnvelopeID", mgr);
    XmlNode status = envelopeStatus.SelectSingleNode("./a:Status", mgr);

    var targetFileDirectory = @"\\my-network-share\";

    if (envelopeId != null) {
        System.IO.File.WriteAllText($"{targetFileDirectory}{envelopeId.InnerText}_{status.InnerText}_.xml", xmldoc.OuterXml);
    }

    if (status.InnerText == "Completed") {
        // Loop through the DocumentPDFs element, storing each document.

        XmlNode docs = xmldoc.SelectSingleNode("//a:DocumentPDFs", mgr);
        foreach (XmlNode doc in docs.ChildNodes) {
            string documentName = doc.ChildNodes[0].InnerText; // pdf.SelectSingleNode("//a:Name", mgr).InnerText;
            string documentId = doc.ChildNodes[2].InnerText; // pdf.SelectSingleNode("//a:DocumentID", mgr).InnerText;
            string byteStr = doc.ChildNodes[1].InnerText; // pdf.SelectSingleNode("//a:PDFBytes", mgr).InnerText;

            System.IO.File.WriteAllText($"{targetFileDirectory}{envelopeId.InnerText}_{documentId}_{documentName}", byteStr);
        }
    }

    return Ok();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    相关资源
    最近更新 更多