2017-10-16 1 views
3

Je travaille sur un middleware pour aspnetcore2.0 où je veux exécuter une vue rasoir.
En fait, j'ai besoin d'un middleware de gestion des erreurs qui afficherait de belles pages à partir de vues rasoir. Je sais qu'il est possible de faire avec UseStatusCodePagesWithReExecute basé sur les codes d'état. Mais j'ai besoin d'une approche plus générale - gérer une exception dans mon middleware pour déléguer (dans certains cas) à une vue d'erreur. Je me suis rendu compte que DeveloperExceptionPageMiddleware fait quelque chose de similaire à ce dont j'ai besoin. Mais je ne peux pas comprendre comment cela fonctionne même après avoir creusé dans ses sources.aspnetcore: comment retourner une vue du middleware

est ici le lieu où ce middleware retourne une vue - https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs#L206

Mais je ne comprends pas ce genre de vue, il est. Ce n'est ni une rasoir page (comme il n'a pas de @page directive) ni un mvc vue (mais je ne suis pas sûr). Dans le projet, il existe deux fichiers pour cette vue: ErrorPage.cshtml et ErrorPage.Designer.cs. Comment Designer.cs a été créé? Cela ressemble à un fichier généré. Mais grâce à cela, il y a une classe normale dans le projet (ErrorPage) qui peut être utilisée explicitement. Il hérite de la classe Microsoft.Extensions.RazorViews.BaseView du package Microsoft.Extensions.RazorViews.Sources.

Ainsi, le middleware juste execute ce point de vue:

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

Comment peut-il être atteint dans mon projet?

+0

Faut-il être un intergiciel? Un filtre d'action ou de résultat peut également le faire https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters – Tseng

+0

@Tseng principalement parce qu'il est plus robuste (le middleware peut être le premier en pipeline) et en raison de la nécessité de gérer les erreurs comme 404 (ils ne sont pas des exceptions, donc le filtre mvc les ignorera) – Shrike

Répondre

2

Il s'est avéré que c'est assez facile à faire. Aspnet Prjoect possède un outil interne appelé RazorPageGenerator (voir https://github.com/aspnet/Razor/tree/dev/src/RazorPageGenerator) qui peut être utilisé pour compiler des vues. Après compilation avec cet outil nous aurons des classes normales qui peuvent être utilisées dans les middlewares.

Mais avant d'avoir besoin de RazorPageGenerator et de le personnaliser légèrement.

1.Créez un nouveau projet de console

dotnet new console -o MyRazorGenerator 

2.Put NuGet.config dans ce dossier

<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.Ajouter ce qui suit dans csprj (comme dotnet add package ne prend pas en charge l'installation de pré paquets -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 pour vérifier que vous avez Raz orPageGenerator

5.Ajouter en 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 nous avons notre propre générateur et permet de compiler des vues

7.Create un rasoir Voir (.cshtml)

8.lancer notre générateur de compiler vue:

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

ici, je suppose que la vue est à l'intérieur dossier Middleware\Views.

9.Generator crée un fichier comme ErrorPage.Designer.cs (si vue était ErrorPage.cshtml) que nous pouvons utiliser:

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

Ici, nous allons revenir à notre point de vue en cas d'erreur 404 et absense de StatusCodePagesMiddleware. Peut être utile pour l'interface utilisateur intégrée dans les bibliothèques.

Le code généré utilise du personnel qui devrait être ajouté à votre projet. Pour l'obtenir, nous devons acquérir le paquet nuget Microsoft.Extensions.RazorViews.Sources. Encore une fois, il n'est pas sur nuget.org donc nous devons l'installer à partir de https://dotnet.myget.org/feed/aspnetcore-dev/package/nuget/Microsoft.Extensions.RazorViews.Sources.

+0

Voir aussi mon post sur ce sujet: https://techblog.dorogin.com/handling-errors-in-aspnet-core- middleware-e39872496d51 – Shrike