VansFannel
VansFannel

Reputation: 45911

Posting file with HttpClient to a Web Api

I'm developing an ASP.NET Web Api 2 with C# and .NET Framework 4.7.

I'm trying to upload a file to the web api using a HttpClient instance.

I have added this to Web.Config:

<httpRuntime targetFramework="4.7" maxRequestLength="1048576" />

[ ... ]

<location path="ProductionOrderApi">
  <system.web>
    <httpRuntime executionTimeout="120" maxRequestLength="81920" />
  </system.web>
</location>

[ ... ]

<security>
  <requestFiltering>
    <requestLimits maxAllowedContentLength="1073741824" />
  </requestFiltering>
</security>

This is the web api method:

[HttpPost]
[Route("api/ProductionOrder/{productionOrderName}/Processed")]
public HttpResponseMessage UploadProductionOrderProcessed(
    string productionOrderName,
    byte[] jsonData)
{
    HttpResponseMessage response = null;

    try
    {
        Data.ProductionOrder po = repository
            .SearchFor(p => string.Equals(p.Name, productionOrderName) &&
                        p.Phase == (byte)Phase.Processed)
            .FirstOrDefault();

        if (po == null)
            response = Request.CreateResponse(HttpStatusCode.InternalServerError);
        else
        {
            string json = Encoding.ASCII.GetString(jsonData);

            StoredProcedureErrors error = 
                StoredProcedures.LoadProcessedBatch(connectionString, json);

            if (error == StoredProcedureErrors.NoError)
                response = Request.CreateResponse(HttpStatusCode.Created);
            else
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError);

                exceptionLogger.LogMessage(
                    this.GetType().Name,
                    System.Reflection.MethodBase.GetCurrentMethod().Name,
                    "Database error: " + error);
            }
        }
    }
    catch (Exception ex)
    {
        exceptionLogger.LogCompleteException(
            this.GetType().Name,
            System.Reflection.MethodBase.GetCurrentMethod().Name,
            ex);

        response = Request.CreateResponse(HttpStatusCode.InternalServerError);
    }

    return response;
}

This is client to make the call:

public bool UploadProcessedBatch(string productionOrderName, byte[] jsonData)
{
    string completeUri = string.Format(UploadProcessedBatchUri, productionOrderName);

    return Post<byte[]>(completeUri, jsonData);
}

protected bool Post<T>(string completeUri, T dataToPost)
{
    if (EqualityComparer<T>.Default.Equals(dataToPost, default(T)))
        throw new ArgumentNullException("dataToPost");

    bool result = false;

    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri(_webApiHost);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        HttpContent content = new StringContent(JsonConvert.SerializeObject(dataToPost), Encoding.UTF8, "application/json");
        Task<HttpResponseMessage> response = client.PostAsync(completeUri, content);
        HttpResponseMessage message = response.Result;

        result = (message.StatusCode == HttpStatusCode.Created);

        LatestStatusCode = message.StatusCode;
        ReasonPhrase = message.ReasonPhrase;
    }

    return result;
}

If I make a call with PostMan without posting any jsonData it receives the call, but when I make a call with any jsonData it doesn't call it (I have a breakpoint at first line in Web Api method): I get an exception saying "Cancelled task" with anything else useful.

The file I'm trying to upload it is big (more than 7 MB).

Any idea about what is it happening?

I think the problem is how I sending the data. All the examples that I have found are about sending the data with a Html form but I haven't found anything about how to send it with a HttpClient.

Upvotes: 1

Views: 3148

Answers (1)

Severin Jaeschke
Severin Jaeschke

Reputation: 671

Edit:

So since Web Api 2.1 it is possible to use BSON, a "JSON-like" Format, which is able to send binary formatted data. In the linked Article you'll even find an example using HttpClient.

Before the Introduction of BSON a common way around the limitation of JSON has been to encode the binary as base64.

Orig:

The short of it is you can't simply send a byte[] as a Json Property.

Possible work-arounds are:

  1. Base64 parsing at Client/Server
  2. Another possibility that i haven't been aware of until now is BSON. Look at the official Docs and this Thread for more info.

Maybe someone else has something to add to that list.

Cheers,

Upvotes: 1

Related Questions