Reputation: 27842
I got the ByteArrayContent to work
/* MVC Method , ByteArrayContent */
private async Task<HttpResponseMessage> ExecuteProxy(string url)
{
using (var client = new HttpClient(HttpClientHandlerFactory.GetWindowsAuthenticationHttpClientHandler()))
{
byte[] byte1 = new byte[] { 1, 2, 3 };
ByteArrayContent byteContent = new ByteArrayContent(byte1);
this.Request.Method = HttpMethod.Post;
this.Request.Content = byteContent;
return await client.SendAsync(this.Request);
}
}
/* WebApi Delegating Handler , ByteArrayContent */
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var byteArray = request.Content.ReadAsByteArrayAsync().Result;
if (null != byteArray)
{
/* I see the byte of "1,2,3" */
}
}
The below method isn't part of the problem, but I include it for completeness.
public static class HttpClientHandlerFactory
{
public static HttpClientHandler GetWindowsAuthenticationHttpClientHandler()
{
HttpClientHandler returnHandler = new HttpClientHandler()
{
UseDefaultCredentials = true,
PreAuthenticate = true
};
return returnHandler;
}
}
I'm having trouble "getting" the MultipartFormDataContent on the WebApi side of things.
/* MVC Method , MultipartFormDataContent */
private async Task<HttpResponseMessage> ExecuteProxy(string url)
{
using (var client = new HttpClient(HttpClientHandlerFactory.GetWindowsAuthenticationHttpClientHandler()))
{
byte[] byte1 = new byte[] { 1, 2, 3 };
ByteArrayContent byteContent1 = new ByteArrayContent(byte1);
StringContent stringContent1 = new StringContent("StringContent1Value");
byte[] byte2 = new byte[] { 4, 5, 6 };
ByteArrayContent byteContent2 = new ByteArrayContent(byte2);
StringContent stringContent2 = new StringContent("StringContent2Value");
MultipartFormDataContent multipartContent = new MultipartFormDataContent();
multipartContent.Add(byteContent1, "MyByteArrayContent1");
multipartContent.Add(stringContent1);
multipartContent.Add(byteContent2, "MyByteArrayContent2");
multipartContent.Add(stringContent2);
this.Request.Method = HttpMethod.Post;
this.Request.Content = multipartContent;
return await client.SendAsync(this.Request);
}
}
/* WebApi Delegating Handler , MultipartFormDataContent*/
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
/* I have no idea how to change this back into a MultipartFormDataContent .. or however else you parse it */
}
I've googled and read about 40 SOF posts about it. The solution still alludes me.
Upvotes: 1
Views: 2566
Reputation: 27842
So the magic method seems to be ReadAsMultipartAsync
There were two issues with this. One minor, one significant.
ReadAsMultipartAsync is an extension method. (This is the minor issue)
/* System.Net.Http.Formatting.dll */
and
using System.Net.Http.Headers;
This is why I did not see this method originally in the intellisense. (I had not added the reference .. or the using statement to my .cs)
Request.Content.ReadAsMultipartAsync never returns
So below is what I came up with that allows "by name" finding.
/* WebApi Delegating Handler , MultipartFormDataContent*/
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
/* see https://stackoverflow.com/questions/15201255/request-content-readasmultipartasync-never-returns */
IEnumerable<HttpContent> contents = null;
Task.Factory.StartNew(
() =>
contents = request.Content.ReadAsMultipartAsync().Result.Contents,
CancellationToken.None,
TaskCreationOptions.LongRunning, // guarantees separate thread
TaskScheduler.Default)
.Wait();
if (null != contents)
{
//// This could be accomplished with LINQ queries, but I've left the for-loops in ... so its easier to see what's going on
foreach (HttpContent currentHttpContent in contents)
{
if (null != currentHttpContent)
{
if (null != currentHttpContent.Headers)
{
HttpContentHeaders cheaders = currentHttpContent.Headers;
if (null != cheaders)
{
if (null != cheaders.ContentDisposition)
{
System.Net.Http.Headers.ContentDispositionHeaderValue cdhv = cheaders.ContentDisposition;
if (null != cdhv)
{
if (!string.IsNullOrEmpty(cdhv.Name))
{
if (cdhv.Name.Equals("MyByteArrayContent1", StringComparison.OrdinalIgnoreCase))
{
byte[] byteArray = null;
////currentHttpContent.LoadIntoBufferAsync().Wait();
////currentHttpContent.ReadAsByteArrayAsync().ContinueWith(t =>
////{
//// byteArray = t.Result;
////});
byteArray = currentHttpContent.ReadAsByteArrayAsync().Result;
}
/* you can also check for MyByteArrayContent2, StringContent1Value, StringContent2Value as well, left out for brevity */
}
}
}
}
}
}
}
}
}
Other links:
Request.Content.ReadAsMultipartAsync never returns
Multipart form POST using ASP.Net Web API
How to get MultipartFormDataContent in Web.API Post method?
How do I get the file contents of a MultipartMemoryStreamProvider as a byte array?
Post byte array to Web API server using HttpClient
Why is the body of a Web API request read once?
(No answer for the below one)
How to parse MultipartFormDataContent
APPEND:
Here is the linq query I figured out:
if (null != contents)
{
/* sometimes the ContentDisposition.Name is null so the extra where filters are helpful to avoid object-null-reference exception */
HttpContent foundContent = (from cnt in contents
where null!= cnt && null != cnt.Headers && null != cnt.Headers.ContentDisposition && !string.IsNullOrEmpty(cnt.Headers.ContentDisposition.Name) && cnt.Headers.ContentDisposition.Name.Equals("MyByteArrayContent1", StringComparison.OrdinalIgnoreCase)
select cnt).FirstOrDefault();
if (null != foundContent )
{
byte[] byteArray = foundContent .ReadAsByteArrayAsync().Result;
}
}
Upvotes: 1