app.Run() 中间件为什么会覆盖 ASP.NET Core 中特定路由映射?

huangapple go评论73阅读模式
英文:

Why is app.Run() middleware overriding a specific route mapping in ASP.NET Core?

问题

  1. 我使用 app.Map() 创建了一个处理特定路由(/hello)的中间件。
  2. 但是,当我使用 app.Run() 添加第二个中间件时,它不检查特定路由。
  3. 即使对/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'的中间件。

英文:
  1. I have created a middleware using app.Map() that handles a specific route (/hello).
  2. However, when I add a second middleware using app.Run() that does not check for a specific route.
  3. 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&lt;Task&gt; next) =&gt;
{
    await next();

    if (!context.Response.HasStarted)
    {
        context.Response.ContentType = &quot;text/html&quot;;

        await context.Response.WriteAsync(&quot;Bye&quot;);
    }
});
app.Map(&quot;/hello&quot;, async (HttpContext context) =&gt; {
    context.Response.ContentType = &quot;text/html&quot;;

    await context.Response.WriteAsync(&quot;Hello&quot;);
});

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");
}));

根据您的需求,您可以检查差异:

app.Run() 中间件为什么会覆盖 ASP.NET Core 中特定路由映射?
app.Run() 中间件为什么会覆盖 ASP.NET Core 中特定路由映射?

英文:

You could check the source codes of RunExtensions.Run() method here

public static class RunExtensions
{
    /// &lt;summary&gt;
    /// Adds a terminal middleware delegate to the application&#39;s request pipeline.
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;app&quot;&gt;The &lt;see cref=&quot;IApplicationBuilder&quot;/&gt; instance.&lt;/param&gt;
    /// &lt;param name=&quot;handler&quot;&gt;A delegate that handles the request.&lt;/param&gt;
    public static void Run(this IApplicationBuilder app, RequestDelegate handler)
    {
        ArgumentNullException.ThrowIfNull(app);
        ArgumentNullException.ThrowIfNull(handler);

        app.Use(_ =&gt; handler);
    }
}

it adds a middleware like

app.Use(next =&gt; async (HttpContext context) =&gt;
{
    context.Response.ContentType = &quot;text/html&quot;;

    await context.Response.WriteAsync(&quot;Bye&quot;);

});

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) =&gt;
{
    context.Response.ContentType = &quot;text/html&quot;;

    await context.Response.WriteAsync(&quot;Bye&quot;);
});

Or branch the pipeline:

app.Map(&quot;/hello&quot;,app=&gt;app.Run(async (HttpContext context) =&gt;
{

    context.Response.ContentType = &quot;text/html&quot;;

    await context.Response.WriteAsync(&quot;Hello&quot;);
}));

For your requirement

You could check the difference:
app.Run() 中间件为什么会覆盖 ASP.NET Core 中特定路由映射?
app.Run() 中间件为什么会覆盖 ASP.NET Core 中特定路由映射?

huangapple
  • 本文由 发表于 2023年5月11日 19:24:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76227091.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定