【问题标题】:How to build and inspect MultipartFormData objects using Invoke-WebRequest in Powershell?如何在 Powershell 中使用 Invoke-WebRequest 构建和检查 MultipartFormData 对象?
【发布时间】:2020-10-26 17:03:55
【问题描述】:

这是一个复合问题,所以我会尽我所能保持它与标题相关,但首先是背景:

就本问题而言,Invoke-Web/Rest cmdlet 将称为 web-cmdlet。

我有一个[System.Net.Http.MultipartFormDataContent] 对象。包含一个字段。

我可以构建对象:

$MultipartContent = [System.Net.Http.MultipartFormDataContent]::new()

#XML
$stringHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")
$stringHeader.Name = "request"
$StringContent = [System.Net.Http.StringContent]::new($xml, [System.Text.Encoding]::UTF8, "application/xml")
$StringContent.Headers.ContentDisposition = $stringHeader
$multipartContent.Add($stringContent)

然后将它传递给带有详细日志记录的 web-cmdlet,我可以看到负载中包含与请求一起发送的数据。服务器返回一个错误,表明它没有看到任何 XML 数据,但它确认了请求。如果它看到数据并且不喜欢它的格式化方式,则会产生不同的错误。

这 2 种行为向我表明它正在发送数据,但它以一种使其在服务器看来为空的方式发送数据。

如果我明确使用-Form 参数并让web-cmdlet 处理[System.Net.Http.MultipartFormDataContent] 的创建,则请求成功。

所以我知道它应该可以工作,但我无法确定我在做什么与使用 -Form 不同。我遵循了 Mark Kraus 的指示:Here,他创建了这个特殊功能,但我无法手动让它工作。

有人如何跟踪这些 cmdlet 以深入挖掘?

示例 [A] - 使用成功的 -Form

$XMLStringObject = @"
<request>
<parameters>             
</parameters>                   
</request>  
"@

$Params = @{
    URI        = "https://URL.com/xml"
    Credential = $Credential
    Form       = @{"request" = $XMLStringObject }
    Method     = "Post"
}

Invoke-RestMethod @Params

【问题讨论】:

  • 为什么要在请求中设置Content-Disposition?表单数据是一种内容类型。那么您需要发送表单还是 XML?
  • 关于使用 -Form 的工作示例,请参见编辑示例 [A]。我的假设(可能是错误的)是,如果表单字段采用 IDictionary 值“请求”,则它必须是恰好采用 XML 的表单字段。
  • 是的。恰好是 XML 的表单字段不是 XML 内容类型。使用 Fiddler 或类似工具检查请求详细信息。 telerik.com/fiddler
  • 将引号文字添加到 $stringheader.name 有助于在 MacOS 上成功提交。参见示例 [B]。现在已解决。

标签: c# .net powershell .net-core


【解决方案1】:

在 [ContentDispositionHeaderValue] 对象上的 $stringHeader.name 的值中添加引号文字 ""。

$XMLStringObject = @"
<request>
<parameters>             
</parameters>                   
</request>  
"@


$MultipartContent = [System.Net.Http.MultipartFormDataContent]::new()
$stringHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")
$stringHeader.Name = '"request"'
$StringContent = [System.Net.Http.StringContent]::new($xml, [System.Text.Encoding]::UTF8, "application/xml")
$StringContent.Headers.ContentDisposition = $stringHeader
$multipartContent.Add($stringContent)

Related Stackoverflow

Related Github - PR in web-cmdlet modules that adds quotes

您可以查看将通过调用发送的 [MultipartFormDataContent] 对象的文本表示。 ReadAsStringAsync() 在对象上。

从上面的代码$multipartContent.ReadAsStringAsync()返回:

--f657665b-b82f-49b2-a67c-8ff35da8ea6c
Content-Type: application/xml; charset=utf-8                                         
Content-Disposition: form-data; name="request"

<request>
<parameters>             
</parameters>                   
</request>                                                                         

--f657665b-b82f-49b2-a67c-8ff35da8ea6c--

在原始代码中,name=request 没有引号,导致接收服务器的行为无法识别该字段的值。

修正语法后,您可以将 [MultipartFormDataContent] 对象提交给 Invoke-RestMethodInvoke-WebRequest 的 Body 参数。 Documentation

$Params = @{
    URI        = "https://URL.com/xml"
    Credential = $Credential
    Body       = $multipartContent
    Method     = "Post"
}

Invoke-RestMethod @Params 

如果这些更改不起作用,您可以使用 Fiddler 读取请求以查看是否正在发送对象。

在我的情况下,上面是正确的,但是我的一个测试函数意外地包装了 [multiparFormDataContent] 对象,因此它不会发送文本表示,而是只发送对象的文字名称“System.Net. Http.MultipartContent”(哎呀!)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2017-07-26
    • 2015-12-03
    相关资源
    最近更新 更多