Angular-如何忽略API进入路由?
呼叫 https://www.mysite.example.example/api/api/jccpayment/jccpayment/jccrespsesponse 例如,我得到以下。
Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'api/jccpayment/JCCResponse' Error: Cannot match any routes. URL Segment: 'api/jccpayment/JCCResponse' at Jt.noMatchError
我注意到这仅在IIS上托管的生产中发生。有什么方法可以通过角路由忽略我的API调用?
编辑:尝试了许多方法到目前为止,
- 我的基础HREF是
< base href =“/”>
- 尝试的哈希策略
{usehash:true} < /code>
编辑2:进一步解释。我有一个.NET核心项目,该项目具有C#后端和Angular Frontend。两者都在同一项目中。 (我有我不讨论的原因,不是主题),
所以我正在做的是使用外部服务(在项目之外)中使用付款系统。我将所有要求传递给您将URL作为响应URL提供的系统。通过取消或付款,用户从该支付系统中导航后,该URL响应是在拨出付款系统后调用的。
现在,怪异的部分是:
- 在Localhost上,它总是成功地击中
- 生产,如果用户在30秒内取消或付款,否则我会得到上述未匹配路线的错误。
看来我的API调用在某种程度上被捕获在角路线上,然后给出了错误。我花了一个月的时间研究,尝试事物而没有成功。我快要截止日期了...任何帮助
编辑3:有什么办法可能是HTTP超时问题?因为响应是http帖子,而30秒的响应对我来说是一个超时错误,即使它说了有关路线
编辑4:在研究之后和研究之后,我的问题似乎是我的问题是路线。许多建议使用哈希策略,但由于少数原因,我不想使用它。因此,我使用{提供:locationstrategy,useclass:pathLocationstrategy},
...仍然一切正常,它可以很好地重新加载,我可以从浏览器URL触发细微的API调用。除非我要从付款网站返回并且它试图击中我的API ...
我的app-routing.module.ts
export const routes: Routes = [
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'folder/:id',
loadChildren: () => import('./folder/folder.module').then( m => m.FolderPageModule)
},
{
path: 'pages/test/test',
loadChildren: () => import('./pages/test/test.module').then( m => m.TestPageModule)
},
{
path: 'pages/test2/test2',
loadChildren: () => import('./pages/test2/test2.module').then( m => m.Test2PageModule)
},
{
path: 'tc-form',
loadChildren: () => import('./pages/tc-form/tc-form.module').then( m => m.TcFormPageModule)
},
{
path: 'tc-driver-list',
loadChildren: () => import('./pages/tc-driver-list/tc-driver-list.module').then( m => m.TcDriverListPageModule)
},
{
path: 'login',
loadChildren: () => import('./pages/login/login.module').then( m => m.LoginPageModule)
},
{
path: 'verification',
loadChildren: () => import('./pages/verification/verification.module').then( m => m.VerificationPageModule)
},
{
path: 'tc-formlist',
loadChildren: () => import('./pages/tc-formlist/tc-formlist.module').then( m => m.TcFormlistPageModule)
},
{
path: 'jcc-depositlist',
loadChildren: () => import('./pages/jcc-depositlist/jcc-depositlist.module').then(m => m.JCCDepositlistPageModule)
},
{
path: 'pricelist',
loadChildren: () => import('./pages/pricelist/pricelist.module').then(m => m.PricelistPageModule)
},
{
path: 'tc-checkout',
loadChildren: () => import('./pages/tc-checkout/tc-checkout.module').then( m => m.TcCheckoutPageModule)
},
{
path: 'jcc-complete',
loadChildren: () => import('./pages/jcc-complete/jcc-complete.module').then( m => m.JccCompletePageModule)
},
{
path: 'jcc-request',
loadChildren: () => import('./components-global/jcc-request/jcc-request.module').then( m => m.JccRequestPageModule)
},
{
path: 'jcc-response',
loadChildren: () => import('./components-global/jcc-response/jcc-response.module').then( m => m.JccResponsePageModule)
},
{
path: 'covernote-document',
loadChildren: () => import('./pages/covernote-document/covernote-document.module').then( m => m.CovernoteDocumentPageModule)
},
{
path: 'register',
loadChildren: () => import('./pages/register/register.module').then( m => m.RegisterPageModule)
},
{
path: 'forgot-password',
loadChildren: () => import('./pages/forgot-password/forgot-password.module').then( m => m.ForgotPasswordPageModule)
},
{
path: 'forgot-password2',
loadChildren: () => import('./pages/forgot-password2/forgot-password2.module').then( m => m.ForgotPassword2PageModule)
},
{
path: 'version-modal',
loadChildren: () => import('./pages/version-modal/version-modal.module').then( m => m.VersionModalPageModule)
},
{
path: 'home',
loadChildren: () => import('./pages/home/home.module').then( m => m.HomePageModule)
},
{
path: 'alteration',
loadChildren: () => import('./pages/alteration/alteration.module').then( m => m.AlterationPageModule)
},
{
path: 'jcc-wait',
loadChildren: () => import('./components-global/jcc-wait/jcc-wait.module').then( m => m.JccWaitPageModule)
},
//{
// path: '**',
// redirectTo: 'login',
// pathMatch: 'full'
//}
];
@NgModule({
imports: [
//LoginPageModule,
//TcDriverFormPageModule,
//RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
RouterModule.forRoot(routes)
],
exports: [RouterModule]
})
export class AppRoutingModule {}
startup.cs
// 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.Use(async (context, next) =>
{
//var url = context.Request.Path.Value;
//if (url.Contains("/api/tcform/GetCurrentDate"))
//{
// // ...do your things
// context.Response.Redirect(url, permanent: false);
// return; // short circuit
//}
await next();
if (context.Response.StatusCode == 404 && !System.IO.Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
//app.UseDeveloperExceptionPage();
}
else
{
//app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.Use(async (context, next) =>
{
//var url = context.Request.Path.Value;
//if (url.Contains("/api/tcform/GetCurrentDate"))
//{
// // ...do your things
// context.Response.Redirect(url, permanent: false);
// return; // short circuit
//}
await next();
if (context.Response.StatusCode == 404 && !System.IO.Path.HasExtension(context.Request.Path.Value) &&
!context.Request.Path.Value.Contains("/api/"))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseHsts();
}
//app.UseStaticFiles();
app.UseDefaultFiles();
app.UseStaticFiles();
//app.UseDefaultFiles();
//app.UseStaticFiles(new StaticFileOptions
//{
// OnPrepareResponse = context =>
// {
// if (context.File.Name == "index.html")
// {
// context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store");
// context.Context.Response.Headers.Add("Expires", "-1");
// }
// }
//});
if (!env.IsDevelopment())
{
//app.UseMvc();
//app.UseStatusCodePagesWithReExecute("/"); // <-- added to redirect to angular
app.UseSpaStaticFiles();
}
app.UseRouting();
app.UseSession();
app.UseHttpsRedirection();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
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";
//spa.Options.StartupTimeout = new TimeSpan(0, 10, 0);
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
我只是无法弄清楚什么问题...
编辑5:我尝试了{提供:locationstrategy,useclass:hashlocationstrategy},
,在我的URL中添加#...仍然是同一个问题。
我快要放弃了,我尝试了100多件事,没有任何效果。
编辑6:我最终发现了问题。答案是在这篇文章中 Angular + .NET Core-从浏览器调用API时仅生产问题
When calling https://www.mysite.example/api/jccpayment/JCCResponse for example I get the below.
Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'api/jccpayment/JCCResponse' Error: Cannot match any routes. URL Segment: 'api/jccpayment/JCCResponse' at Jt.noMatchError
I noticed that this happen only in production which is hosted on IIS. Is there any way to make my api calls get ignored by the angular routing?
Edit: Tried many methods nothing so far is working
- My base href is
<base href="/">
- Tried hash strategy
{useHash: true}
Edit 2: To explain further. I have a .Net Core project that has a C# backend and Angular frontend. Both are in the same project. (I have my reasons which I will not discuss, it is not the subject)
So what I am doing is using a payment system from an external service (outside of my project). I pass all the requirement and to that system you give a url as a response url. That url response is called after the user navigates out of that payment system, either by cancelling or paying.
So I give the url : https://www.mysite.example/api/jccpayment/JCCResponse which is a controller method in the C# backend of my project.
Now the weird parts are :
- On localhost it always hits successfully
- On production it works if the user cancel or pay in the span of 30 seconds otherwise I get the above error of no routes matched.
It seems somehow my api call is getting caught in the angular routes and then it gives that error. I spend like a month researching,trying things and no success. I am near my deadline...any help is appreciated
Edit 3: Is there any way it could be an http timeout issue? Because the response is http Post and 30 seconds limit sounds to me like a timeout error even if it says about the routes
Edit 4: After tons and tons of research it seems my problem is the routes. A lot of suggestions say to use the hash strategy but I do not want to use that for few reasons. So I use { provide: LocationStrategy, useClass: PathLocationStrategy },
...still everything works perfectly, it reloads fine and I can trigger fine api calls from browser url. Except when I am going back from the payment site and it tries to hit my api...
My app-routing.module.ts
export const routes: Routes = [
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'folder/:id',
loadChildren: () => import('./folder/folder.module').then( m => m.FolderPageModule)
},
{
path: 'pages/test/test',
loadChildren: () => import('./pages/test/test.module').then( m => m.TestPageModule)
},
{
path: 'pages/test2/test2',
loadChildren: () => import('./pages/test2/test2.module').then( m => m.Test2PageModule)
},
{
path: 'tc-form',
loadChildren: () => import('./pages/tc-form/tc-form.module').then( m => m.TcFormPageModule)
},
{
path: 'tc-driver-list',
loadChildren: () => import('./pages/tc-driver-list/tc-driver-list.module').then( m => m.TcDriverListPageModule)
},
{
path: 'login',
loadChildren: () => import('./pages/login/login.module').then( m => m.LoginPageModule)
},
{
path: 'verification',
loadChildren: () => import('./pages/verification/verification.module').then( m => m.VerificationPageModule)
},
{
path: 'tc-formlist',
loadChildren: () => import('./pages/tc-formlist/tc-formlist.module').then( m => m.TcFormlistPageModule)
},
{
path: 'jcc-depositlist',
loadChildren: () => import('./pages/jcc-depositlist/jcc-depositlist.module').then(m => m.JCCDepositlistPageModule)
},
{
path: 'pricelist',
loadChildren: () => import('./pages/pricelist/pricelist.module').then(m => m.PricelistPageModule)
},
{
path: 'tc-checkout',
loadChildren: () => import('./pages/tc-checkout/tc-checkout.module').then( m => m.TcCheckoutPageModule)
},
{
path: 'jcc-complete',
loadChildren: () => import('./pages/jcc-complete/jcc-complete.module').then( m => m.JccCompletePageModule)
},
{
path: 'jcc-request',
loadChildren: () => import('./components-global/jcc-request/jcc-request.module').then( m => m.JccRequestPageModule)
},
{
path: 'jcc-response',
loadChildren: () => import('./components-global/jcc-response/jcc-response.module').then( m => m.JccResponsePageModule)
},
{
path: 'covernote-document',
loadChildren: () => import('./pages/covernote-document/covernote-document.module').then( m => m.CovernoteDocumentPageModule)
},
{
path: 'register',
loadChildren: () => import('./pages/register/register.module').then( m => m.RegisterPageModule)
},
{
path: 'forgot-password',
loadChildren: () => import('./pages/forgot-password/forgot-password.module').then( m => m.ForgotPasswordPageModule)
},
{
path: 'forgot-password2',
loadChildren: () => import('./pages/forgot-password2/forgot-password2.module').then( m => m.ForgotPassword2PageModule)
},
{
path: 'version-modal',
loadChildren: () => import('./pages/version-modal/version-modal.module').then( m => m.VersionModalPageModule)
},
{
path: 'home',
loadChildren: () => import('./pages/home/home.module').then( m => m.HomePageModule)
},
{
path: 'alteration',
loadChildren: () => import('./pages/alteration/alteration.module').then( m => m.AlterationPageModule)
},
{
path: 'jcc-wait',
loadChildren: () => import('./components-global/jcc-wait/jcc-wait.module').then( m => m.JccWaitPageModule)
},
//{
// path: '**',
// redirectTo: 'login',
// pathMatch: 'full'
//}
];
@NgModule({
imports: [
//LoginPageModule,
//TcDriverFormPageModule,
//RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
RouterModule.forRoot(routes)
],
exports: [RouterModule]
})
export class AppRoutingModule {}
Startup.cs
// 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.Use(async (context, next) =>
{
//var url = context.Request.Path.Value;
//if (url.Contains("/api/tcform/GetCurrentDate"))
//{
// // ...do your things
// context.Response.Redirect(url, permanent: false);
// return; // short circuit
//}
await next();
if (context.Response.StatusCode == 404 && !System.IO.Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
//app.UseDeveloperExceptionPage();
}
else
{
//app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.Use(async (context, next) =>
{
//var url = context.Request.Path.Value;
//if (url.Contains("/api/tcform/GetCurrentDate"))
//{
// // ...do your things
// context.Response.Redirect(url, permanent: false);
// return; // short circuit
//}
await next();
if (context.Response.StatusCode == 404 && !System.IO.Path.HasExtension(context.Request.Path.Value) &&
!context.Request.Path.Value.Contains("/api/"))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseHsts();
}
//app.UseStaticFiles();
app.UseDefaultFiles();
app.UseStaticFiles();
//app.UseDefaultFiles();
//app.UseStaticFiles(new StaticFileOptions
//{
// OnPrepareResponse = context =>
// {
// if (context.File.Name == "index.html")
// {
// context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store");
// context.Context.Response.Headers.Add("Expires", "-1");
// }
// }
//});
if (!env.IsDevelopment())
{
//app.UseMvc();
//app.UseStatusCodePagesWithReExecute("/"); // <-- added to redirect to angular
app.UseSpaStaticFiles();
}
app.UseRouting();
app.UseSession();
app.UseHttpsRedirection();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
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";
//spa.Options.StartupTimeout = new TimeSpan(0, 10, 0);
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
I just cannot figure out what is wrong...
Edit 5 : I tried { provide: LocationStrategy, useClass: HashLocationStrategy },
which adds # in my url...still the same issue.
I am close to giving up, I tried more than 100 things and nothing worked.
Edit 6 : I found the issue finally. The answer is in this post Angular + .Net Core - Production only routing problem when calling API from a browser
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论