In the previous article, we have learned how to integrate HttpClient in ASP.NET Core, and how to use it to fetch the data from Web API. Also, we learned how to send the GET request using both the GetAsync method and the HttpRequestMessage class. As a continuation, in this article, we are going to learn how to send POST, PUT, and DELETE requests using HttpClient in ASP.NET Core. We are going to show you both examples for each request with shortcut methods (PostAsync, PutAsync, DeleteAsync) and with the HttpRequestMessage class.
You can also visit our HttpClient Tutorial page, to see all the articles from this tutorial.
Let’s start.
Sending a POST Request with HttpClient in ASP.NET Core
If you have read our previous article, you know that we have the HttpClientCrudService
class in the CompanyEmployees.Client
application. This class already contains two methods, and we are going to expand it with all the methods from this article.
So, since the configuration is already prepared, we can add a new method to send the POST request to the Web API:
private async Task CreateCompany() { var companyForCreation = new CompanyForCreationDto { Name = "Eagle IT Ltd.", Country = "USA", Address = "Eagle IT Street 289" }; var company = JsonSerializer.Serialize(companyForCreation); var requestContent = new StringContent(company, Encoding.UTF8, "application/json"); var response = await _httpClient.PostAsync("companies", requestContent); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var createdCompany = JsonSerializer.Deserialize<CompanyDto>(content, _options); }
We first prepare a company object that we want to create and serialize it with the Serialize
method. Then, we create a new StringContent
object providing our serialized company, encoding type, and the media type arguments. After that, we use the PostAsync
method to send the POST request to the API. After we receive a response, we check if it is a successful one. Then, we apply a well-known logic (from a previous article) by reading the content with the ReadAsStringAsync
method and deserializing the content using the JsonSerializerOptions
argument. Remember that we created the _options
parameter in a previous article.
At this point, we have to ensure that our client app calls this method. So, let’s modify the Execute
method inside the class:
public async Task Execute() { //await GetCompanies(); //await GetCompaniesWithXMLHeader(); await CreateCompany(); }
Now, if we place a breakpoint in the CreateCompany
method and start both applications:
We can see our created company as a result. You can also check the database if you want.
Using HttpRequestMessage Class to Send the POST Request
The PostAsync
method is a shortcut method because it encapsulates the HttpRequestMessage
class. And as we could see, it works great. But, if we want to have greater control over our request and also to explicitly set up different request options, like headers, we have to use the HttpRequestMessage
class. So, let’s see how we can do that:
private async Task CreateCompanyWithHttpRequestMessage() { var companyForCreation = new CompanyForCreationDto { Name = "Hawk IT Ltd.", Country = "USA", Address = "Hawk IT Street 365" }; var company = JsonSerializer.Serialize(companyForCreation); var request = new HttpRequestMessage(HttpMethod.Post, "companies"); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Content = new StringContent(company, Encoding.UTF8); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var createdCompany = JsonSerializer.Deserialize<CompanyDto>(content, _options); }
Again, we start with a new companyForCreation
object and its serialization. Then, we create a new HttpRequestMessage
object and provide the type of the request and the endpoint’s address. After that, we add an accept header to determine which format we support as a response. Right after that, we populate the Content
of our request by using the StringContent
class and providing the serialized company object and encoding type. Also, we specify the media type of our request with the ContentType
property.
Note: We can configure the ContentType
in the constructor of the StringContent
class as well, but with this implementation, it is easier to understand the process, and where the ContentType
property is coming from.
To send the request, we use the SendAsync
method. After we are sure a successful status code is returned, we read our content and deserialize it.
Now, we can modify the Execute
method:
public async Task Execute() { //await GetCompanies(); //await GetCompaniesWithXMLHeader(); //await CreateCompany(); await CreateCompanyWithHttpRequestMessage(); }
Place a breakpoint in our new method, and start our client app:
There we go. Our company was successfully created.
Also, if we inspect our response, we will find the 201 – Created – status code:
Excellent.
We can continue.
Using HttpClient in ASP.NET Core to Send a PUT Request
Let’s see, how we can send a PUT request using HttpClinet in ASP.NET Core.
As we did with the POST request, we are going to use the shortcut method first, and then show how to do the same thing with the HttpRequestMessage
class.
Before we modify the client project, we just want to mention that our Web API’s UpdateCompany
action returns a NoContent
response. So, there is no content to deserialize on the client-side, just a 204 status code. Of course, you can check the code on your own by visiting our GitHub repo.
That said, we are ready to add a new method in the HttpClientCrudService
class:
private async Task UpdateCompany() { var updatedCompany = new CompanyForUpdateDto { Name = "Eagle IT Ltd.", Country = "USA", Address = "Eagle IT Street 289 Updated" }; var company = JsonSerializer.Serialize(updatedCompany); var requestContent = new StringContent(company, Encoding.UTF8, "application/json"); var uri = Path.Combine("companies", "fc12c11e-33a3-45e2-f11e-08d8bdb38ded"); var response = await _httpClient.PutAsync(uri, requestContent); response.EnsureSuccessStatusCode(); }
In this method, we create a new updatedCompany
object with a modified Address
property. Then, as we did in the CreateCompany
method, we serialize the object and create a new StringContent
providing the serialized object, encoding type, and media type. After that, we create the URI to the controller’s action, which expects the Id of the company we are updating. As soon as we do that, we send our PUT request using the PutAsync
shortcut method and just ensure that we receive a successful status code. In this case the 204 - NoContent
status code.
With this in place, we can modify the Execute
method:
public async Task Execute() { ... await UpdateCompany(); }
Now, let’s put a breakpoint in the UpdateCompany
method and start the app:
Also, if we inspect our database:
We can confirm our company is updated successfully.
Using the HttpRequestMessage Class to Send the PUT Request
As we already said, using the HttpRequestMessage
class allows us more control over our requests. So, let’s see how we can utilize it to send the PUT request:
private async Task UpdateCompanyWithHttpRequestMessage() { var updatedCompany = new CompanyForCreationDto { Name = "Hawk IT Ltd.", Country = "USA", Address = "Hawk IT Street 365 Updated" }; var company = JsonSerializer.Serialize(updatedCompany); var uri = Path.Combine("companies", "29bc0429-eb4d-4eeb-f11d-08d8bdb38ded"); var request = new HttpRequestMessage(HttpMethod.Put, uri); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Content = new StringContent(company, Encoding.UTF8); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); }
When we look at this method, we can see that it has almost the same implementation as the CreateCompanyWithHttpRequestMessage
method. Of course, here we create an additional uri
parameter and we don’t deserialize our response body content since it is empty.
After the method implementation, let’s call it from the Execute
method:
public async Task Execute() { ... await UpdateCompanyWithHttpRequestMessage(); }
And let’s start the app:
There we go. We have a successful result.
Feel free to check the database as well.
Sending a DELETE Request with HttpClient
Since the DELETE request is the simplest of all the previous ones, we are just going to show the code.
So, let’s first see how to send a DELETE request with a shortcut DeleteAsync
method:
private async Task DeleteCompany() { var uri = Path.Combine("companies", "fc12c11e-33a3-45e2-f11e-08d8bdb38ded"); var response = await _httpClient.DeleteAsync(uri); response.EnsureSuccessStatusCode(); }
Also, let’s call this method from the Execute
method:
public async Task Execute() { ... await DeleteCompany(); }
As soon as we run the client app, we are going to get the 204 response. This is a valid response for the Delete action in Web API.
Now, let’s see how we can do the same thing using the HttpRequestMessage class:
private async Task DeleteCompanyWithHttpResponseMessage() { var uri = Path.Combine("companies", "29bc0429-eb4d-4eeb-f11d-08d8bdb38ded"); var request = new HttpRequestMessage(HttpMethod.Delete, uri); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); }
Again, nothing new here. Just one note. We are still adding the accept header to our request because some APIs return the content if something goes wrong. We then have to deserialize that content on the client-side.
And that’s it.
We can call this method from the Execute method and run the app.
We should get the 204 response.
Conclusion
So, in this article, we have learned how to send POST, PUT and DELETE requests from our client application using both the shortcut methods and the HttpRequestMessage class. Combining this with the knowledge we have from the previous article, we have covered all the CRUD methods with the HttpClient class.
In the next article, we are going to learn more about the PATCH request and how to send it with HttpClient.
Until then.
All the best.
Thanks for sharing the excellent article. It helps me to
create my website.
You are most welcome. I’m glad it was useful to you.
it resolve my problem tnx
Why bother to put an article with full working code?
Let’s put an HttpClient code without showing how to initialize it.
FK OFF
Dude, are you serious? If you’ve just read the entire article, you would’ve seen that we’ve shown how to do that (initializing the HttpClient class) in the previous article and that this one is just a continuation.
Additionally, you have a complete source code in front of you and you still can’t find it or you just don’t know how to use it. Well, that still speaks enough about you. If we add the value of your comment to that – nothing else needs to be said.
Thanks for your reply!
Yes, API is returning status code, a created object and the URI.
My question is more about what the HttpClient should return to the ViewModel?
I have the same View / ViewModel for Creating and Updating, in this case a Project. I have a LoadAsync(int? projectId) and if projectId.HasValue it loads that Project and then Initialize(project). If not a new Project is created and then Initialize(project).
public async Task LoadAsync(int? id)
{
var project = id.HasValue
? await _projectClient.GetProjectByIdAsync(id.Value)
: CreateNewProject();
InitializeProject(project);
}
When saving it will Post if Project.Id == 0 and Put if Project.Id has a value. This means that I have to grab that newly created Project after Created to Initialize(project) with that newly created Project or fire LoadAsync(id) again but then I will need that id. If I dont, Project.Id will still be 0.
Should I return the createdProject to the ViewModel and Initialize(createdProject)?
Should I return the response to the ViewModel and there ReadAsStringAsync / DeSerialize and Initialize(createdProject)?
Shoulld I return the response to the ViewModel and grad that id from uri and LoadAsync(id)?
Something else?
Hi!
Thanks for a great book ang tutorial!
When client (Avalonia) makes a HttpClient Post, should we return the created object (In this case, Project) or ResponsMessage to the ViewModel?
Somehow I need to be able to reload the View and I can do that by either LoadAsync(id) but then I need createdProject.Id or I can do it by Initializing the Project again with createdProject if I return that.
Thanks again for this great tutorial!
Well, that response should be returned by your API. It should return a proper status code, a newly created object and an URI where you can fetch that object. We talked about that in our book as well.
Thanks for your reply Marinko.
Yes the API is returning status code, the newly created object and an URI, but how to handle that on the client app?
What should the HttpClient return to the ViewModel? Should it return response and then on the ViewModel ReadAsString and Deserialize? Or return the deseralized object directly? Maybe return respons and then grab that id from url to LoadAsync(id)?
How is this usually done?