3

I need to receive a json object together with a byte array in a c# Web API application.

This is how I am sending the data:

public bool SendMedia(string method, Media media)
{
    string filePath = Path.GetFullPath(Path.Combine(filesDirectory, media.FileName));
    if (!File.Exists(filePath))
    {
        return false;
    }
    using (var client = new HttpClient())
    using (var content = new MultipartContent() )
    {
        content.Add(new StringContent(JsonConvert.SerializeObject(media), Encoding.UTF8, "application/json"));
        byte[] b = File.ReadAllBytes(filePath);
        content.Add(new ByteArrayContent(b, 0, b.Length));
        var response = client.PostAsync(new Uri(baseUri, method).ToString(), content).Result;
        if (response.IsSuccessStatusCode)
            return true;
        return false;
    }
}

And this is how I am trying to receive it:

// POST: api/Media
[ResponseType(typeof(Media))]
public HttpResponseMessage PostMedia(Media media, byte[] data)
{
    int i = data.Length;
    HttpResponseMessage response = new HttpResponseMessage();
    if (!ModelState.IsValid)
    {
        response.StatusCode = HttpStatusCode.ExpectationFailed;
        return response;
    }

    if (MediaExists(media.MediaId))
        WebApplication1Context.db.Media.Remove(WebApplication1Context.db.Media.Where(p => p.MediaId == media.MediaId).ToArray()[0]);
    WebApplication1Context.db.Media.Add(media);


    try
    {
        WebApplication1Context.db.SaveChanges();
    }
    catch (DbUpdateException)
    {
        response.StatusCode = HttpStatusCode.InternalServerError;
        return response;
        throw;
    }

    response.StatusCode = HttpStatusCode.OK;
    return response;
}

I don't know much about developing for web at the moment. Is sending a MultipartContent the right approach?

1 Answer 1

3

The framework can only bind one item from the body so what you are trying to attempt would not work.

Instead, read the request content just as you sent it and extract the parts.

[ResponseType(typeof(Media))]
public async Task<IHttpActionResult> PostMedia() {

    if (!Request.Content.IsMimeMultipartContent()) { 
        return StatusCode(HttpStatusCode.UnsupportedMediaType); } 

    var filesReadToProvider = await Request.Content.ReadAsMultipartAsync(); 

    var media = await filesReadToProvider.Contents[0].ReadAsAsync<Media>(); 
    var data = await filesReadToProvider.Contents[1].ReadAsByteArrayAsync();

    int i = data.Length;

    if (!ModelState.IsValid) {
        return StatusCode(HttpStatusCode.ExpectationFailed);
    }

    if (MediaExists(media.MediaId))
        WebApplication1Context.db.Media.Remove(WebApplication1Context.db.Media.Where(p => p.MediaId == media.MediaId).ToArray()[0]);
    WebApplication1Context.db.Media.Add(media);


    try {
        WebApplication1Context.db.SaveChanges();
    } catch (DbUpdateException) {
        return StatusCode(HttpStatusCode.InternalServerError);
    }

    return Ok(media);
}

Note also that in your original code you state the the action has a [ResponseType(typeof(Media))] but an object of that type was never returned. The above answer includes the model in the Ok(media) response.

The is a very simplified example. add any validation as necessary.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks! Il'l give it a try.
The request is now received by the method, huge improvement, but when it trys to cast it as a MultipartContent it stays as null. Debugger says that Request.Content is a System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent, but when I try to cast it to that it, it wont build because it says it isn't accessible due to its protection level.
Ok let me take a look.
I think that I got it. if (!Request.Content.IsMimeMultipartContent()) { return StatusCode(HttpStatusCode.UnsupportedMediaType); } var filesReadToProvider = await Request.Content.ReadAsMultipartAsync(); var media = await filesReadToProvider.Contents[0].ReadAsAsync<Media>(); var data = await filesReadToProvider.Contents[1].ReadAsByteArrayAsync();
@demilp that is correct. you figured it out before I got back to my machine. updating answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.