Problems encountered when. Net core submits forms using httpclient

Time:2020-3-21

Problems

When developing the entry interface of small and micro merchants for wechat payment, it is necessary to upload the ID card image and other data through the form. The wechat payment interface document also indicates that multipart / form data is needed to send the request. . net provides the multipartformdatacontent type to help us build form requests, so there is the following code:

var form = new MultipartFormDataContent()
{
  {new StringContent("Value"),"Name},
  {new bytearraycontent (new byte [] {} / * simulated file data * /), "file," filename}
}

After submitting the official documents of wechat payment, the parameter error has been prompted all the time, which can’t be solved.

Reasons

Through the post man simulation form submission, capture the data package, and compare it with the submission code of C ා, two problems are found.

Original submission of postman:

POST http://api.mch.weixin.qq.com/secapi/mch/uploadmedia HTTP/1.1
User-Agent: PostmanRuntime/7.21.0
Accept: */*
Cache-Control: no-cache
Postman-Token: b6800c0f-3f16-4981-b661-e6d16fc1bb1e
Host: api.mch.weixin.qq.com
Content-Type: multipart/form-data; boundary=————————–639275760242036520206377
Accept-Encoding: gzip, deflate
Content-Length: 566
Connection: keep-alive

—————————-639275760242036520206377
Content-Disposition: form-data; name=”mch_id”

1565111111
—————————-639275760242036520206377
Content-Disposition: form-data; name=”media_hash”

7215E92A8F3F3D0256484EFFF53A25F6
—————————-639275760242036520206377
Content-Disposition: form-data; name=”sign_type”

HMAC-SHA256
—————————-639275760242036520206377
Content-Disposition: form-data; name=”sign”

A1D8B094FA24BE5531D1AC198DE25550
—————————-639275760242036520206377–

C ා code submission:

POST http://api.mch.weixin.qq.com/secapi/mch/uploadmedia HTTP/1.1
Host: api.mch.weixin.qq.com
Content-Type: multipart/form-data; boundary=”e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217″
Content-Length: 502

–e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=mch_id

–e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=media_hash

33F15BC2D17D6FFBC18FA566EF65722E
–e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=sign

1E377684F9BD583D2ED26FB367916C0C
–e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217–

1. Double quotes of boundary

For form requests submitted with multipartformdatacontent, the boundary value of the external content type has a “sign. For the form request submitted by postman, there is no double quotation mark for its boundary value.

So why does it make such a difference? Refer to the explanation of this blog, it is caused by the inconsistent implementation of RFC 2046 in various systems / languages. For multipartformdatacontent behavior, if the value after boundary is enclosed with double quotes, it is standard.

RFC 2612 Original:

2) Although RFC 2046 [40] permits the boundary string to be
quoted, some existing implementations handle a quoted boundary
string incorrectly.

Boundary is a randomly generated string, which is used to split multiple internal contents in HTTP protocol. Why is it randomly generated? It is to prevent this separator from repeating with your internal content and causing accidents. (C ා by default, the GUID is used as a random string. You can also specify it manually through its constructor when constructing multipartformdatacontent.)

2. Key value pairs in the form, double quotation marks of values

The second problem is the content in the form. Their name key value pairs have no double quotes, so you need to specify the double quotes manually when adding content.

Solve the problem

Both problems are caused by double quotes, so you only need to replace the inner double quotes with empty ones or add the missing double quotes before the call.

To solve the first problem, the inner contenttype.parameters can find the key value pair of boundary through LINQ, and replace the inner double quotes.


var boundaryValue = form.Headers.ContentType.Parameters.Single(p => p.Name == "boundary");
boundaryValue.Value = boundaryValue.Value.Replace("\"", String.Empty);

For problem 2, when constructing internal content, its name is manually given double quotes.


var form = new MultipartFormDataContent
{
  {new StringContent(mchId), "\"mch_id\""},
  {new ByteArrayContent(bytes), "media", $"\"{HttpUtility.UrlEncode(Path.GetFileName(imagePath))}\""},
  {new StringContent(mediaHash), "\"media_hash\""},
  {new StringContent(sign), "sign"}
};

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.