.NET 7 和 .NET 6 都支持 Minimal API,但是它们之间还是存在一些区别:
- 支持的平台:
.NET 7引入了对Apple Silicon和Windows ARM64的原生支持,这使得.NET 7的Minimal API可以在更广泛的平台上运行。而.NET 6只支持在Windows、macOS 和 Linux上运行。 - 语法特性:
.NET 7的Minimal API支持一些新的语法特性,比如top-level statements,这使得编写Minimal API更加简洁。而.NET 6的Minimal API不支持这些新特性。 Web API支持:.NET 7的Minimal API支持Web API的构建,而.NET 6的Minimal API主要是用来构建命令行应用程序或单独的HTTP端点。- 性能:
.NET 7中的Minimal API在某些情况下比.NET 6更快,这主要得益于其采用了一些新的优化和性能改进。不过具体的性能优化效果还需要在具体场景中测试才能得出结论。
总之,虽然 .NET 6 和 .NET 7 都支持 Minimal API,但它们在支持平台、语法特性、Web API 支持和性能方面都存在一些差异。开发者可以根据自己的需求和具体场景选择适合的版本来使用。
随着.Net 7发布,我们也来探索一下.Net 7。 随着.Net 7发布的同时,C# 10.0也会随之发布,在C# 10.0中为了.Net 6的发布,语言级别集成了很多新特性, 这些特性主要有:
- Top-level statements
- async main
- Global using directives ( 基于SDK的隐式
global using) - File-scoped名称空间
- new表达式类型推断
- 空引用类型
有了这些新特性之后, .Net 6推出了Minimal API, 那么到底什么Minimal API? 为了更快速的直观的观察他们,我们先安装.Net 6的sdk, 您可以微软的网站:dotnet.microsoft.com/download/do… 来下载和安装.Net 6, 安装完成之后我们可以继续观察了。
1. Minimal API初体验
相比原来的模板生成的项目,这里的文件是相当的少:
appsettings.json appsetttings.Developments.json Program.cs
我们可以进一步的看一下Program.cs的内容:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", async (context) => await context.Response.WriteAsync("hello"));
app.Run();
在 .NET 7 中,应该使用HttpContext对象的Response属性来创建响应。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () =>
{
var response = app.Context.Response;
response.ContentType = "text/plain";
return response.WriteAsync("hello");
});
app.Run();
在此代码中,我们使用 app.Context.Response 来获取 HttpContext 对象的 Response 属性,并将响应类型设置为 "text/plain"。然后,我们使用 response.WriteAsync() 方法将字符串 "hello" 写入响应体中。
请注意,在这个代码中我们使用了 async 和 await 关键字,这是因为在写入响应体时需要进行异步操作。这是一种更好的编程风格,因为它允许 Web 服务器同时处理多个请求。
关于这部分代码,我们可以看到有如下的特征:
- 应用了新的特性:
top-level statement - .Net 6 应用了新的特性:
隐式global using。 - 没有了
Startup类了。 - 应用了新的类
WebApplication - 应用了新的类
WebApplicationBuilder
对比较我们之前的应用模板,除了主要的新特性支持,最重要的要是WebApplication类和WebApplicationBuilder类的应用,除此之外,路由部分也和之间有所有不同,之前我们是先启用路由中间件,然后使用useEndpoint扩展方法进行映射,但是现在可以直接app.MapGet()等一系列的方法。同时可以看到我们通过WebAplicationBuilder来添加我们需要的服务,通过WebApplication的实例来启用中间件,构建管道。
除了使用模板之外,我们还是更快速的使用更小的代码来构建我们的mini应用,下面我们看看路由的用法:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World");
app.Run();
想监听更多的HTTP动作?
app.MapGet("/", () => "This is a GET");
app.MapPost("/", () => "This is a POST");
app.MapPut("/", () => "This is a PUT");
app.MapDelete("/", () => "This is a DELETE");
app.MapMethods("/options-or-head", new [] { "OPTIONS", "HEAD" },
() => "This is an options or head request ");
app.MapGet("/", () => "This is an inline lambda");
var handler = () => "This is a lambda variable";
app.MapGet("/", handler)
当然你可以使用任何你想使用的类型,例如:
var handler = new HelloHandler();
app.MapGet("/", handler.Hello);
class HelloHandler
{
public string Hello()
{
return "Hello World";
}
}
你还可以处理更多的路由参数:
app.MapGet("/users/{userId}/books/{bookId}",
(int userId, int bookId) => $"The user id is {userId} and book id is {bookId}");
路由约束在这里还是可以继续使用:
app.MapGet("/todos/{id:int}", (int id) => db.Todos.Find(id));
app.MapGet("/todos/{text}", (string text) => db.Todos.Where(t => t.Text.Contains(text));
app.MapGet("/posts/{slug:regex(^[a-z0-9_-]+$)}", (string slug) => $"Post {slug}");
同时Attributes可以明确的定义参数:
using Microsoft.AspNetCore.Mvc;
app.MapGet("/{id}", ([FromRoute]int id,
[FromQuery(Name = "p")]int page,
[FromServices]Service service,
[FromHeader(Name = "Content-Type")]string contentType) => { });
自定义response:
app.MapGet("/todos/{id}", (int id, TodoDb db) =>
db.Todos.Find(id) is Todo todo
? Results.Ok(todo)
: Results.NotFound()
);
看一个完整的文件上传的例子:
app.MapGet("/upload", async (HttpRequest req) =>
{
if (!req.HasFormContentType)
{
return Results.BadRequest();
}
var form = await req.ReadFormAsync();
var file = form.Files["file"];
if (file is null)
{
return Results.BadRequest();
}
var uploads = Path.Combine(uploadsPath, file.FileName);
await using var fileStream = File.OpenWrite(uploads);
await using var uploadStream = file.OpenReadStream();
await uploadStream.CopyToAsync(fileStream);
return Results.NoContent();
})
.Accepts<IFormFile>("multipart/form-data");
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using System.IO;
using System.Threading.Tasks;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.MapPost("/upload", async (HttpContext context) =>
{
// 检查是否有文件上传
if (context.Request.Form.Files.Count == 0)
{
return Results.BadRequest("No files were uploaded.");
}
// 处理每个上传的文件
foreach (var file in context.Request.Form.Files)
{
// 检查文件大小是否符合要求,例如不能大于 10MB
if (file.Length > 10 * 1024 * 1024)
{
return Results.BadRequest($"The file {file.FileName} is too large.");
}
// 保存文件到磁盘
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "uploads", file.FileName);
await using var stream = new FileStream(filePath, FileMode.Create);
await file.CopyToAsync(stream);
}
return Results.Ok("Files uploaded successfully.");
});
app.Run();
那么在 .NET 7 中,创建一个新的 ASP.NET Core Web 应用程序需要使用以下命令:
dotnet new web -n FileUpload
接下来,进入项目目录,并使用以下命令添加一个文件上传控制器:
cd FileUpload
dotnet add package Microsoft.AspNetCore.Http
dotnet add package Microsoft.AspNetCore.Http.Features
在 Controllers 文件夹下创建一个名为 UploadController.cs 的控制器,并添加以下代码:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;
namespace FileUpload.Controllers
{
[ApiController]
[Route("[controller]")]
public class UploadController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
if (file == null || file.Length == 0)
{
return BadRequest("No file uploaded.");
}
var filePath = Path.GetTempFileName();
using (var stream = System.IO.File.Create(filePath))
{
await file.CopyToAsync(stream);
}
return Ok($"File uploaded successfully. Stored in {filePath}");
}
}
}
在此代码中,我们创建了一个名为UploadController的控制器,并添加了一个名为 Upload的动作。此动作将接受一个 IFormFile对象,该对象将包含要上传的文件的数据。如果未选择文件或所选文件大小为零,则该动作将返回一个 BadRequest响应。否则,该动作将创建一个唯一的临时文件名,并将上传的文件保存到该文件中。最后,该动作将返回一个 Ok响应,指示文件已成功上传并保存在临时文件中。
接下来,在 Startup.cs 文件中添加以下代码,以允许文件上传:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace FileUpload
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddHttpContextAccessor();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
在此代码中,我们使用 AddControllers 方法将 MVC 控制器添加到应用程序中,并使用 AddHttpContextAccessor方法添加 IHttpContextAccessor 服务以访问 HTTP 请求和响应。最后,我们在 Configure 方法中添加了必要的中间件和路由规则,以便启用 MVC 控制器并允许文件上传。
最后,您可以使用 dotnet run 命令运行应用程序,然后使用您选择的工具(如 Postman 或 cURL)向 https://localhost:5001/upload 发送 POST 请求,其中包含要上传的文件。应用程序将返回一个包含临时文件路径的 JSON 响应。