[英]Routing in Angular 7 running in subfolder not working correctly
We are working on migrating our application to a new Angular version.我们正在努力将我们的应用程序迁移到新的 Angular 版本。 The old one (Angular.JS) was it's own application/repo being served by an .NET Framework 4.5.2 ASP.NET MVC application that would route every call to
Home
which would return a Razor View that contained the angular application and then start it up, possibly routing the suffix of the URL to the actual Angular page.旧的 (Angular.JS) 是它自己的应用程序/存储库,由 .NET Framework 4.5.2 ASP.NET MVC 应用程序提供服务,该应用程序会将每次调用路由到
Home
,后者将返回一个包含角度应用程序的 Razor 视图,然后启动它,可能将 URL 的后缀路由到实际的 Angular 页面。 For example, it would route www.website.com/profile
to the profile
route in Angular, NOT trying to access a folder called profile
on the server.例如,它会将
www.website.com/profile
路由到 Angular 中的profile
路由,而不是尝试访问服务器上名为profile
的文件夹。 Integrating our API and Angular.JS application is not too too pretty but it worked.集成我们的 API 和 Angular.JS 应用程序并不太漂亮,但它奏效了。 The server also has virtual folders in IIS for other subfolders that should be accessed like fonts, images, configs, etc.
服务器在 IIS 中还有虚拟文件夹,用于其他应该访问的子文件夹,如字体、图像、配置等。
Currently I am working on getting the Angular 7 application to run alongside the Angular.JS application.目前我正在努力让 Angular 7 应用程序与 Angular.JS 应用程序一起运行。 We want to run the Angular 7 application to run inside of a directory of the current application and later on move it to it's own web app because our new Angular application is just a bunch of static files and does not need to be bundled with the server anymore.
我们希望运行 Angular 7 应用程序以在当前应用程序的目录中运行,然后将其移动到它自己的 Web 应用程序中,因为我们的新 Angular 应用程序只是一堆静态文件,不需要与服务器捆绑了。 Basically, there is no need for any ASP.NET MVC configuration.
基本上,不需要任何 ASP.NET MVC 配置。
The current url would be www.website.com
and return the Angular.JS application.当前 url 将是
www.website.com
并返回 Angular.JS 应用程序。 The new one would be www.website.com/v2/
and would return the Angular 7 application.新的将是
www.website.com/v2/
并将返回 Angular 7 应用程序。 If we had finished a v2 version of the profile
page, navigating to wwww.website.com/v2/profile
should now navigate to the profile
page of the Angular 7 application.如果我们完成了 v2 版本的
profile
页面,导航到wwww.website.com/v2/profile
现在应该导航到 Angular 7 应用程序的profile
页面。
In IIS, one of the virtual folders is a folder called dist
which leads to the location of the Angular.JS app files.在 IIS 中,其中一个虚拟文件夹是一个名为
dist
的文件夹,它指向 Angular.JS 应用程序文件的位置。 A new one called v2
is now configured, which leads to the location of the Angular 7 app files.现在配置了一个名为
v2
的新文件,它指向 Angular 7 应用程序文件的位置。 Another one called assets
leads to the assets
folder of the Angular 7 application.另一个名为
assets
的文件夹指向 Angular 7 应用程序的assets
文件夹。
Now, when I navigate to www.website.com/v2/
, Angular starts and routes me to www.website.com/v2/home
, which is the home route.现在,当我导航到
www.website.com/v2/
,Angular 会启动并将我路由到www.website.com/v2/home
,这是主路由。
The issue is that when I type in www.website.com/v2/home
myself, it results in the application routing back to www.website.com
.问题是当我自己输入
www.website.com/v2/home
,它会导致应用程序路由回www.website.com
。 and thus it boots up the Angular.JS application again.因此它会再次启动 Angular.JS 应用程序。 There are no errors or redirects taking place.
没有发生错误或重定向。 It seems like it just ignores the part that comes after the
v2/
part even though Angular.JS does this just fine.似乎它只是忽略了
v2/
部分之后的部分,即使 Angular.JS 做得很好。
TL;DR Navigating to www.website.com/v2
loads up Angular 7, but navigating to v2/{{Anything}}
results in the application falling back to the Angular.JS application running on www.website.com
, even though if {{anything}}
was an internal link in Angular 7, it would navigate to the {{anything}}
route. TL;DR导航到
www.website.com/v2
会加载 Angular 7,但导航到v2/{{Anything}}
导致应用程序回退到在www.website.com
运行的 Angular.JS 应用程序,即使{{anything}}
在角7的内部链接,将导航到{{anything}}
路线。
I build the Angular project with the following command:我使用以下命令构建 Angular 项目:
ng build --configuration=dev --deploy-url=/v2/ --base-href=/v2/
The routes in the angular 7 application look like this: angular 7 应用程序中的路由如下所示:
const routes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full',
},
{
path: '',
canActivate: [AuthGuard],
component: DefaultLayoutComponent,
children: [
{
path: 'home',
component: DashboardComponent,
canLoad: [NoAuthGuard],
},
{
path: 'contact',
loadChildren: './modules/contact/contact.module#ContactModule',
canLoad: [NoAuthGuard],
},
{
path: 'timesheets',
loadChildren: './modules/timesheet/timesheet.module#TimesheetModule',
canLoad: [NoAuthGuard],
},
{
path: 'users',
loadChildren: './modules/users/users.module#UsersModule',
canLoad: [NoAuthGuard, NgxPermissionsGuard],
data: {
permissions: {
only: 'seeUsersPage',
redirectTo: '/403',
},
},
},
{
path: 'profile',
loadChildren: './modules/profile/profile.module#ProfileModule',
canLoad: [NoAuthGuard],
},
],
},
{
path: 'login',
component: LoginComponent,
},
{
path: '403',
component: Page403Component,
},
{
path: '**',
redirectTo: '/home',
pathMatch: 'full',
},
];
Can anyone tell me how I can make, for example, typing www.website.com/v2/contact
in the browser lead to the v2 contact page, while also making the internal navigation possible (so if the user clicks on a "navigate to v2 contact page" inside of the Angular 7 application, it also navigates to the v2 contact page)谁能告诉我如何使,例如,在浏览器中输入
www.website.com/v2/contact
导致 v2 联系页面,同时还可以进行内部导航(因此,如果用户单击“导航到v2 联系页面”在 Angular 7 应用程序内部,它还导航到 v2 联系页面)
Edit: Information about the Angular.JS Routerconfig
and the back-end web.config
were requested;编辑:请求有关 Angular.JS
Routerconfig
和后端web.config
的信息; I have provided them below.我在下面提供了它们。
RouterConfig
: RouterConfig
:
$routeProvider
.when('/', {
templateUrl: 'scripts/home/home.html',
controller: 'HomeController',
controllerAs: 'homeCtrl'
})
.when('/gebruikers', {
templateUrl: 'scripts/users/users.html',
controller: 'UsersController',
controllerAs: 'usersCtrl'
})
.when('/profiel', {
templateUrl: 'scripts/profile/profile.html',
controller: 'ProfileController',
controllerAs: 'profileCtrl'
})
.when('/timesheets', {
templateUrl: 'scripts/timesheets/timesheets.html',
controller: 'TimesheetsController',
controllerAs: 'timesheetsCtrl',
reloadOnSearch: false
})
.when('/facturen', {
templateUrl: 'scripts/invoices/invoices.html',
controller: 'InvoicesController',
controllerAs: 'invoicesCtrl',
reloadOnSearch: false
})
.when('/opdrachten', {
templateUrl: 'scripts/vacancies/vacancies.html',
controller: 'VacanciesController',
controllerAs: 'vacanciesCtrl'
})
.when('/contact', {
templateUrl: 'scripts/contact/contact.html',
controller: 'ContactController',
controllerAs: 'contactCtrl'
})
.when('/help', {
templateUrl: 'scripts/help/help.html',
controller: 'HelpController',
controllerAs: 'helpCtrl'
})
.otherwise({
redirectTo: '/'
});
Web.Config IIS rewrite rules:
<rewrite>
<rules>
<clear />
<rule name="Redirect Angular endpoints to MVC Home" enabled="true">
<match url="^(profiel|timesheets|facturen|opdrachten|contact|help|gebruikers)" negate="false" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="Home" logRewrittenUrl="false" />
</rule>
<!-- Some other rules that are not important are here, they redirect HTTP to HTTPS -->
</rules>
</rewrite>
The reason why it would always route back to the v1 url is because the angular 7 app contained a web.config
file that looked like this: 之所以总是将其路由回v1网址,是因为angular 7应用程序包含一个如下所示的
web.config
文件:
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Angular" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I believe this is default for an IIS deployment and a team member might have added this. 我认为这是IIS部署的默认设置,团队成员可能已添加了此设置。 I never thought about having a web.config in a front-end project.
我从未想过要在前端项目中使用web.config。
Basically, this rule takes care of rerouting the user to the index.html. 基本上,此规则负责将用户重新路由到index.html。 For example
www.website.com/folder
would normally bring the user to a folder called folder
on the webserver, but this is not where Angular runs and could cause a 404. This rule brings the user back to www.website.com
and then lets angular route the folder
part. 例如,
www.website.com/folder
folder通常会将用户带到Web服务器上的一个名为folder
的文件folder
,但这不是Angular运行的位置,并且可能会导致404。此规则将用户带回www.website.com
,然后让角度路由folder
部分。
Because I am running my application in a subfolder, I changed the url="/"
to url="/v2/"
and it worked immediatly! 因为我在子文件夹中运行应用程序,所以我将
url="/"
更改为url="/v2/"
并立即生效!
Remember to build the project with ng build --configuration=dev --deploy-url=/v2/ --base-href=/v2/
! 请记住使用
ng build --configuration=dev --deploy-url=/v2/ --base-href=/v2/
来构建项目! The deploy-url is needed because the scripts/css/other files are not found in the root folder of the server; 需要deploy-url,因为在服务器的根文件夹中找不到脚本/ css /其他文件。 it is found in /v2/.
在/ v2 /中可以找到它。 The base-href is necessary for the router;
路由器需要base-href; it should start routing the application at
www.website.com/v2/
and not at www.website.com/
! 它应该从
www.website.com/v2/
而不是www.website.com/
开始路由应用程序!
No other iis rewrite rules are necessary, no asp.net config, no special angular routing. 无需其他iis重写规则,asp.net配置,特殊的角度路由。 Just these simple steps!
这些简单的步骤!
Have you made any modification to your Web.config file? 您是否对Web.config文件进行了任何修改? You need to set it up for the base angular app (using the UrlRewrite module) I'd assume it might need a modification for your use case...
您需要为基本的角度应用程序设置它(使用UrlRewrite模块),我认为它可能需要针对您的用例进行修改...
<rewrite>
<rules>
<rule name="Angular RoutesV1" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/my/app/" />
</rule>
</rules>
</rewrite>
My assumption is you will need to add another 'rule' here. 我的假设是您将需要在此处添加另一个“规则”。 Hope this helps!!!
希望这可以帮助!!! (note: the rewrite is supposed to match your ng build base href value)
(注意:重写应该与您的ng build base href值匹配)
Web.Config IIS rewrite rules
Web.Config IIS rewrite rules
RouteConfig
change it this way RouteConfig
以这种方式更改它 RouteConfig 路由配置
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// don't change the arrangement, this must be executed first
routes.MapRoute(
name: "V2",
url: "v2/{*url}",
defaults: new { controller = "Home", action = "IndexV2", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{*url}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Basically what this does is it will catch all your route paths given with the specific route name, the {*url}
catches all the route segment regardless of the value. 基本上,此操作将捕获您使用特定路由名称指定的所有路由路径,
{*url}
捕获所有路由段,无论其值如何。
So when we say the url is; 所以当我们说URL是
Default
Default
V2
V2
Default
Default
V2
V2
and in your HomeController
make sure to add the IndexV2
并在您的
HomeController
确保添加IndexV2
HomeController 家庭控制器
public ActionResult IndexV2()
{
return View();
}
For .Net Core 3 or higher对于 .Net Core 3 或更高版本
if 404 happened in the angular subdirectory, it's because of the default route config.如果 404 发生在 angular 子目录中,那是因为默认路由配置。 so it will be fixed by writing this code on startup.
所以它将通过在启动时编写此代码来修复。
app.Use(async (context, next) => {
await next();
if (context.Response.StatusCode == 404 &&
!System.IO.Path.HasExtension(context.Request.Path.Value) &&
!context.Request.Path.Value.ToLower().StartsWith("/api/")&&
!context.Request.Path.Value.ToLower().StartsWith("/swagger"))
{
context.Request.Path = "yousubdirectory/index.html";
await next();
}
});
app.UseMvcWithDefaultRoute();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.