在 .net 核心应用程序启动中结合使用 MapWhen 和 ApplicationBuilder?

Using a combination of MapWhen and ApplicationBuilder in .net core app startup?

是否可以部分分支启动?

举个例子,是否可以这样:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.AlwaysUseThisMiddleware();
    app.MapWhen(conditionA, appBuilder => {appBuilder.SometimesUseThisOne;})
    app.MapWhen(conditionB, appBuilder => {appBuilder.SometimesUseThisOtherOne;})

或者我需要把 AlwaysUseThisMiddleware 放在每个分支中吗?像这样:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.MapWhen(conditionA, appBuilder =>
    {
        appBuilder.AlwaysUseThisMiddleware(); // Duplicated
        appBuilder.SometimesUseThisOne;
    )
    app.MapWhen(conditionB, appBuilder =>
    {
        appBuilder.AlwaysUseThisMiddleware(); // Duplicated
        appBuilder.SometimesUseThisOtherOne;
    )

简答

是的。它将按您的预期工作。


其实我们在Use()一系列中间件的时候,就是在注册一系列的中间件,处理请求的时候会依次调用这些中间件。

MapWhen() 方法只不过是辅助方法 that invokes the Use(). What MapWhen(predicate,configFn) does is to registering something that runs as below :

if (predicate(context)){
    await branch(context);
} else {
    await _next(context);
}

因此,当我们调用 MapWhen() 时,我们正在注册另一个分支处理的中间件。

例如:

app.UseMiddleware<AlwaysUseThisMiddleware>();                

app.MapWhen(ctx=>ctx.Request.Query["a"]=="1", appBuilder =>{
    appBuilder.UseMiddleware<SometimesUseThisOne>();
});

app.MapWhen(ctx=>ctx.Request.Query["b"]=="1", appBuilder =>{
    appBuilder.UseMiddleware<SometimesUseThisOtherOne>();
})

// ...

基本上,此代码按以下方式运行:

call  `AlwaysUseThisMiddleware`;

////////////////////////////////////
if (ctx.Request.Query["a"]=="1"){   
    call SometimesUseThisOne ;            
} else {
    //------------------------------------------
    if (ctx.Request.Query["b"]=="1"){
        call SometimesUseThisOtherOne ;
    } else {
        //##################################################
        await _next(context);  // call other middlewares ...
        //##################################################
    }
    //-----------------------------------------
}
////////////////////////////////////

或者如果你喜欢也可以重写如下:

call `AlwaysUseThisMiddleware` middleware

if(ctx.Request.Query["a"]=="1")           // go to branch 1
    call `SometimesUseThisOne` middleware

else if (ctx.Request.Query["b"]=="1")     // go to branch 2
    call `SometimesUseThisOtherOne` middleware 

else :
    ...

注意这里的分支被翻译成 else if 而不是 if。并且中间件 AlwaysUseThisMiddleware 总是在 branch1 & branch2 之前被调用。