哈囉大家好!
今天要練習如何用Controller來發送POST request~
這次練習用的API是{JSON Placeholder},
JSONPlaceholder提供免費的REST API, 提供模擬資料來測試GET, POST, PUT, PATCH DELETE等HTTP method。
根據官方文檔,其中有個endpoint -> https://jsonplaceholder.tyicode.com/posts 可以模擬使用者發佈一篇新貼文的情境,傳遞的body格式如下:
title: 'exampleTitle',
body: 'Hello World! This is my first post,
userId: 7
模擬使用者上傳貼文後返回的資料格式如下:
id: 101,
title: 'exampleTitle',
body: 'Hello World! This is my first post',
userId: 7
接下來把過程寫成實際的程式碼!
開始寫後端之前,先用Angular架一個簡單的前端頁面,讓我可以輸入貼文的標題和內容:
<h1>上傳貼文</h1>
<h4>標題</h4>
<input type="text" [(ngModel)]="title" />
<h4>內容</h4>
<input type="text" [(ngModel)]="body" />
<button (click)="createPost()">上傳貼文</button>
在ts檔中處理發送POST request的function:
createPost() {
const newPost = {
title: this.title,
body: this.body,
userId: 1, // 假設 userId 是 1
};
const endpoint = 'http://localhost:5232/post/updatePost';
this.http.post(endpoint, newPost).subscribe({
next: (response) => {
console.log(response);
},
error: (err) => {
console.log(err);
},
});
}
再來要處理後端~
在Client.cs檔中新增PostClient class, 並且定義回傳格式PostResponse class:
public class PostClient
{
public class PostResponse
{
public int? id { get; set; }
public string? title { get; set; }
public string? body { get; set; }
public int? userId { get; set; }
}
public static async Task<PostResponse?> CreatePostAsync(Post post)
{
using (HttpClient client = new HttpClient())
{
try
{
var jsonContent = JsonSerializer.Serialize(post);
var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://jsonplaceholder.typicode.com/posts", content);
response.EnsureSuccessStatusCode();
var jsonResponse = await response.Content.ReadAsStringAsync();
var postResponse = JsonSerializer.Deserialize<PostResponse>(jsonResponse);
return postResponse;
}
catch (HttpRequestException)
{
return null;
}
}
}
}
接著在Controllers資料夾中建立PostController.cs檔(撰寫格式和GET request大同小異):
using Microsoft.AspNetCore.Mvc;
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public int UserId { get; set; }
}
[ApiController]
[Route("[controller]")]
public class PostController : ControllerBase
{
[HttpPost("updatePost")]
public async Task<IActionResult> CreatePost([FromBody] Post post)
{
var response = await PostClient.CreatePostAsync(post);
if (response is not null)
{
return CreatedAtAction(nameof(CreatePost), new { id = response.id }, response);
}
return null;
}
}
這裡比較特別的是,因為Angular的來源是http://localhost:4200, 後端API的來源是http://localhost:5235, 瀏覽器的同源政策下會讓程式碼報錯。所以要在後端開放CORS(跨來源資源共享):
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("Frontend", // 指定名稱為Frontend
policy =>
{
policy.WithOrigins("http://localhost:4200") // 帶入Angular來源
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseCors("Frontend");
app.MapControllers();
app.Run();
在前端填入測試內容,按下上傳按鈕後,打開瀏覽器dev tool,就可以看到後端回傳的資料了!
目前對於基本的API操作有了一些認識,明天要來看看什麼是「資料傳輸物件(DTO)」~