aspnetcore:如何从中间件返回视图 [英] aspnetcore: how to return a view from middleware

查看:36
本文介绍了aspnetcore:如何从中间件返回视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 aspnetcore2.0 的中间件工作,我想在其中执行一些剃刀视图.
实际上我需要一个错误处理中间件,它可以从剃刀视图中显示漂亮的页面.我知道可以根据状态代码使用 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);返回 errorPage.ExecuteAsync(context);

如何在我的项目中实现?

解决方案

UPDATE [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放在这个文件夹里

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

3.在csprj中添加以下内容(因为dotnet add package不支持安装预发布包)

<PackageReference Include="RazorPageGenerator" Version="2.1.0-*"/><PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" 版本="2.1.0-*"/><PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="2.1.0-*"/></项目组>

4.restore dotnet restore 检查你是否有 RazorPageGenerator

5.加入Program.cs:

 public static int Main(string[] args){if (args == null || args.Length <1){Console.WriteLine("无效参数.");返回 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 结果 = RazorPageGenerator.Program.MainCore(razorEngine, targetProjectDirectory);foreach (var 结果在结果中){File.WriteAllText(result.FilePath, result.GeneratedCode);}Console.WriteLine();Console.WriteLine($"{results.Count} 个文件成功生成.");Console.WriteLine();返回0;}

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

7.创建 Razor 视图 (.cshtml)

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

dotnet run --project .MyRazorPageGeneratorMyRazorPageGenerator.csproj Croc.XFW3.Web .Middleware

这里我假设视图位于 MiddlewareViews 文件夹内.

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

 公共异步任务调用(HttpContext 上下文){尝试{等待_next.Invoke(上下文);if (context.Response.StatusCode == StatusCodes.Status404NotFound){var statusCodeFeature = context.Features.Get();if (statusCodeFeature == null || !statusCodeFeature.Enabled){如果 (!context.Response.HasStarted){var view = new ErrorPage(new ErrorPageModel());等待 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.

I'm working at a middleware for aspnetcore2.0 where I want to execute some razor view.
Actually I need a error handling middleware which would show nice pages from razor views. I know that it's possible to do with UseStatusCodePagesWithReExecute based on status codes. But I need a more general approach - handle an exception in my middleware to delegate (in some cases) it to an error view.

I realized that DeveloperExceptionPageMiddleware does something similar to what I need. But I can't understand how it works even after digging into its sources.

Here is the place where that middleware returns a view - https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs#L206

But I can't understand what kind of view it is. It's nor a razor page (as it has no @page directive) neither an mvc view (but i'm not sure).

In the project there're two files for that view: ErrorPage.cshtml and ErrorPage.Designer.cs. How that Designer.cs was created? It looks like a generated file. But thanks to it there's a normal class in the project (ErrorPage) which can be used explicitly. It inherits Microsoft.Extensions.RazorViews.BaseView class from Microsoft.Extensions.RazorViews.Sources package.

So the middleware just execute that view:

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

How can it be achieved in my project?

解决方案

UPDATE [2018.06]: Please note that the post was written for .NET Core 2.0 times, there're breaking changes for RazorEngine in .NET Core 2.1.

It turned out that it's pretty easy to do. Aspnet prjoect has an internal tool called RazorPageGenerator (see https://github.com/aspnet/Razor/tree/dev/src/RazorPageGenerator) which can be used to compile views. After compilation with this tool we'll get normal classes which can be used in middlewares.

But before we need to get RazorPageGenerator and slightly customize it.

1.Create a new console project

dotnet new console -o MyRazorGenerator

2.put NuGet.config inside this folder

<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.Add the following in csprj (as dotnet add package doesn't support installing pre-prelease packages)

<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 to check you got RazorPageGenerator

5.add into 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.Now we have our own generator and can compile views

7.Create a Razor View (.cshtml)

8.run our generator to compile view:

dotnet run --project .MyRazorPageGeneratorMyRazorPageGenerator.csproj Croc.XFW3.Web .Middleware

here I assume that the view is inside MiddlewareViews folder.

9.Generator creates a file like ErrorPage.Designer.cs (if view was ErrorPage.cshtml) which we can use:

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

Here we're returning our view in case of 404 error and absense of StatusCodePagesMiddleware. Can be useful for embedded UI in libs.

The generated code uses staff which should be added into your project. To get it we need to acquire nuget package Microsoft.Extensions.RazorViews.Sources. Again it’s not on nuget.org so we need to install it from https://dotnet.myget.org/feed/aspnetcore-dev/package/nuget/Microsoft.Extensions.RazorViews.Sources.

这篇关于aspnetcore:如何从中间件返回视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆