Reputation: 30737
I am trying to write tests for a custom MultipartMemoryStreamProvider
- one that is very similar to this MultipartFormDataMemoryStreamProvider.cs
In particular, I am trying to test my own implementation of the GetStream(HttpContent parent, HttpContentHeaders headers)
method.
It requires an HttpContent and HttpContentHeaders.
To achieve this I am trying to create a controller context and controller, then pass through the appropriate properties from that controllers request.
In fact, I have tried to implement the answer on this (duplicate) question: Testing a Web API method that uses HttpContext.Current.Request.Files?
Everything I try results in the Content-Disposition
on the headers being null
As shown in the images below:
Any idea what I am missing?
For code-sake, here is a copy of the code. You will notice it's the same as that in the answer on the other question. I just can't get passed the null content-disposition.
var content = new ByteArrayContent(new Byte[100]);
content.Headers.Add("Content-Disposition", "form-data");
var controllerContext = new HttpControllerContext
{
Request = new HttpRequestMessage
{
Content = new MultipartContent { content }
}
};
var controller = new MockController();
controller.ControllerContext = controllerContext;
MockController is simply:
public class MockController : ApiController { }
Upvotes: 4
Views: 2978
Reputation: 13182
If you expect Content-Disposition
header to appear in MultipartContent
you should set in on MultipartContent
not on ByteArrayContent
.
But if you want to emulate file upload form a web page you do need to set Content-Disposition
header on ByteArrayContent
. In that case to see the value of Content-Disposition
you need to iterate through inner contents of MultipartContent
:
var multipart = await Request.Content.ReadAsMultipartAsync();
foreach (var content in result.Contents)
{
var contentDisposition = content.Headers.ContentDisposition;
}
You can check this tutorial: Sending HTML Form Data in ASP.NET Web API. It might be a bit outdated but it shows the idea.
EDIT: Just checked and it appears to be same tutorial mentioned in the answer you referenced in your question.
Upvotes: 2
Reputation: 11573
Please correct me if I'm wrong. Here's my analysis of the situation:
The class MultipartContent
basically has a collection of child HttpContent
objects (ByteArrayContent
is inheriting from HttpContent
). It overrides the WriteNextContentHeadersAsync
method and writes out the headers from its child HttpContent
collection. It does have its own Headers
property, but it is inherited from HttpContent
, no overrides, nothing special.
So, what you are trying to do, is basically not implemented in that way. The MultipartContent
does write out the headers to the output, but does not reflect these headers in its own Headers
collection.
You could override this behavior. Simple and naive implementation could be the following:
public class MyMultipartContent : MultipartContent
{
public override void Add(HttpContent content)
{
base.Add(content);
foreach (var header in content.Headers.ToList())
{
if (!this.Headers.Contains(header.Key))
this.Headers.Add(header.Key, header.Value);
}
}
}
So every header from a child HttpContent
will be added to the MultipartContent's
Header
collection. Maybe this is completely wrong and will cause errors and other problems :)
Another option would be to enumerate child HttpContent
objects in the MultipartContent
:
foreach (var httpContent in (MultipartContent) controller.Request.Content)
{
var header = httpContent.Headers.ContentDisposition; // here it is
}
Another option is to use an extension method:
public static class MyExtensions
{
public static ContentDispositionHeaderValue MyGetContentDisposition(this HttpContent httpContent)
{
if (httpContent is MultipartContent)
return ((MultipartContent) httpContent).FirstOrDefault(c => c.Headers.ContentDisposition != null)?.Headers.ContentDisposition;
return httpContent.Headers.ContentDisposition;
}
}
If the httpContent
is MultipartContent
then return the first not null ContentDisposition
header from it's child HttpContent
collection.
var hereItIs = controller.Request.Content.MyGetContentDisposition();
Upvotes: 0