最近都把專案升級成 .Net 6 ,沒啥大問題,只是最近想找個機會好好研究一下 Web API,想說遇到或是測試到就筆記一下,所以也不是啥教學文
如果有啥更好得做法,可以在跟我說,這邊沒有啥難度的技術,可能對很多高手來說就是喝水一樣的事情。

這次案例設計很簡單就是一個 <form> 我直接 POST 到 Web API (案例中為 TestController) 上面
介紹一下 <form> 的結構
<form action="/api/test/sample2" method="post">
<div style="margin-bottom:20px">
<legend>用戶帳號</legend><br />
<input class="input" type="text" placeholder="donma" name="userId">
</div>
<fieldset>
<legend>選擇你的興趣:</legend>
<div>
<input type="checkbox" name="hobby" checked value="釣魚">
<label>釣魚</label>
</div>
<div>
<input type="checkbox" name="hobby" checked value="睡覺">
<label>睡覺</label>
</div>
<div>
<input type="checkbox" name="hobby" value="看電影">
<label>看電影</label>
</div>
<div>
<input type="checkbox" name="hobby" value="上網">
<label>上網</label>
</div>
</fieldset>
<div>
<legend for="gender">性別</legend><br>
<select name="gender">
<option value="0">Female</option>
<option value="1">Male</option>
</select>
</div>
<div>
<legend for="">生日</legend><br>
<input class="input" type="date" placeholder="2022-10-11" value="2022-10-11" name="userBirth">
</div>
<div>
<legend for="">薪水</legend><br>
<input class="input" type="number" value="199.99" name="userSalary">
</div>
<hr />
<div>
<input type="submit" value="送出">
</div>
</form>
出來長相大概長這樣,如果你看 code 無法想像的話

接下來就是 首先在 .Net 6 中,你得先在 Program.cs 加入 app.MapControllers(); 這一步我常常忘記

Web API Code Sample2 :
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Dynamic;
namespace TestWebAPI1.API
{
[Route("api/test")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet]
public string Get()
{
return "Test Service";
}
[HttpPost]
[Route("sample2")]
public IActionResult RegistUserActionResult([FromForm] string userId,
[FromForm] string gender,
[FromForm] string[] hobby,
[FromForm] DateTimeOffset userBirth,
[FromForm] decimal? userSalary)
{
dynamic res = new ExpandoObject();
res.UserId = userId;
res.Gender = gender;
res.Hobby = hobby;
res.Birth = userBirth;
res.Salary = userSalary;
return Ok(res);
}
}
}
這案例很簡單回傳就是 IActionResult ,其實回傳他預設就會是 ontent-type: application/json; charset=utf-8
回應結果
{"UserId":"許當麻","Gender":"0","Hobby":["釣魚","睡覺"],"Birth":"2022-10-11T00:00:00+08:00","Salary":199.99}
看一下回應的 headers
這裡面值得一提的就是,input 如果 type 是 number ,WebAPI 這邊是可以用 decimal 承接,如果是 input:checkbox 同一個 name ,則可以使用
string[] 接 (如文中的 hobby)
這其實非常方便,當然一般狀況通常都是在前端準備好物件(一個 自訂好結構的 json
) 在一次往後送,不過這是測試,我也非常偷懶的直接用 dynamic 接了就拋
再來測試 XML 輸出,因為輸出 dynamic 比較麻煩所以我建立了一個物件 User.cs
public class User
{
public string Id { get; set; }
public string Name { get; set; }
public string[]? Hobby { get; set; }
public string Gender { get; set; }
public decimal? Salary { get; set; }
public DateTimeOffset Birth { get; set; }
}
Web API Code Sample3 :
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Dynamic;
namespace TestWebAPI1.API
{
[Route("api/test")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet]
public string Get()
{
return "Test Service";
}
[HttpPost]
[Route("sample3")]
//輸出為 XML
[Produces("application/xml")]
public IActionResult RegistUserJson([FromForm] string userId,
[FromForm] string gender,
[FromForm] string[] hobby,
[FromForm] DateTimeOffset userBirth,
[FromForm] decimal? userSalary)
{
var u = new Models.User();
u.Name = userId;
u.Id = userId;
u.Gender = gender;
u.Birth = userBirth;
u.Hobby = hobby;
u.Salary = userSalary;
return Ok(u);
}
}
}
注意,需要再 Program.cs 中 var app = builder.Build(); 之前加入
builder.Services.AddControllers().AddXmlSerializerFormatters().AddXmlDataContractSerializerFormatters();
當然 form 那邊的 action 也要改成 action="/api/test/sample3"
回應結果:
<?xml version="1.0" encoding="UTF-8"?>
<User xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<script />
<Id>許當麻</Id>
<Name>許當麻</Name>
<Hobby>
<string>釣魚</string>
<string>睡覺</string>
</Hobby>
<Gender>0</Gender>
<Salary>199.99</Salary>
<Birth>2022-10-11T00:00:00+08:00</Birth>
</User>
回應的 headers

注意: 如果你的 Web API 部分有些是允許 null 或是空值傳入 ,但是你傳入到 Web API 會出現
{
"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title":"One or more validation errors occurred.",
"status":400,
"traceId":"00-c483917b91ff3410d2305af939c2ac3e-60280f3f85d80a58-00",
"errors":{
"userId":[
"The userId field is required."
]
}
需要再 Program.cs 中 修改這一段
//for not check required
builder.Services.AddControllers(options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);
需要再 AddControllers 中加入 options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true
大概筆記到這裡,不算教學,算是給自己的筆記