在这一节中我们介绍HTTP另外的几种请求方式:
POST
PUT
DELETE
PATCH
新增MVC项目命名为AspNetCore.HttpClientWithHttpVerb,在该项目中我们新建一个api作为服务器端,在当前项目的HomeController中使用HttpClient来请求该api
1.TodoItems api
我们使用EFCore作为ORM并将数据存储到内存中,在Model文件夹下新增TodoItems类和TodoContext类:
在Program类中新增EF Core相关服务:
在Controllers文件夹下新增api命名为TodoItemsController并继承自ControllerBase
using AspNetCore.HttpClientWithHttpVerb.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace AspNetCore.HttpClientWithHttpVerb.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;
public TodoItemsController(TodoContext context)
{
_context = context;
}
public async Task<IEnumerable<TodoItem>> Get() =>
await _context.TodoItems.AsNoTracking().ToListAsync();
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> Get(long id)
{
var request = HttpContext.Request;
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return todoItem;
}
[HttpPost]
public async Task<IActionResult> Post(TodoItem todoItem)
{
var request = HttpContext.Request;
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Get), new { Id = todoItem.Id, todoItem });
}
[HttpPut("{id}")]
public async Task<IActionResult> Put(long id, TodoItem todoItem)
{
var request = HttpContext.Request;
if (todoItem.Id != id)
return BadRequest();
_context.Update(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(long id)
{
var request = HttpContext.Request;
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
}
}
在这个类中我们定义常用的api包含增删改查
2.HttpClient客户端
我们使用类型化方式声明HttpClient,在启动类中配置HttpClient
在Model文件夹下新增一个TodoClient类,在该类内部中使用构造函数中获取HttpClient,该类内部请求TodoItems api:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace AspNetCore.HttpClientWithHttpVerb.Models
{
public class TodoClient
{
private static readonly JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions
{
IgnoreNullValues = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
private readonly HttpClient _httpClient;
public TodoClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<IEnumerable<TodoItem>> GetItemsAsync()
{
using var httpReponse = await _httpClient.GetAsync("/api/TodoItems");
httpReponse.EnsureSuccessStatusCode();
var stream = await httpReponse.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync<List<TodoItem>>(stream, _jsonSerializerOptions);
}
public async Task<TodoItem> GetItemAsync(long id)
{
using var httpResponse = await _httpClient.GetAsync($"/api/TodoItems/{id}");
if (httpResponse.StatusCode == HttpStatusCode.NotFound)
return null;
httpResponse.EnsureSuccessStatusCode();
var stream = await httpResponse.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync<TodoItem>(stream, _jsonSerializerOptions);
}
public async Task CreateItemAsync(TodoItem todoItem)
{
var todoItemJson = new StringContent(
JsonSerializer.Serialize(todoItem, _jsonSerializerOptions),
System.Text.Encoding.UTF8,
"application/json");
using var httpResponse = await _httpClient.PostAsync("/api/TodoItems", todoItemJson);
httpResponse.EnsureSuccessStatusCode();
}
public async Task SaveItemAsync(TodoItem todoItem)
{
var todoItemJson = new StringContent(
JsonSerializer.Serialize(todoItem, _jsonSerializerOptions),
System.Text.Encoding.UTF8,
"application/json"
);
using var httpResponse = await _httpClient.PutAsync($"/api/TodoItems/{todoItem.Id}", todoItemJson);
httpResponse.EnsureSuccessStatusCode();
}
#region Delete Request
public async Task DeleteItemAsync(long id)
{
using var httpResponse = await _httpClient.DeleteAsync($"/api/TodoItems/{id}");
httpResponse.EnsureSuccessStatusCode();
}
#endregion
}
}
在HomeController中通过调用HttpClient来请求api,并将请求的结果传给视图呈现:
源代码地址:
https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/Fundamentals/AspNetCore.HttpRequest/AspNetCore.HttpClientWithHttpVerb
参考文献
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-8.0