Angular-如何忽略API进入路由?

发布于 2025-02-11 07:16:42 字数 8862 浏览 1 评论 0原文

呼叫 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调用?

编辑:尝试了许多方法到目前为止,

  1. 我的基础HREF是< base href =“/”>
  2. 尝试的哈希策略{usehash:true} < /code>

编辑2:进一步解释。我有一个.NET核心项目,该项目具有C#后端和Angular Frontend。两者都在同一项目中。 (我有我不讨论的原因,不是主题),

所以我正在做的是使用外部服务(在项目之外)中使用付款系统。我将所有要求传递给您将URL作为响应URL提供的系统。通过取消或付款,用户从该支付系统中导航后,该URL响应是在拨出付款系统后调用的。

因此,我给出url: https://www.mysite.example.example.example/api/api/jccpayment/jccpayment/jcccresponse < /a>是我项目的C#后端中的控制器方法。

现在,怪异的部分是:

  1. 在Localhost上,它总是成功地击中
  2. 生产,如果用户在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

  1. My base href is <base href="/">
  2. 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 :

  1. On localhost it always hits successfully
  2. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文