抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

ASP.Net最小Web API

最近需要搭建一个Windows Web服务器,处理一些很简单的访问请求,于是研究了一下ASP.Net的最小Web API

项目创建

打开VS2022,按照ASP.Net模块后,使用模板创建项目

ASP模板

ASP模板参数

程序运行

模板是一个预测(随机生成)未来五天天气的demo,可以用命令行启动程序

dotnet run --project=./项目名称

Mini API

模板项目内容非常少,只有一个C#文件

ASP模板内容

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

// 创建一个Get接口,返回天气预测结果
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
...
))
.ToArray();
return forecast;
});

app.Run();

// record是C#的一个关键字,可以定义一个不可变的数据类型
internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}


record可以用于快速定义一个类

// 两者等效
record EditTodoItemRequest(int Id, TodoItemDTO Dto, TodoDb Db);

class EditTodoItemRequest
{
public int Id { get; set; }
public TodoItemDTO Dto { get; set; } = default!;
public TodoDb Db { get; set; } = default!;
}

添加一个新Get

app.MapGet("/open/{path}", (string path) =>
{
try
{
Process.Start("explorer.exe", path);
}
catch (Exception ex)
{
Console.WriteLine($"Can't open folder: {ex.Message}");
}
});
http://localhost:xxxx/open/C%3A%5CUsers%5C28240%5Ccode

用文件浏览器打开本地的C:\Users\28240\code路径

解析Request内容

app.MapGet("/do", (HttpRequest request) =>
{
var prop_a = request.Query["a"];
var prop_b = request.Query["b"];
var sessionid = request.Query["sessionid"];
});
http://localhost:xxxx/do?a=hello&b=world&sessionid=default

输入一个文件

app.MapPost("/do", (HttpRequest request) =>
{
var sourceFile = request.Form.Files[0];
// 将 http 请求的文件保存在本地
using (var st = new FileStream(localPath, FileMode.Create))
{
sourceFile.CopyTo(st);
}
...
});

返回一个文件

app.MapPost("/download", (HttpRequest request) =>
{
return Results.File(System.IO.File.OpenRead(localVideoPath), "video/mp4");
});

用python下载这个文件

response = requests.post(url, headers=headers, files={"file": file})
if response.status_code == 200:
print("Request successful!")
with open('received_file.mp4', 'wb') as f:
f.write(response.content)
print("文件已保存为 'received_file.mp4'")
else:
print("Request failed with status code:", response.status_code)

url转义规则

除了下面这些保留字外,用%{两位十六进制}进行转义

字符 转义形式
空格 %20
! %21
* %2A
%27
( %28
) %29
; %3B
: %3A
@ %40
& %26
= %3D
+ %2B
$ %24
, %2C
/ %2F
? %3F
# %23
[ %5B
] %5D

Web Socket

除了简单的Web API,我们有时也会用到Web Socket

服务端代码

// Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

var webSocketOptions = new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromMinutes(2)
};

app.UseWebSockets(webSocketOptions);

app.MapControllers();

app.Run();
namespace SocketDemo.Controllers
{
public class xxxxController : ControllerBase
{
[Route("/ws")]
public async Task Get()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}

private static async Task Echo(WebSocket webSocket)
{
Console.WriteLine("First Connect");
var buffer = new byte[1024 * 4];
var receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);

while (!receiveResult.CloseStatus.HasValue)
{
var segment = new ArraySegment<byte>(buffer, 0, receiveResult.Count);
await webSocket.SendAsync(
segment,
receiveResult.MessageType,
receiveResult.EndOfMessage,
CancellationToken.None);
Console.WriteLine($"Send: {Encoding.UTF8.GetString(segment.Array, segment.Offset, segment.Count)}");

receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
}

await webSocket.CloseAsync(
receiveResult.CloseStatus.Value,
receiveResult.CloseStatusDescription,
CancellationToken.None);
}
}
}

客户端代码

import asyncio
import websockets

async def connect_to_server():
uri = "wss://localhost:7167/ws" # 替换成你的服务器地址

async with websockets.connect(uri) as websocket:
print(f"Connected to {uri}")

try:
while True:
message = input("Enter message to send (or 'exit' to quit): ")

if message.lower() == "exit":
break

await websocket.send(message)
print(f"> Sent: {message}")

response = await websocket.recv()
print(f"< Received: {response}")

finally:
await websocket.close()
print("WebSocket connection closed")

asyncio.run(connect_to_server())

注:客户端连接websocket时,不使用http、https,而是ws、wss

评论