RandomUs1r
RandomUs1r

Reputation: 4190

How can I receive multipart/form-data in web api 2 on OWIN pipeline

I'm having trouble getting my web api 2 method to correctly read my multipart/form-data post from ng-file-upload on the angular UI side.

I'm initiating the call like so:

Upload.upload({
                url: config.ApiUrl + 'Orders/CreateOrder',
                data: request
            }).then(function (response) {
                console.log('Success ' + response.config.data.file.name + 'uploaded. Response: ' + response.data);
            }, function (error) {
                $scope.errors = "Oops! Something went wrong... " + error.statusText;
            });

And this gets me a payload to send to web api:

-----------------------------9623122368016
Content-Disposition: form-data; name="somefield"

Some Value
-----------------------------9623122368016
Content-Disposition: form-data; name="errorMessage"

null
-----------------------------9623122368016
Content-Disposition: form-data; name="success"

false
-----------------------------9623122368016
Content-Disposition: form-data; name="file"; filename="imapdf.pdf"
Content-Type: application/pdf

%PDF-1.2
1 0 obj 
<<
/Producer()
/Author()
/Title()
/Subject()
/Keywords()
/CreationDate(D:20040106)
/ModDate(D:20040106)
/Creator()
>> 
endobj
2 0 obj 
<<
/Type/XObject
/Subtype/Image
/Name/wpt1
/Width 41
/Height 15
/BitsPerComponent 8
/ColorSpace/DeviceRGB
/Length 100
/Filter [/FlateDecode] >>
stream
xsqH0s 

I can't access HttpContext.Current.Request.Filesbecause I'm using the OWIN pipeline, and am not having much luck with Request.Content.ReadAsMultipartAsync

How can I receive my file & it's associated form data in web api 2?

C# Code Update:

public Task<OrderRequest> CreateOrder(OrderRequest orderRequest)
{
    try
    {
        var asdf = OwinHttpRequestMessageExtensions.GetOwinContext(Request);
        if (!Request.Content.IsMimeMultipartContent("multipart/form-data"))
        {
            var provider = new MultipartMemoryStreamProvider();
            this.Request.Content.ReadAsMultipartAsync(provider);

            var content = provider.Contents.First();
            var buffer = content.ReadAsByteArrayAsync();
        }

        var test = orderRequest;
        var a = HttpContext.Current.Request.Files;
    }
    catch (Exception ex)
    {
        throw ex;
    }

    return Task.FromResult<OrderRequest>(null);
}

Upvotes: 0

Views: 2955

Answers (1)

Kirk Larkin
Kirk Larkin

Reputation: 93003

As its name suggests, ReadAsMultipartAsync is an asynchronous function. Because you're not awaiting the call, you're likely ending up in a situation where you're trying to access Contents before it has been populated.

To fix this, you can update your CreateOrder action as follows:

public async Task<OrderRequest> CreateOrder(OrderRequest orderRequest)
{
    ...
    await this.Request.Content.ReadAsMultipartAsync(provider);
    ...
}

All that's changed here is the addition of async before Task<OrderRequest> and await before this.Request.Content.ReadAsMultipartAsync(provider);. You'll also want to add await before content.ReadAsByteArrayAsync(); for the same reason and then you can just return null rather than having to use Task.FromResult at the end.

In fact, here's the entire code with those changes:

public async Task<OrderRequest> CreateOrder(OrderRequest orderRequest)
{
    try
    {
        var asdf = OwinHttpRequestMessageExtensions.GetOwinContext(Request);
        if (!Request.Content.IsMimeMultipartContent("multipart/form-data"))
        {
            var provider = new MultipartMemoryStreamProvider();
            await this.Request.Content.ReadAsMultipartAsync(provider);

            var content = provider.Contents.First();
            var buffer = await content.ReadAsByteArrayAsync();
        }

        var test = orderRequest;
        var a = HttpContext.Current.Request.Files;
    }
    catch (Exception ex)
    {
        throw ex;
    }

    return null;
}

Obviously, this is not a complete solution but I believe it will address your specific problems and allow you to continue your exploration.

Upvotes: 2

Related Questions