8

How do you accept a byte[] in WebAPI controller in .net core. Something like below:

    [HttpPost]
    public IActionResult Post(byte[] rawData)
    {
        try
        {
            System.Diagnostics.Trace.WriteLine("Total bytes posted: " + rawData?.Length);
            return StatusCode(200);
        }
        catch(Exception ex)
        {
            return StatusCode(500, $"Error. msg: {ex.Message}");
        }
    }

I get 415 Unsupported Media Type error when testing from fiddler. Is this even possible in .net core webapi? I have searched for a while and there are no solutions for .net core. There are examples of BinaryMediaTypeFormatter which would not work with .net core webapi. If this is not possible with webapi then what is the best solution to accept a byte array in .net core web applications?

Our old application is an asp.net forms app. It will call Request.BinaryRead() to get the byte array and process the data. We are in the process of migrating this application to .net core.

Thank you.

2
  • 1
    An alternative might be to accept a string representing the byte array and handle it in the controller endpoint. Commented Jun 18, 2018 at 22:03
  • 1
    @DavidL I did explore this option but this is not a possible solution for my case. We cannot ask our customers to change anything at their end. Commented Jun 18, 2018 at 23:09

1 Answer 1

20

In ended up creating an InputFormatter to read posted data as byte[] array.

public class BinaryInputFormatter : InputFormatter
{
    const string binaryContentType = "application/octet-stream";
    const int bufferLength = 16384;

    public BinaryInputFormatter()
    {
        SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse(binaryContentType));
    }

    public async override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
    {
        using (MemoryStream ms = new MemoryStream(bufferLength))
        {
            await context.HttpContext.Request.Body.CopyToAsync(ms);
            object result = ms.ToArray();
            return await InputFormatterResult.SuccessAsync(result);
        }
    }

    protected override bool CanReadType(Type type)
    {
        if (type == typeof(byte[]))
            return true;
        else
            return false;
    }
}

Configured this in Startup class

        services.AddMvc(options =>
        {
            options.InputFormatters.Insert(0, new BinaryInputFormatter());
        });

My WebAPI controller has the following method to receive the HTTP posted data (Note, my default route has Post as the action instead of Index.)

    [HttpPost]
    public IActionResult Post([FromBody] byte[] rawData)
    {
        try
        {
            System.Diagnostics.Trace.WriteLine("Total bytes posted: " + rawData?.Length);
            return StatusCode(200);
        }
        catch(Exception ex)
        {
            return StatusCode(500, $"Error. msg: {ex.Message}");
        }
    }

After doing an HTTP Post to the controller, the rawData parameter has the posted data in a byte array.

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

1 Comment

A fun thing to note is that if you do this, and then use the VS 2019 built-in OpenAPI/swagger generator, the resulting swagger.json will correctly describe application/octet-stream as a possible input option, but the client code generated from this swagger.json (again, using the VS 2019 built-in Add - Service reference - OpenAPI) will be completely messed up. It will send `Content-type: application/octent-stream", but it will encode the binary data in json/base64, so the API will see garbage.

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.