Posting an octet-stream to a .NET backend

Posting a binary array from the browser to a backend API can pose a bit of a challenge. In this article I will demonstrate how to accomplish this. The common error returned by the server is a 415 status code. This blog will demonstrate how to achieve this.

The code for this example can be found here. 

Create a new empty API controller called OctetController.

Now add a Put() method that returns an IActionResult. This method takes no parameters, as adding parameters causes the 415 status to be returned with the code never executing.

Update the put method to look like this.

        [HttpPut]
        public IActionResult Put()
        {
            var buffer = new byte[4096];
            var bytes = new List<byte>();
            while( Request.Body.ReadAsync(buffer, 0, buffer.Length).Result > 0 )
            {
                bytes.AddRange(buffer);
            }
            var result = Encoding.UTF8.GetString(bytes.ToArray());
            return Ok(result);
        }

This will read the request stream and push it into your byte array until there are no more bytes left to read. For the response we will simply decode the string and return it in the body.

Now, navigate to your ClientApp/src folder. Open setupProxy.js and change lines 7 through 9 to the following.

const context =  [
  "/api",
];

Now navigate to Home.js. Here we will encode a string to a UInt8Array and send that array as an octet stream to the backend.

import React, { useState } from 'react'
import { Button, Form } from 'reactstrap'

const Home = () => {
  const [resp, setResp] = useState()
  const encoder = new TextEncoder()
  const utf = encoder.encode("Encoded test")

  const onSubmit = async (e) => {
    e.preventDefault()
    const response = await fetch('/api/octet', {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/octet-stream'
      },
      body: utf
    })
    if (response.ok){
      const text = await response.text()
      setResp(text)
    }
  }

  return (
    <div>
      <h1>Post This</h1>
      <Form onSubmit={onSubmit}>
        <Button type='submit'>Post</Button>
      </Form>
      {!!resp &&
        <div>
          <p>{resp}</p>
        </div>
      }
    </div>
  );
}

export default Home

Since we changed the component from a class to a function, update App.js to import it as a function.

import Home from './components/Home';

Now, run the app. When you hit the ‘Post’ button, you should get the test string back and display it.

As always, please drop me a comment below.