Building RESTful Web Services with .NET Core
上QQ阅读APP看书,第一时间看更新

POST

POST is used to create a resource. In our case, we will try to create a product using a POST request to the server. Before doing that, we will make a few changes to our project. You can find all related code on GitHub (https://github.com/PacktPublishing/Building-RESTful-Web-services-with-DOTNET-Core), so don't worry at all!

Why wait then? Let's write the Post method as follows:

 // POST: api/Products
[HttpPost]
public async Task<IActionResult> Post([FromBody]Product product)
=> (await _productService.CreateProductAsync(product))
? (IActionResult)Created($"api/products/{product.Id}", product) // HTTP 201
: StatusCode(500); // HTTP 500

The action method calls CreateProductAsync of the related service and checks if the operation was successful. If successful, it sends back 201, else 500. Note that to send back the correct status code, we are leveraging the IActionResult. This interface has a large set of subclasses that are accessible via the Controller class. Since we inherit from the Controller base class, we can easily use methods such as StatusCode to return our intended status according to the operation we performed on the resource.

In the previous section, we mentioned that on POST success, we should get 201 CREATED and on failure, it should send a generalized 500 Internal Server Error response. That is what the code does.

There is another interesting thing, that is: Created($"api/products/{product.Id}", product). This is a method inside the Controller class which assigns the URL to the location and 201 to the status code of the response. Don't believe me!? Okay, let me prove it by way of Postman, right away.

Have a look at the following screenshot taken from the Postman request screen:

Notice that we passed the data for a product as JSON and after creating the product, the API returned us the status code as 201 Created and the URL of the new product created, which is api/products/1. What that means is that when you run this URL as a GET request, you will receive the newly created product details. Simple, isn't it?

As you can see, the datatype of the passed product details is JSON, but the question is, who told the server that it is in that format? Well, that's the request header content-type set with value application/json. You can see that in the last screenshot. A default encoding of charset=utf-8 is appended by Postman.

However, interestingly, how come Postman knew that we wanted the datatype content to be JSON? It can't set it automatically. I told it to do that.

The option to set any type of request header is just below the URL textbox. Refer to the following screenshot, which shows that I have set the content-type header:

For the previously mentioned GET request, which returns the product details by ID, we can design the action method as follows:

// GET: api/Products/1
[HttpGet("{id}")]
public Task<Product> Get(int id)
=> _productService.GetOrderAsync(id);

Here, we are providing a template argument of "{id}" to [HttpGet]. This will make sure that one HTTP Get route such as api/orders/1 is available—where the ID is a variable passed to the GET request.

We have a service called ProductService which is implementing the interface IProductService and through the constructor of the controller, the service (dependency) is injected, which is called dependency injection. With .NET Core, it's very easy to handle dependencies with the built-in inversion of control container. If you are not getting what I am talking about, then I would highly recommend going through my other book on this topic, Dependency Injection in .NET Core (https://www.packtpub.com/application-development/dependency-injection-net-core-20).