ASP.net Core 的RESTful应用

.tabset mean tabs.

在发布具有历史意义的.net 5.0的2H前,写下此博文。 windows msg1

  • PowerShell v5.1
  • IDE: VS Code/VS 2019
  • NuGet

..\AppData\Roaming\NuGet\NuGet.Config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>

Create Project

Choice vs2019 or vs code.

  • VS Code
  • VS 2019

VS2019

VS2019 pre1

add NuGet packages

Install-Package Microsoft.EntityFrameworkCore
Install-Package MySql.Data.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.Tools

vs code

dotnet new webapi -o MyWebApp --package Swashbuckle.AspNetCore:PackageVersion=6.2.3

add NuGet package

dotnet add package Microsoft.EntityFrameworkCore
dotnet add package MySql.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Tools

Test

Browser

Models

建立Entity类:Supplier、Product、Category

DbContext

public class StorageBuyDbContext : DbContext
{
    public StorageBuyDbContext(DbContextOptions<StorageBuyDbContext> options) : base(options){}

    public DbSet<Category> Categories { get; set; }
    public DbSet<Supplier> Suppliers { get; set; }
    public DbSet<Product> Products { get; set; }
}

add service

add connectiong string

"Data": {
  "StorageBuy": {
    "ConnectionString": "server=127.0.0.1; user id=DBAdmin; password=xbfirst; database=storagebuy; pooling=false; Convert Zero Datetime=True;"
  }
}

add mysql

services.AddDbContext<StorageBuyDbContext>(options =>
    options.UseMySQL(Configuration["Data:StorageBuy:ConnectionString"])
);

数据表

  • PM
  • Dotnet CLI

PM

生成db执行文件

PM> Add-Migration Initial

生成Table

PM> Update-Database

CLI

生成db执行文件

dotnet ef migrations add Initial

生成Table

dotnet ef database update

写入数据

seedData.cs

exec

Startup.cs

Configure方法中

SeedData.EnsurePopulated(app);

Part I 提取码: cn56

建立MCj

建立Controller

使用Scaffolder模板: VS2019 prj1

配置路由

  • class
[ApiController]
[Route("api/[controller]")]
  • method
    以Get举例:
[HttpGet]

处理Data

所有数据:

var result = _db.Products;

指定数据:

 var result = _db.Products.FindAsync(id);

配置Json

忽略空值

services.Configure<JsonOptions>(
    opts =>
    {
        opts.JsonSerializerOptions.IgnoreNullValues = true;
    }
);

Part II 提取码: 5deh

commit operator

指定操作方式(Table 3-1), 并指定源1(Table 3-2).
推荐使用PostMan来进行调试.

Table 3-1. HTTP Methods and Operations

HTTP Method Description
GET 从服务器获取数据
POST 向服务器提交新的Object
PUT 向服务器提交修改(整体)
DELETE 向服务器提交删除object.
PATCH 向服务器提交更新部分object.

Table 3-2. 源属性

Name Description
FromQuery Gets values from the query string.
FromRoute Gets values from route data.
FromForm Gets values from posted form fields.
FromBody Gets values from the request body.
FromHeader Gets values from HTTP headers.

POST/DELETE/PUT

  • 添加
_db.Products.AddAsync(product);
  • 移出
_db.Products.Remove(product);
  • 更新
_db.Update(product);

Patch

在客户端patch时的操作码见Table3-3

Table 3-3. httpPatch操作码

Operation Notes
add Add a property or array element. For existing property: set value.
remove Remove a property or array element.
replace Same as remove followed by add at same location.
move Same as remove from source followed by add to destination using value from source.
copy Same as add to destination using value from source.
test Return success status code if value at path = provided value.

PM

Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson --Version 5.0.11

CLI

dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson

config

Startup

services.AddControllers().AddNewtonsoftJson();

            services.Configure<MvcNewtonsoftJsonOptions>(opts => {
                opts.SerializerSettings.NullValueHandling
                = Newtonsoft.Json.NullValueHandling.Ignore;
            });

enjoin parameter

需要指定从哪里获取JSON, 普遍是FromBody,并用JsonPatchDocument解析JSON, 最后在方法里使用ApplyTo2

ModifyProduct(long id, [FromBody] JsonPatchDocument<Product> patchDoc)
patchDoc.ApplyTo(product);

Test Data

PowerShell

get

Invoke-WebRequest https://localhost:44309/api/products/1 | Select-Object Content

post

Invoke-RestMethod https://localhost:44309/api/products -Method POST -Body (@{ Name="Swimming Goggles";
Price=12.75; Category_id=1; Supplier_id=1} | ConvertTo-Json) -ContentType "application/json"
Invoke-RestMethod https://localhost:44309/api/products -Method POST -Body (@{ Name="Soccer Boots"; Price=89.99;
Category_id=2; Supplier_id=2} | ConvertTo-Json) -ContentType "application/json"
Invoke-RestMethod https://localhost:44309/api/products -Method POST -Body (@{ Name="Swim Buoy";
Price=19.99; Category_id=1; Supplier_id=1} | ConvertTo-Json) -ContentType "application/json"

update

Invoke-RestMethod https://localhost:44309/api/products -Method PUT -Body (@{ Id=1; Name="Green Kayak";
Price=275; Category_id=1; Supplier_id=1} | ConvertTo-Json) -ContentType "application/json"

delete

Invoke-RestMethod https://localhost:44309/api/products/13 -Method DELETE

status code

Invoke-WebRequest https://localhost:44309/api/products/100 |Select-Object StatusCode

patch

无法在PS中执行,只能在swaggerUI.

输入ID: 5; 并在Request body,更改为如下内容:

[
  {
    "path": "Price",
    "op": "replace",
    "value": "66800"
  }
]

Part III 提取码: v44x

Reference