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

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

问题描述

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

我意识到 DeveloperExceptionPageMiddleware 所做的事情与我需要的类似.但是即使深入研究其来源,我也无法理解它的工作原理.

这是中间件返回视图的地方-解决方案

更新[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新控制台-o MyRazorGenerator 

2.将NuGet.config放入此文件夹

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

3.在csprj中添加以下内容(因为 dotnet add package 不支持安装预发行版本的软件包)

 < 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 :

 公共静态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.创建剃刀视图(.cshtml)

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

  dotnet运行--project.\ MyRazorPageGenerator \ MyRazorPageGenerator.csproj Croc.XFW3.Web.\ Middleware 

在这里,我假设视图位于 Middleware \ Views 文件夹中.

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

 公共异步任务调用(HttpContext上下文){尝试{等待_next.Invoke(context);如果(context.Response.StatusCode == StatusCodes.Status404NotFound){var statusCodeFeature = context.Features.Get< IStatusCodePagesFeature>();如果(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 .\MyRazorPageGenerator\MyRazorPageGenerator.csproj Croc.XFW3.Web .\Middleware

here I assume that the view is inside Middleware\Views 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天全站免登陆