我正在尝试将ASP.NET Core 2.0 Angular 5
设置的webpack
应用程序迁移到ASP.NET Core 2.1 Angular 6
Angular-Cli
cshtml
。
简短问题:
如何强制使用Microsoft.AspNetCore.SpaServices.Extensions
解析index.html
的剃刀页面指令?
我不想使用Angular.json
中的index.cshtml
,而是使用index.html
。
详细说明:
我从Angular template开始了一个新的ASP.NET核心项目。有很多东西可以神奇地起作用。
ClientApp/src
文件夹中有</body>
个文件
应用程序启动时自动提供服务。index.html
之前的inline.bundle.js
标记(从第一点开始)会插入几个脚本:polyfills.bundle.js
,vendor.bundle.js
,main.bundle.js
,{{在styles.bundle.css
标记之前1}}和</head>
。我不确定是谁插入了这些脚本,但我想将它们插入Razor页面(cshtml
)。
我尝试使用旧项目中的代码:
<!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>
并将Angular.json
中的索引选项指向此index.cshtml
:
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "wwwroot/dist",
"index": "Views/Home/Index.cshtml", //<----- here
问题是ASP.NET Core不处理内容(所有@标签),但它输出直接内容:
<!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>
...
但它应该是:
<!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>
我想打印一些变量(从appsettings.json)到结束html页面。由于我已经在使用ASP.NET Core,因此Razor页面似乎是很好的解决方案。
我也尝试:
添加新的RazorPage,处理C#内容(@指令),但没有人插入Angular脚本。
对AndyCunningham的回复回答:
ng build --prod
写下这些文件:
<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>
到index.html
。如何将此写入剃刀页面。
答案 0 :(得分:4)
这是一个古老的问题,但我希望答案能帮助某人
好吧,很难让webpack在您的index.cshtml中插入scripts标签,但是您可以像这样
那样将标签包含在index.cshtml中 $.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
}).fail(function (reason) {
console.log("SignalR connection failed: " + reason);
});
然后您可以像路由pvc一样
@{
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>
请注意,所有与{controller} {action = Index} / {id?}不对应的路由都属于“ spa-fallback”,即如果文件没有.css或.map或.js或。 sockjs为您的家庭/索引提供服务。 NET的“正则表达式”是必需的,而脚本文件则是必需的。
最后一步是使用outputHashing:all
配置您的angular.json以维护脚本的名称。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" });
});
最后,我们可以检查您可以在startup.cs中使用的url是否有效(其他任何url服务器都是索引页)
{
"$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"
}
注意:我将脚本的href放在绝对路径中,例如src =“ / runtime.js”,在json包中,我们可以有几个脚本,如
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"));
}
});
如果我们使用--serve-path = fr-FR,则脚本的href必须使用此serve-path,例如src =“ / fr-FR / runtime.js”
答案 1 :(得分:2)
我将这个答案基于我对React SPA扩展的经验,但是它对于Angular也应该有所帮助,因为它使用了the same ClientApp/index.html
middleware mechanism和相同的IApplicationBuilder.UseSpa
入口点。
问题在于,当您使用() VALUES ()'] [parameters: ({}, {}, {}, {}, {}, {}, {}, {} ... displaying 10 of 895203 total bound parameter sets ... {}, {})] (Background on this error at: http://sqlalche.me/e/2j85)
时,此扩展名configures a middleware that listens for ALL UI requests and fwds them to index.html的默认实现。
我已经为我们的项目构建了一个简短的示例:https://github.com/andycmaj/aspnet_spa_without_indexhtml/pull/1/files应该向您展示需要更改哪些内容以忽略index.html并使用剃刀视图。
基本上,我已经重新实现了app.UseSpa(...)
的功能,但是没有将拦截和转发的中间件附加到index.html。
请注意,UseSpa
剃刀视图仍然需要做index.html正在做的更重要的事情。最重要的是,它需要include bundle.js
由SPA静态内容中间件提供服务。
答案 2 :(得分:-1)
您处于正确的道路上,您仍然需要_layout.cshtml
中拥有的所有内容,但是您没有修改Angular index.html。相反,您的Home/Index.cshtml
或_layout.cshtml
将包含<app-root>
元素以及所有的角度脚本。您可能需要禁用生成的角度文件中的哈希值,并使用ASP.NET来使您的JS无效。
此链接详细解释了此问题,但在Angular 6 + ASP.NET Core 2.1中,我仍然遇到一些小问题: Add Angular 5 CLI project to ASP.Net Core 2.0 project