wake-up-neo.com

ASP.NET Core 2.1 Angular 6.0 SPA-Vorlage - Rasiererseite (cshtml) für Index statt statischer Seite

Ich versuche, meine Anwendung ASP.NET Core 2.0 Angular 5 mit webpack setup nach ASP.NET Core 2.1 Angular 6 mit Angular-Cli zu migrieren. 

Kurze Frage:

Wie kann ich mit Microsoft.AspNetCore.SpaServices.Extensions das Parsing von Rasiererseiten-Anweisungen aus cshtml erzwingen? 

Ich möchte nicht index.html von Angular.json verwenden, sondern index.cshtml.

Lange Beschreibung:

Ich habe ein neues ASP.NET Core-Projekt von Angular template gestartet. Es gibt einige Dinge, die nur auf magische Weise funktionieren. 

  1. Im index.html-Ordner befindet sich eine ClientApp/src-Datei, die automatisch beim Start der Anwendung __.
  2. Wenn die Anwendung ausgeführt wird, werden vor dem </body>-Tag aus index.html (vom ersten Punkt) mehrere Skripts eingefügt: inline.bundle.js, polyfills.bundle.js, vendor.bundle.js, main.bundle.js und styles.bundle.css vor </head>-Tag.

Ich bin nicht sicher, wer diese Skripte eingefügt hat, aber ich möchte sie auf der Razor-Seite (cshtml) einfügen.

Ich habe versucht, Code aus meinem alten Projekt zu verwenden:

<!DOCTYPE html>
<html>
<head>
    <base href="/" />
    <title>@ViewData["Title"]</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
@{string googleAnalyticsId = Html.Raw(ViewData["GoogleAnalyticsId"]).ToString();}
@if (!string.IsNullOrEmpty(googleAnalyticsId))
{
    <script>
        (function(i, s, o, g, r, a, m)
        {
           ...
        })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');

        ga('create', '@googleAnalyticsId', 'auto');
    </script>
}
<script>
    @Html.Raw(ViewData["TransferData"])
</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/0.8.2/css/flag-icon.min.css" async defer />
<script src="https://apis.google.com/js/platform.js" async defer></script>
<app>
    <!-- loading layout replaced by app after startupp -->
    <div class="page-loading">
        <div class="bar">
            <i class="sphere"></i>
        </div>
    </div>
</app>
</body>
</html>

Und zeigen Sie Indexoptionen in Angular.json auf diesen index.cshtml:

  "architect": {
    "build": {
      "builder": "@angular-devkit/build-angular:browser",
        "options": {
            "outputPath": "wwwroot/dist",
            "index": "Views/Home/Index.cshtml",   //<----- here

Das Problem ist, dass der Inhalt (alle @ -Tags) nicht von ASP.NET Core verarbeitet wird, sondern direkten Inhalt ausgibt:

<!DOCTYPE html>
<html>
<head>
    <base href="/" />
    <title>@ViewData["Title"]</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
@{string googleAnalyticsId = Html.Raw(ViewData["GoogleAnalyticsId"]).ToString();}
@if (!string.IsNullOrEmpty(googleAnalyticsId))
{
    <script>
...

aber es sollte sein:

<!DOCTYPE html>
<html>
<head>
    <base href="/" />
    <title>Test title</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
    <script>

Ich möchte einige Variablen (von appsettings.json) auf die HTML-Endseite drucken. Da ich bereits ASP.NET Core verwende, scheint die Razor-Seite eine gute Lösung zu sein.

Ich versuche auch:
Zum Hinzufügen neuer RazorPage werden C # -Inhalte (@ -Anweisungen) verarbeitet, aber niemand fügt Angular -Skripts ein.

Antwort von AndyCunningham:

ng build --prod schreibt diese Dateien:

<script type="text/javascript" src="runtime.b38c91f828237d6db7f0.js"></script><script type="text/javascript" src="polyfills.2fc3e5708eb8f0eafa68.js"></script><script type="text/javascript" src="main.16911708c355ee56ac06.js"></script> 

zu index.html. Wie schreibe ich das auf die Rasiermesserseite?.

5
Makla

es ist eine alte Frage, aber ich hoffe, die Antwort hilft jemandem

Nun, es ist schwierig, dass das Webpack das Scripts-Tag in Sie index.cshtml einfügt, aber Sie können die Tags auch in die index.cshtml einfügen

@{
    ViewData["title"] = "I'am from cshtml";
}
<app-root>Loading...</app-root>
<script type="text/javascript" src="/runtime.js"></script>
<script type="text/javascript" src="/polyfills.js"></script>
<script type="text/javascript" src="/styles.js"></script>
<script type="text/javascript" src="/vendor.js"></script>
<script type="text/javascript" src="/main.js"></script>

dann kannst du deinen mvc gerne fräsen

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action=Index}/{id?}");

    routes.MapRoute(
        name: "spa-fallback",
        template: "{*url:regex(^((?!.css|.map|.js|sockjs).)*$)}",
        defaults: new { controller = "Home", action = "Index" });

});

Alle Routen, die nicht mit {Controller} {action = Index}/{id?} Korrespondieren, fallen in "Spa-Fallback", die besagen, dass die Datei nicht über .css oder .map oder .js oder .sockjs verfügt Startseite/Index. Es ist notwendig, dass der "Regex" für .NET die erforderlichen Skriptdateien bereitstellt.

Der letzte Schritt besteht darin, dass Sie angle.json so konfigurieren, dass der Name der Skripts mithilfe von outputHashing: all beibehalten wird

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "ClientApp": {
      ...
      "architect": {
        "build": {
            ...
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all", //<--add this line
                  ...
            },
            ....
  },
  "defaultProject": "ClientApp"
}

Als letztes können wir überprüfen, ob eine URL gültig ist oder nicht (ansonsten kann der URL-Server die Indexseite sein), die Sie in "startup.cs" verwenden können

app.Use(async (context, next) =>
{
    string path = context.Request.Path.Value.Substring(1);
    bool encontrado = path.EndsWith(".js") || path.EndsWith(".css") || path.EndsWith(".map") || path.StartsWith("sockjs");
    if (!encontrado)
    {
        ..use your code to check the url...
    }
    if (encontrado)
        await next.Invoke(); //<--continue
    else
    {   //send to an error404 page
        context.Response.ContentType = "text/html";
        await context.Response.SendFileAsync(Path.Combine(env.WebRootPath, "error404.html"));
    }
});

HINWEIS: Ich setze die href der Skripte in den absoluten Pfad, z. B. src = "/ runtime.js". Nun, im Paket json können wir mehrere Skripte haben

"scripts": {
    "ng": "ng",
    "start": "ng serve --base-href=/ --serve-path=/",
    "start:fr": "ng serve --base-href=/fr-FR/ --configuration=fr --serve-path=/fr-FR",
    "build": "ng build",
    ...
  },

Wenn Sie --serve-path = fr-FR verwenden, muss die Skriptreferenz diesen Servepfad verwenden, z. src = "/ fr-FR/runtime.js" 

3
Eliseo

Ich stütze diese Antwort auf meine Erfahrung mit React SPA-Erweiterungen, aber sie sollte auch für Angular hilfreich sein, da sie den gleichen ClientApp/index.html-Middleware-Mechanismus und den gleichen IApplicationBuilder.UseSpa entrypoint verwendet .

Das Problem ist, dass bei der Verwendung von app.UseSpa(...) die Standardimplementierung dieser Erweiterung configureseine Middleware ist, die ALLE UI-Anforderungen abfragt und sie an index.html weiterleitet.

Ich habe ein kurzes Beispiel dafür geschaffen, wie wir dies für unsere Projekte umgehen können: https://github.com/andycmaj/aspnet_spa_without_indexhtml/pull/1/files sollte Ihnen zeigen, was geändert werden muss, um den Index zu ignorieren .html und verwenden Sie stattdessen eine Rasiereransicht.

Grundsätzlich habe ich das, was UseSpa tut, neu implementiert, jedoch ohne die Middleware, die abfängt und fwds an index.html bindet.

Beachten Sie, dass die Rasiereransicht Home noch die wichtigsten Dinge erledigen muss, die index.html ausgeführt hat. Am wichtigsten ist, dass es bundle.js enthalten muss, das von der SPA-Middleware für statische Inhalte bereitgestellt wird.

1
AndyCunningham