aspnetcore:如何 return 来自中间件的视图
aspnetcore: how to return a view from middleware
我在 aspnetcore2.0 的中间件上工作,我想在其中执行一些 razor 视图。
实际上我需要一个错误处理中间件,它可以从剃刀视图中显示漂亮的页面。我知道可以根据状态代码处理 UseStatusCodePagesWithReExecute
。但我需要一种更通用的方法 - 在我的中间件中处理异常以将其委托(在某些情况下)到错误视图。
我意识到 DeveloperExceptionPageMiddleware
做的事情与我需要的类似。但即使深入了解它的来源,我也无法理解它是如何工作的。
这是中间件 returns 视图的地方 - https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs#L206
但是我看不懂这是什么观点。它既不是 razor page(因为它没有 @page
指令)也不是 mvc view(但我不确定)。
在项目中,该视图有两个文件:ErrorPage.cshtml
和 ErrorPage.Designer.cs
。 Designer.cs 是如何创建的?它看起来像一个生成的文件。但多亏了它,项目 (ErrorPage) 中有一个正常的 class 可以显式使用。它从 Microsoft.Extensions.RazorViews.Sources
包继承 Microsoft.Extensions.RazorViews.BaseView
class。
所以中间件只执行那个视图:
var errorPage = new ErrorPage(model);
return errorPage.ExecuteAsync(context);
如何在我的项目中实现?
更新 [2018.06]:请注意 post 是为 .NET Core 2.0 编写的,.NET Core 2.1 中的 RazorEngine 有重大更改。
事实证明,这很容易做到。
Aspnet prjoect 有一个名为 RazorPageGenerator
(参见 https://github.com/aspnet/Razor/tree/dev/src/RazorPageGenerator)的内部工具,可用于编译视图。用这个工具编译后就正常了类,可以用在中间件中
但在此之前我们需要获取 RazorPageGenerator 并稍微自定义它。
1.Create 一个新的控制台项目
dotnet new console -o MyRazorGenerator
2.put 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.Add以下csprj(因为dotnet add package
不支持安装pre-prerelease包)
<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.add 变成 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我们有自己的生成器,可以编译视图
7.Create 剃刀视图 (.cshtml)
8.run我们的生成器编译视图:
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.
安装它
我在 aspnetcore2.0 的中间件上工作,我想在其中执行一些 razor 视图。
实际上我需要一个错误处理中间件,它可以从剃刀视图中显示漂亮的页面。我知道可以根据状态代码处理 UseStatusCodePagesWithReExecute
。但我需要一种更通用的方法 - 在我的中间件中处理异常以将其委托(在某些情况下)到错误视图。
我意识到 DeveloperExceptionPageMiddleware
做的事情与我需要的类似。但即使深入了解它的来源,我也无法理解它是如何工作的。
这是中间件 returns 视图的地方 - https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs#L206
但是我看不懂这是什么观点。它既不是 razor page(因为它没有 @page
指令)也不是 mvc view(但我不确定)。
在项目中,该视图有两个文件:ErrorPage.cshtml
和 ErrorPage.Designer.cs
。 Designer.cs 是如何创建的?它看起来像一个生成的文件。但多亏了它,项目 (ErrorPage) 中有一个正常的 class 可以显式使用。它从 Microsoft.Extensions.RazorViews.Sources
包继承 Microsoft.Extensions.RazorViews.BaseView
class。
所以中间件只执行那个视图:
var errorPage = new ErrorPage(model);
return errorPage.ExecuteAsync(context);
如何在我的项目中实现?
更新 [2018.06]:请注意 post 是为 .NET Core 2.0 编写的,.NET Core 2.1 中的 RazorEngine 有重大更改。
事实证明,这很容易做到。
Aspnet prjoect 有一个名为 RazorPageGenerator
(参见 https://github.com/aspnet/Razor/tree/dev/src/RazorPageGenerator)的内部工具,可用于编译视图。用这个工具编译后就正常了类,可以用在中间件中
但在此之前我们需要获取 RazorPageGenerator 并稍微自定义它。
1.Create 一个新的控制台项目
dotnet new console -o MyRazorGenerator
2.put 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.Add以下csprj(因为dotnet add package
不支持安装pre-prerelease包)
<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.add 变成 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我们有自己的生成器,可以编译视图
7.Create 剃刀视图 (.cshtml)
8.run我们的生成器编译视图:
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.
安装它