英文:
Why is app.Run() middleware overriding a specific route mapping in ASP.NET Core?
问题
- 我使用 app.Map() 创建了一个处理特定路由(/hello)的中间件。
- 但是,当我使用 app.Run() 添加第二个中间件时,它不检查特定路由。
- 即使对/hello路由发出请求,似乎也会覆盖第一个中间件的响应。
我对为什么会发生这种情况以及如何修复它感到困惑。
以下是代码:
using Microsoft.Extensions.Primitives;
using System.Web;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/hello", async (HttpContext context) => {
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Hello");
});
app.Run(async (HttpContext context) => {
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Bye");
});
app.Run();
我尝试删除 app.Run() 中间件,然后指定的'/hello' 中间件会执行。
但只要我再次添加 app.Run() 中间件,它就会跳过映射到'/hello'的中间件。
英文:
- I have created a middleware using app.Map() that handles a specific route (/hello).
- However, when I add a second middleware using app.Run() that does not check for a specific route.
- It seems to overwrite the response of the first middleware even when a request is made to the /hello route.
I'm confused about why this is happening and how to fix it.
The code is below:
using Microsoft.Extensions.Primitives;
using System.Web;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/hello", async (HttpContext context) => {
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Hello");
});
app.Run(async (HttpContext context) => {
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Bye");
});
app.Run();
I tried removing the app.Run() middleware then the specified '/hello' middleware is executing.
But as soon as I add the app.Run() middleware again it then skips the middleware that is mapped to '/hello';
答案1
得分: 2
Here is the translated code part:
尝试切换到Use
:
app.Use(async (HttpContext context, Func<Task> next) =>
{
await next();
if (!context.Response.HasStarted)
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Bye");
}
});
app.Map("/hello", async (HttpContext context) =>
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Hello");
});
app.Run();
我猜这种行为是因为RunExtensions.Run
添加了所谓的"终端中间件委托"。
另外,ASP.NET Core中间件文章可能会有用。
英文:
Try switching to Use
:
app.Use(async (HttpContext context, Func<Task> next) =>
{
await next();
if (!context.Response.HasStarted)
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Bye");
}
});
app.Map("/hello", async (HttpContext context) => {
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Hello");
});
app.Run();
I guess that the behaviour is due to the fact that the RunExtensions.Run
adds something called "terminal middleware delegate".
Also ASP.NET Core Middleware article can be useful.
答案2
得分: 2
以下是您要翻译的内容:
您可以在此处查看RunExtensions.Run()
方法的源代码。
public static class RunExtensions
{
/// <summary>
/// 向应用程序的请求管道添加终端中间件委托。
/// </summary>
/// <param name="app">IApplicationBuilder 实例。</param>
/// <param name="handler">处理请求的委托。</param>
public static void Run(this IApplicationBuilder app, RequestDelegate handler)
{
ArgumentNullException.ThrowIfNull(app);
ArgumentNullException.ThrowIfNull(handler);
app.Use(_ => handler);
}
}
它添加了一个类似的中间件:
app.Use(next => async (HttpContext context) =>
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Bye");
});
如果您不分支管道,您的请求将被快速处理。
您可以尝试使用 Guru Stron 的解决方案或:
app.MapFallback(async (HttpContext context) =>
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Bye");
});
或者分支管道:
app.Map("/hello", app => app.Run(async (HttpContext context) =>
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Hello");
}));
根据您的需求,您可以检查差异:
英文:
You could check the source codes of RunExtensions.Run()
method here
public static class RunExtensions
{
/// <summary>
/// Adds a terminal middleware delegate to the application's request pipeline.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> instance.</param>
/// <param name="handler">A delegate that handles the request.</param>
public static void Run(this IApplicationBuilder app, RequestDelegate handler)
{
ArgumentNullException.ThrowIfNull(app);
ArgumentNullException.ThrowIfNull(handler);
app.Use(_ => handler);
}
}
it adds a middleware like
app.Use(next => async (HttpContext context) =>
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Bye");
});
if you don't branch the pipeline ,your request would be shortcut
You could try with Guru Stron's solution or
app.MapFallback(async (HttpContext context) =>
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Bye");
});
Or branch the pipeline:
app.Map("/hello",app=>app.Run(async (HttpContext context) =>
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Hello");
}));
For your requirement
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论