我正在.Net Core 3 Web API中创建一个Webhook,用于 DocuSign Connect ,以从我的应用程序创建的信封中调用并提供状态更新+签名的文档。 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)不支持的媒体类型。。这样导致我将[FromBody]
属性添加到方法签名中,就像这样,但是当Connect调用Webhook时,仍然出现相同的错误。
[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
,但是我不确定会丢失什么(如果有的话)。
最近有没有其他人通过网络挂钩与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>
我已将AddXmlSerializerFormatters()
添加到ConfigureServices
中的Startup.cs
方法中。这是.Net Core 3,我必须像services.AddControllers().AddXmlSerializerFormatters()
那样设置它,而不是像https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio那样设置services.AddMVC().AddXmlSerializerFormatters()
。
有了这一更改,我现在尝试像这样使用[FromForm]
并击中我的Webhook IS ,但是request
输入参数实际上是空的... {{ 1}}:
request.Content = null
由于请求是从DocuSign Connect发送的,所以我无法控制标题/格式/内容。据我所知,他们没有提交XML对象,也没有提交表单,因此[HttpPost("api/[controller]/ConnectWebHook")]
public void ConnectWebHook([FromForm] HttpRequestMessage request)
{
// ... rest of the method was unchanged, removed for brevity
}
可能不是解决之道。
答案 0 :(得分:1)
该链接示例不适用于.net核心。 HttpRequestMessage
不再是asp.net核心框架中的头等公民,而将被视为普通模型。
仅从请求的正文中直接提取内容,其余内容应与示例中的内容相同。
[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();
}