【问题标题】:aspnetcore: how to return a view from middlewareaspnetcore:如何从中间件返回视图
【发布时间】:2018-03-28 09:44:15
【问题描述】:

我正在研究 aspnetcore2.0 的中间件,我想在其中执行一些 razor 视图。
实际上,我需要一个错误处理中间件,它可以从剃刀视图中显示漂亮的页面。我知道可以根据状态代码使用UseStatusCodePagesWithReExecute。但我需要一种更通用的方法 - 在我的中间件中处理异常以将其(在某些情况下)委托给错误视图。

我意识到DeveloperExceptionPageMiddleware 做了一些我需要的事情。但是即使在挖掘其来源之后,我也无法理解它是如何工作的。

这里是中间件返回视图的地方 - https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs#L206

但我不明白这是一种什么样的看法。它也不是 razor 页面(因为它没有 @page 指令)也不是 mvc 视图(但我不确定)。

在项目中,该视图有两个文件:ErrorPage.cshtmlErrorPage.Designer.cs。 Designer.cs 是如何创建的?它看起来像一个生成的文件。但多亏了它,项目中有一个普通类(ErrorPage),可以显式使用。它从Microsoft.Extensions.RazorViews.Sources 包继承Microsoft.Extensions.RazorViews.BaseView 类。

所以中间件只是执行那个视图:

var errorPage = new ErrorPage(model);
return errorPage.ExecuteAsync(context);

如何在我的项目中实现?

【问题讨论】:

  • 必须是中间件吗?操作或结果过滤器也可以这样做docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters
  • @Tseng 主要是因为它更健壮(中间件可以是管道中的第一个)并且由于需要处理像 404 这样的错误(它们不是异常,所以 mvc 过滤器会忽略它们)

标签: razor asp.net-core .net-core asp.net-core-2.0


【解决方案1】:

更新 [2018.06]:请注意,该帖子是为 .NET Core 2.0 编写的,在 .NET Core 2.1 中对 RazorEngine 进行了重大更改。

事实证明,这很容易做到。 Aspnet prjoect 有一个名为RazorPageGenerator(参见https://github.com/aspnet/Razor/tree/dev/src/RazorPageGenerator)的内部工具,可用于编译视图。使用此工具编译后,我们将得到可以在中间件中使用的普通类。

但在我们需要获取 RazorPageGenerator 并稍微自定义它之前。

1.新建一个控制台项目

dotnet new console -o MyRazorGenerator

2.把NuGet.config放到这个文件夹里

<configuration>
  <config>
    <add key="globalPackagesFolder" value="./packages" />
  </config>
  <packageSources>
    <add key="aspnetcore-dev" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json " />
  </packageSources>
</configuration>

3.在csprj中添加以下内容(dotnet add package不支持安装pre-prelease包)

<ItemGroup>
  <PackageReference Include="RazorPageGenerator" Version="2.1.0-*" />
  <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="2.1.0-*" />
  <PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="2.1.0-*" />
</ItemGroup>

4.restore dotnet restore 以检查您是否获得了 RazorPageGenerator

5.添加到Program.cs:

    public static int Main(string[] args)
    {
        if (args == null || args.Length < 1)
        {
            Console.WriteLine("Invalid argument(s).");
            return 1;
        }

        var rootNamespace = args[0];
        var targetProjectDirectory = args.Length > 1 ? args[1] : Directory.GetCurrentDirectory();

        var razorEngine = RazorPageGenerator.Program.CreateRazorEngine(rootNamespace, builder => {
            FunctionsDirective.Register(builder);
            InheritsDirective.Register(builder);
            SectionDirective.Register(builder);
        });
        var results = RazorPageGenerator.Program.MainCore(razorEngine, targetProjectDirectory);

        foreach (var result in results)
        {
            File.WriteAllText(result.FilePath, result.GeneratedCode);
        }

        Console.WriteLine();
        Console.WriteLine($"{results.Count} files successfully generated.");
        Console.WriteLine();
        return 0;
    }

6.现在我们有了自己的生成器,可以编译视图了

7.创建 Razor 视图 (.cshtml)

8.运行我们的生成器来编译视图:

dotnet run --project .\MyRazorPageGenerator\MyRazorPageGenerator.csproj Croc.XFW3.Web .\Middleware

这里我假设视图位于Middleware\Views 文件夹内。

9.Generator 创建一个类似 ErrorPage.Designer.cs 的文件(如果视图是 ErrorPage.cshtml),我们可以使用它:

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next.Invoke(context);
            if (context.Response.StatusCode == StatusCodes.Status404NotFound)
            {
                var statusCodeFeature  = context.Features.Get<IStatusCodePagesFeature>();
                if (statusCodeFeature == null || !statusCodeFeature.Enabled)
                {
                    if (!context.Response.HasStarted)
                    {
                        var view = new ErrorPage(new ErrorPageModel());
                        await view.ExecuteAsync(context);
                    }
                }
            }
        }
    }

在出现 404 错误和缺少 StatusCodePagesMiddleware 的情况下,我们将返回视图。可用于库中的嵌入式 UI。

生成的代码使用人员,应将其添加到您的项目中。要获得它,我们需要获取 nuget 包 Microsoft.Extensions.RazorViews.Sources。同样它不在 nuget.org 上,所以我们需要从 https://dotnet.myget.org/feed/aspnetcore-dev/package/nuget/Microsoft.Extensions.RazorViews.Sources 安装它。

【讨论】:

  • 另见我的帖子:techblog.dorogin.com/…
  • 当您有 @model 指令时,这似乎不起作用。它将其视为文字。我们如何解决这个问题?
  • 我认为你需要在 CreateRazorEngine 的回调中注册一个额外的指令。我猜是ModelDirective (github.com/aspnet/Razor/blob/dev/src/…)
  • 是的,谢谢。我能够做到这一点。 :)
  • 这个我没看懂,我从来没有在asp.net核心项目中看到过nuget.config文件,而且Program.cs没有任何BuildWebHost()方法。你的观点在哪里?我不能使用我的传统观点吗?您有任何官方参考资料供您指导吗?
猜你喜欢
  • 2022-08-16
  • 2017-06-04
  • 2018-03-20
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多