Angular and ASP.NET Core MVC: "Uncaught SyntaxError: Unexpected token '<'" for index file references when deployed
Angular and ASP.NET Core MVC: "Uncaught SyntaxError: Unexpected token '<'" for index file references when deployed
我有一个使用 ASP.NET Core MVC 和 Angular UI 框架的应用程序。
我可以 运行 IIS Express 开发环境中的应用程序没有问题。当我切换到 IIS Express 生产环境或部署到 IIS 主机时,无法读取我的索引引用文件并显示浏览器错误:
Uncaught SyntaxError: Unexpected token '<'
这些页面看起来像是在加载索引页面,而不是 .js 或 .css 文件。
这是底层 runtime.js 的一个片段,因为它应该加载到浏览器中,而不是 index.html。
/******/ (function(modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ function webpackJsonpCallback(data) {
/******/ var chunkIds = data[0];
/******/ var moreModules = data[1];
/******/ var executeModules = data[2];
/******/
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0, resolves = [];
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]);
/******/ }
根据我的理解,这应该是命名或路径错误,但我可以在浏览器中访问索引文件,这些文件都在同一个文件夹中,并且没有文件名散列。我注意到一些文件夹结构似乎被排除在 .csproj 之外,但这似乎并不影响文件本身。
我认为这与 startup.cs、.csproj 说明或 IIS 配置有关,但如果没有更具体的错误,我看不出哪里出了问题。
Program.cs:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SNAP
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Startup.cs:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SNAP.Data;
namespace SNAP
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
AppData.configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddControllersWithViews();
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "SNAP-UI/dist/SNAP-UI";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
//Cannot recognize environment?
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "SNAP-UI";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
}
.csproj:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<IsPackable>false</IsPackable>
<SpaRoot>SNAP-UI\</SpaRoot>
<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
<!-- Set this to true if you enable server-side prerendering -->
<BuildServerSideRenderer>false</BuildServerSideRenderer>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="5.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
<PackageReference Include="nb.Core" Version="6.2.3" />
<PackageReference Include="nb.Data" Version="4.3.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.19" />
</ItemGroup>
<ItemGroup>
<!-- Don't publish the SPA source files, but do show them in the project files list -->
<Compile Remove="SNAP-UI\**" />
<Compile Remove="SNAPUI\**" />
<Content Remove="$(SpaRoot)**" />
<Content Remove="SNAP-UI\**" />
<Content Remove="SNAPUI\**" />
<EmbeddedResource Remove="SNAP-UI\**" />
<EmbeddedResource Remove="SNAPUI\**" />
<None Remove="$(SpaRoot)**" />
<None Remove="SNAP-UI\**" />
<None Remove="SNAPUI\**" />
<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
</ItemGroup>
<ItemGroup>
<None Remove="SNAP-UI\browserslist" />
<None Remove="SNAP-UI\e2e\protractor.conf.js" />
<None Remove="SNAP-UI\e2e\src\app.e2e-spec.ts" />
<None Remove="SNAP-UI\e2e\src\app.po.ts" />
<None Remove="SNAP-UI\e2e\tsconfig.e2e.json" />
<None Remove="SNAP-UI\src\app\angular-material.module.ts" />
<None Remove="SNAP-UI\src\app\app.server.module.ts" />
<None Remove="SNAP-UI\src\app\core\base.service.ts" />
<None Remove="SNAP-UI\src\app\core\deal.service.ts" />
<None Remove="SNAP-UI\src\app\counter\counter.component.html" />
<None Remove="SNAP-UI\src\app\counter\counter.component.spec.ts" />
<None Remove="SNAP-UI\src\app\counter\counter.component.ts" />
<None Remove="SNAP-UI\src\app\deals\Deal.ts" />
<None Remove="SNAP-UI\src\app\deals\dealcalendar.component.ts" />
<None Remove="SNAP-UI\src\app\fetch-data\fetch-data.component.html" />
<None Remove="SNAP-UI\src\app\fetch-data\fetch-data.component.ts" />
<None Remove="SNAP-UI\src\app\home\home.component.html" />
<None Remove="SNAP-UI\src\app\home\home.component.ts" />
<None Remove="SNAP-UI\src\app\kendo_ui.module.ts" />
<None Remove="SNAP-UI\src\app\nav-menu\nav-menu.component.ts" />
<None Remove="SNAP-UI\src\karma.conf.js" />
<None Remove="SNAP-UI\src\tsconfig.app.json" />
<None Remove="SNAP-UI\src\tsconfig.server.json" />
<None Remove="SNAP-UI\src\tsconfig.spec.json" />
<None Remove="SNAP-UI\src\tslint.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SNAP.Data\SNAP.Data.csproj" />
<ProjectReference Include="..\SNAP.Domain\SNAP.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<TypeScriptCompile Include="SNAP-UI\src\app\angular-material.module.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\core\base.service.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\core\deal.service.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\deals\deal.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\deals\dealcalendar.component.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\kendo_ui.module.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\nav-menu\nav-menu.component.ts" />
</ItemGroup>
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
<Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
</Target>
<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build --prod --ec=false --oh=media" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr --prod --ec=false --oh=media" Condition=" '$(BuildServerSideRenderer)' == 'true' " />
<!-- Include the newly-built files in the publish output -->
<ItemGroup>
<DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
<DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" />
<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
<RelativePath>%(DistFiles.Identity)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</ResolvedFileToPublish>
</ItemGroup>
</Target>
</Project>
更新 1:
经过进一步的 IIS 调查,页面似乎正在为单页应用程序进行一些 304 重定向。这发生在 IIS Express(生产模式)和 IIS 主机上。服务器还为非索引组件提供 text/HTML。我在主项目中没有 Web 配置,但它是在发布时生成的。我已将已发布的 web.config 更新为仅指向索引页。这并没有解决问题。
web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\SNAP.dll" stdoutLogEnabled="true" stdoutLogFile="C:\source\TempLog\" hostingModel="inprocess">
<handlerSettings>
<handlerSetting name="debugFile" value="C:\source\TempLog\tempDebug.log" />
<handlerSetting name="debugLevel" value="FILE,TRACE" />
</handlerSettings>
</aspNetCore>
</system.webServer>
</location>
<system.webServer>
<rewrite>
<rules>
<rule name="AddTrailingSlashRule1" stopProcessing="true">
<match url="(.*[^/])$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Redirect" url="{R:1}/" />
</rule>
<rule name="SPA Routes" stopProcessing="true">
<!-- match everything by default -->
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<!-- unless its a file -->
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<!-- or a directory -->
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<!-- or is under the /api directory -->
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
<!-- list other routes or route prefixes here if you need to handle them server side -->
</conditions>
<!-- rewrite it to /index.html -->
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
<tracing>
<traceFailedRequests>
<add path="*">
<traceAreas>
<add provider="ASP" verbosity="Verbose" />
<add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
<add provider="ISAPI Extension" verbosity="Verbose" />
<add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,FastCGI,WebSocket,ANCM,Rewrite" verbosity="Verbose" />
</traceAreas>
<failureDefinitions statusCodes="200-600" />
</add>
</traceFailedRequests>
</tracing>
</system.webServer>
</configuration>
<!--ProjectGuid: d1eca6b3-ff92-4130-9f13-9b13719c7794-->
更新二:
经过进一步调查,我注意到 Program.cs 中有 2 个兴趣点。当 运行 在 IIS Express 上处于生产模式时,在浏览器中刷新应用程序之前,该应用程序似乎不会访问服务器端。似乎 CreateHostBuilder
在 IIS Express 生产模式下挂起。我使用断点确认该应用程序似乎已完全完成 startup.cs(来自 program.cs 的唯一调用)。如果我尝试将断点移动到 CreateHostBuilder
之后,我会收到此错误。
Unable to set the next statement. This thread has called into a function that cannot be displayed.
Program.cs
namespace SNAP
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
Console.WriteLine("Build Complete");
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
可能你不见了
app.UseStaticFiles();
if (!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
因此,就我而言,当我使用 SPA 创建项目时。我使用下一个配置。 s
https://github.com/tematre/Site/blob/master/TemaTre.Site.Resume/Startup.cs
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles()
.UseStaticFiles()
.UseDirectoryBrowser();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
所以,你没有UseDirectoryBrowser()
试试吧,也许对你有帮助。
再评论:.UseStaticFiles() 提供来自 wwwroot 的文件,但它可以更改。 (从屏幕截图我看到你的文件存储在 'distrib' 文件夹中)
其他选项是使用UseSpaStaticFiles()
或UseSpa()
UseSpaStaticFiles
- 在资产中提供静态文件,如图像,css,js
angular 应用
的文件夹
UseSpa
- 让 asp.net 核心知道你想要 运行 你的哪个目录
angular 应用程序,运行在生产模式下安装时的 dist 文件夹和
在开发模式下 运行 angular 应用程序的哪个命令
有使用这种方法的例子:
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
我有一个使用 ASP.NET Core MVC 和 Angular UI 框架的应用程序。
我可以 运行 IIS Express 开发环境中的应用程序没有问题。当我切换到 IIS Express 生产环境或部署到 IIS 主机时,无法读取我的索引引用文件并显示浏览器错误:
Uncaught SyntaxError: Unexpected token '<'
这些页面看起来像是在加载索引页面,而不是 .js 或 .css 文件。
这是底层 runtime.js 的一个片段,因为它应该加载到浏览器中,而不是 index.html。
/******/ (function(modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ function webpackJsonpCallback(data) {
/******/ var chunkIds = data[0];
/******/ var moreModules = data[1];
/******/ var executeModules = data[2];
/******/
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0, resolves = [];
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]);
/******/ }
根据我的理解,这应该是命名或路径错误,但我可以在浏览器中访问索引文件,这些文件都在同一个文件夹中,并且没有文件名散列。我注意到一些文件夹结构似乎被排除在 .csproj 之外,但这似乎并不影响文件本身。
我认为这与 startup.cs、.csproj 说明或 IIS 配置有关,但如果没有更具体的错误,我看不出哪里出了问题。
Program.cs:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SNAP
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Startup.cs:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SNAP.Data;
namespace SNAP
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
AppData.configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddControllersWithViews();
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "SNAP-UI/dist/SNAP-UI";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
//Cannot recognize environment?
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "SNAP-UI";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
}
.csproj:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<IsPackable>false</IsPackable>
<SpaRoot>SNAP-UI\</SpaRoot>
<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
<!-- Set this to true if you enable server-side prerendering -->
<BuildServerSideRenderer>false</BuildServerSideRenderer>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="5.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
<PackageReference Include="nb.Core" Version="6.2.3" />
<PackageReference Include="nb.Data" Version="4.3.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.19" />
</ItemGroup>
<ItemGroup>
<!-- Don't publish the SPA source files, but do show them in the project files list -->
<Compile Remove="SNAP-UI\**" />
<Compile Remove="SNAPUI\**" />
<Content Remove="$(SpaRoot)**" />
<Content Remove="SNAP-UI\**" />
<Content Remove="SNAPUI\**" />
<EmbeddedResource Remove="SNAP-UI\**" />
<EmbeddedResource Remove="SNAPUI\**" />
<None Remove="$(SpaRoot)**" />
<None Remove="SNAP-UI\**" />
<None Remove="SNAPUI\**" />
<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
</ItemGroup>
<ItemGroup>
<None Remove="SNAP-UI\browserslist" />
<None Remove="SNAP-UI\e2e\protractor.conf.js" />
<None Remove="SNAP-UI\e2e\src\app.e2e-spec.ts" />
<None Remove="SNAP-UI\e2e\src\app.po.ts" />
<None Remove="SNAP-UI\e2e\tsconfig.e2e.json" />
<None Remove="SNAP-UI\src\app\angular-material.module.ts" />
<None Remove="SNAP-UI\src\app\app.server.module.ts" />
<None Remove="SNAP-UI\src\app\core\base.service.ts" />
<None Remove="SNAP-UI\src\app\core\deal.service.ts" />
<None Remove="SNAP-UI\src\app\counter\counter.component.html" />
<None Remove="SNAP-UI\src\app\counter\counter.component.spec.ts" />
<None Remove="SNAP-UI\src\app\counter\counter.component.ts" />
<None Remove="SNAP-UI\src\app\deals\Deal.ts" />
<None Remove="SNAP-UI\src\app\deals\dealcalendar.component.ts" />
<None Remove="SNAP-UI\src\app\fetch-data\fetch-data.component.html" />
<None Remove="SNAP-UI\src\app\fetch-data\fetch-data.component.ts" />
<None Remove="SNAP-UI\src\app\home\home.component.html" />
<None Remove="SNAP-UI\src\app\home\home.component.ts" />
<None Remove="SNAP-UI\src\app\kendo_ui.module.ts" />
<None Remove="SNAP-UI\src\app\nav-menu\nav-menu.component.ts" />
<None Remove="SNAP-UI\src\karma.conf.js" />
<None Remove="SNAP-UI\src\tsconfig.app.json" />
<None Remove="SNAP-UI\src\tsconfig.server.json" />
<None Remove="SNAP-UI\src\tsconfig.spec.json" />
<None Remove="SNAP-UI\src\tslint.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SNAP.Data\SNAP.Data.csproj" />
<ProjectReference Include="..\SNAP.Domain\SNAP.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<TypeScriptCompile Include="SNAP-UI\src\app\angular-material.module.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\core\base.service.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\core\deal.service.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\deals\deal.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\deals\dealcalendar.component.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\kendo_ui.module.ts" />
<TypeScriptCompile Include="SNAP-UI\src\app\nav-menu\nav-menu.component.ts" />
</ItemGroup>
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
<Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
</Target>
<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build --prod --ec=false --oh=media" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr --prod --ec=false --oh=media" Condition=" '$(BuildServerSideRenderer)' == 'true' " />
<!-- Include the newly-built files in the publish output -->
<ItemGroup>
<DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
<DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" />
<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
<RelativePath>%(DistFiles.Identity)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</ResolvedFileToPublish>
</ItemGroup>
</Target>
</Project>
更新 1:
经过进一步的 IIS 调查,页面似乎正在为单页应用程序进行一些 304 重定向。这发生在 IIS Express(生产模式)和 IIS 主机上。服务器还为非索引组件提供 text/HTML。我在主项目中没有 Web 配置,但它是在发布时生成的。我已将已发布的 web.config 更新为仅指向索引页。这并没有解决问题。
web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\SNAP.dll" stdoutLogEnabled="true" stdoutLogFile="C:\source\TempLog\" hostingModel="inprocess">
<handlerSettings>
<handlerSetting name="debugFile" value="C:\source\TempLog\tempDebug.log" />
<handlerSetting name="debugLevel" value="FILE,TRACE" />
</handlerSettings>
</aspNetCore>
</system.webServer>
</location>
<system.webServer>
<rewrite>
<rules>
<rule name="AddTrailingSlashRule1" stopProcessing="true">
<match url="(.*[^/])$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Redirect" url="{R:1}/" />
</rule>
<rule name="SPA Routes" stopProcessing="true">
<!-- match everything by default -->
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<!-- unless its a file -->
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<!-- or a directory -->
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<!-- or is under the /api directory -->
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
<!-- list other routes or route prefixes here if you need to handle them server side -->
</conditions>
<!-- rewrite it to /index.html -->
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
<tracing>
<traceFailedRequests>
<add path="*">
<traceAreas>
<add provider="ASP" verbosity="Verbose" />
<add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
<add provider="ISAPI Extension" verbosity="Verbose" />
<add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,FastCGI,WebSocket,ANCM,Rewrite" verbosity="Verbose" />
</traceAreas>
<failureDefinitions statusCodes="200-600" />
</add>
</traceFailedRequests>
</tracing>
</system.webServer>
</configuration>
<!--ProjectGuid: d1eca6b3-ff92-4130-9f13-9b13719c7794-->
更新二:
经过进一步调查,我注意到 Program.cs 中有 2 个兴趣点。当 运行 在 IIS Express 上处于生产模式时,在浏览器中刷新应用程序之前,该应用程序似乎不会访问服务器端。似乎 CreateHostBuilder
在 IIS Express 生产模式下挂起。我使用断点确认该应用程序似乎已完全完成 startup.cs(来自 program.cs 的唯一调用)。如果我尝试将断点移动到 CreateHostBuilder
之后,我会收到此错误。
Unable to set the next statement. This thread has called into a function that cannot be displayed.
Program.cs
namespace SNAP
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
Console.WriteLine("Build Complete");
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
可能你不见了
app.UseStaticFiles();
if (!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
因此,就我而言,当我使用 SPA 创建项目时。我使用下一个配置。 s
https://github.com/tematre/Site/blob/master/TemaTre.Site.Resume/Startup.cs
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles()
.UseStaticFiles()
.UseDirectoryBrowser();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
所以,你没有UseDirectoryBrowser()
试试吧,也许对你有帮助。
再评论:.UseStaticFiles() 提供来自 wwwroot 的文件,但它可以更改。 (从屏幕截图我看到你的文件存储在 'distrib' 文件夹中)
其他选项是使用UseSpaStaticFiles()
或UseSpa()
的文件夹UseSpaStaticFiles
- 在资产中提供静态文件,如图像,css,js angular 应用UseSpa
- 让 asp.net 核心知道你想要 运行 你的哪个目录 angular 应用程序,运行在生产模式下安装时的 dist 文件夹和 在开发模式下 运行 angular 应用程序的哪个命令
有使用这种方法的例子:
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});