Failed connection handshake and 500 error when refreshing page - Abp Zero with Angular and .Net Core - asp.net-core

When I log into the application, angular changes the ulr to https://baseurl/app/home and the home page renders correctly. If I refresh the page I get a server (500) error. if I remove the /app/home part in the address bar and refresh, the page reloads without issues.
In the logs on the server side I find this:
Fail: Microsoft.AspNetCore.SignalR.HubConnectionContext[5]
Failed connection handshake.
I am running the angular client and the .net core application on two different servers, and CORS is set up correctly and the client app is able to connect to the api. The app works fine except when i refresh a page with an angular route.
The problem does not occur when I run the application locally on my development machine.
I have not changed any routing or signalr related code in the original Abp Zero template.
On server:
.NetCore 2.2
Abp Zero v 4.8
services.AddSignalR() is called in the startup.cs file and
app.UseSignalR(routes =>
{
routes.MapHub("/signalr");
});
is also called in the startup.cs file from the Configuration method. All this is standard tempate code.
In Angular client:
#aspnet/signalr v 1.1.4
The unchanged SignalRAspNetCoreHelper of which the initSignalR() is called in OnInit in the app.component.ts file:
import { AppConsts } from '#shared/AppConsts';
import { UtilsService } from '#abp/utils/utils.service';
export class SignalRAspNetCoreHelper {
static initSignalR(): void {
const encryptedAuthToken = new UtilsService().getCookieValue(AppConsts.authorization.encrptedAuthTokenName);
abp.signalr = {
autoConnect: true,
connect: undefined,
hubs: undefined,
qs: AppConsts.authorization.encrptedAuthTokenName + '=' + encodeURIComponent(encryptedAuthToken),
remoteServiceBaseUrl: AppConsts.remoteServiceBaseUrl,
startConnection: undefined,
url: '/signalr'
};
jQuery.getScript(AppConsts.appBaseUrl + '/assets/abp/abp.signalr-client.js');
}
}
The app-routing.module.ts is also unchanged:
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { AppComponent } from './app.component';
import { AppRouteGuard } from '#shared/auth/auth-route-guard';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
import { UsersComponent } from './users/users.component';
import { TenantsComponent } from './tenants/tenants.component';
import { RolesComponent } from 'app/roles/roles.component';
import { ChangePasswordComponent } from './users/change-password/change-password.component';
#NgModule({
imports: [
RouterModule.forChild([
{
path: '',
component: AppComponent,
children: [
{ path: 'home', component: HomeComponent, canActivate: [AppRouteGuard] },
{ path: 'users', component: UsersComponent, data: { permission: 'Pages.Users' }, canActivate: [AppRouteGuard] },
{ path: 'roles', component: RolesComponent, data: { permission: 'Pages.Roles' }, canActivate: [AppRouteGuard] },
{ path: 'tenants', component: TenantsComponent, data: { permission: 'Pages.Tenants' }, canActivate: [AppRouteGuard] },
{ path: 'about', component: AboutComponent },
{ path: 'update-password', component: ChangePasswordComponent }
]
}
])
],
exports: [RouterModule]
})
export class AppRoutingModule { }
root-routing.module.ts (also unchanged):
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
const routes: Routes = [
{ path: '', redirectTo: '/app/home', pathMatch: 'full' },
{
path: 'account',
loadChildren: 'account/account.module#AccountModule', // Lazy load account module
data: { preload: true }
},
{
path: 'app',
loadChildren: 'app/app.module#AppModule', // Lazy load account module
data: { preload: true }
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: []
})
export class RootRoutingModule { }
Any ideas as to what is wrong? As I haven't changed anything, I wonder if the issue is with the environments/configurations?

in case anyone stumbled upon this question:
The problem does not occur when I run the application locally on my development machine.
The problem is related to the production server, the request is not being forwarded into your angular application properly
IIS
basically you need to install the url-rewrite and then configure a web.config file for the front-end site web.config configuration link 1 link 2
Apachi
link 1 link 2

Related

Vue/Vite router has /#/ which doesn't work with Oauth flow callback URL

So I'm pretty sure this is easy but I'm brand new to Vite and I haven't hit upon the right combination yet. I have all of this working in Vue-Cli 3 but would like to get it working in Vite.
I'm using Vue Router 4.0.0 and Vue 3.2.25 and Vite and Okta as my Oauth provider. I have a sign-in redirect URI in Okta of http://localhost:8080/login/callback. When I initiate my login flow it redirects to http://localhost:8080/login/callback?code=PnrOH4v4_... which resolves to my Home route of "/" and not my LoginCallback route of "/login/callback". I'm pretty sure it's the hash. I've tried various combinations of things but haven't hit the right combination yet.
Here's my router.
import { createRouter, createWebHashHistory } from "vue-router";
import { LoginCallback, navigationGuard } from "#okta/okta-vue";
import Home from "../views/Home.vue";
import User from "../views/User.vue";
import Profile from "#/components/Profile.vue";
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/login/callback",
component: LoginCallback,
},
{
path: "/user",
name: "User",
component: User,
meta: {
requiresAuth: true,
},
},
{
path: "/profile",
component: Profile,
meta: {
requiresAuth: true,
},
},
];
console.log("base = " + import.meta.env.BASE_URL);
const router = createRouter({
mode: "history",
history: createWebHashHistory(import.meta.env.BASE_URL),
hash: false,
routes,
});
router.beforeEach(navigationGuard);
export default router;
and here's my vite.config.js
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
import path from "path";
export default defineConfig({
base: "http://localhost:8080/",
server: {
port: 3030,
},
preview: {
port: 8080,
},
plugins: [vue()],
resolve: {
alias: [
{ find: "#", replacement: path.resolve(__dirname, "./src") },
{
// I got this from https://github.com/okta/okta-auth-js/issues/641
find: "#okta/okta-auth-js",
replacement: require.resolve(
"#okta/okta-auth-js/dist/okta-auth-js.umd.js"
),
},
{ find: "#config", replacement: path.resolve(__dirname, "./src/config") },
],
},
});
I believe you don't need any more alias for replacing "#okta/okta-auth-js" with "#okta/okta-auth-js/dist/okta-auth-js.umd.js" since this issue was fixed in the newest version of Okta Vue SDK.
Since 5.x version you need to install #okta/okta-auth-js as dependency. Here you can find more information about migration.

Refresh token feature

how can i make refresh token feature work?
I don't see refresh token in local storage, and it is because core doesn't have it in storemodule config
export function authStoreConfigFactory(): StateConfig {
// if we want to reuse AUTH_FEATURE const in config, we have to use factory instead of plain object
const config: StateConfig = {
state: {
storageSync: {
keys: {
'auth.userToken.token.access_token': StorageSyncType.LOCAL_STORAGE,
'auth.userToken.token.token_type': StorageSyncType.LOCAL_STORAGE,
'auth.userToken.token.expires_in': StorageSyncType.LOCAL_STORAGE,
'auth.userToken.token.expiration_time': StorageSyncType.LOCAL_STORAGE,
'auth.userToken.token.scope': StorageSyncType.LOCAL_STORAGE,
'auth.userToken.token.userId': StorageSyncType.LOCAL_STORAGE,
},
},
},
};
return config;
}
What is the correct way to use it?
Refresh token was deliberately omitted in default storage synchronization configuration for security reasons.
However, if you need that you can always provide your own storage synchronization configuration like in the example below. It will not override default configuration, but it will be combined with it. To exclude something from default configuration you can use excludeKeys similarly to keys property in storageSync configuration.
import { NgModule } from "#angular/core";
import { BrowserModule } from "#angular/platform-browser";
import { translationChunksConfig, translations } from "#spartacus/assets";
import { ConfigModule, StateConfig, StorageSyncType } from "#spartacus/core";
import { B2cStorefrontModule } from "#spartacus/storefront";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
export function refreshTokenConfigFactory(): StateConfig {
const config: StateConfig = {
state: {
storageSync: {
keys: {
"auth.userToken.token.refresh_token": StorageSyncType.LOCAL_STORAGE
}
}
}
};
return config;
}
#NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
B2cStorefrontModule.withConfig({
backend: {
occ: {
baseUrl: "http://localhost:9002",
prefix: "/rest/v2/"
}
},
context: {
baseSite: ["electronics-spa"]
},
i18n: {
resources: translations,
chunks: translationChunksConfig,
fallbackLang: "en"
},
features: {
level: "1.5",
anonymousConsents: true
}
}),
ConfigModule.withConfigFactory(refreshTokenConfigFactory),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}

import Routes [ts] 'types' can only be used in a .ts file.While they are already in app.module.ts

Here is part of my code along with error showing.While build is successfully created.As for your information I am developing a MEAN Stack application which evolve use of Angular 5 as it's ui component.
Here are code and error
import { AppComponent } from './app.component';
import { BookComponent } from './book/book.component';
import { FormsModule } from '#angular/forms';
import { HttpClientModule } from '#angular/common/http';
import { RouterModule, Routes } from '#angular/router';
const appRoutes : Routes = [
{
path: 'books',
component: BookComponent,
data: { title: 'Book List' }
},
{ path: '',
redirectTo: '/books',
pathMatch: 'full'
}
];
#NgModule({
declarations: [
AppComponent,
BookComponent
],
imports: [
BrowserModule,
HttpClientModule,FormsModule,RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
As you can see I have import the Routermodule && Routes.
Please see the pic which shows visual studio editor commiting reponse .
I am almost surprised because Angular use AOT compilation which fails here.Could you please try ?

Angular 6 No NgModule metadata found for 'myModule'

It looks like problem with my 'lazy loading'
When I'm trying ng serve, I got this error:
ERROR in No NgModule metadata found for 'ModuleA'.
And compilation is waiting. Then if I edit and save file modulea.module.ts it works. But this trick doesn't work with ng build (there is now 'watch' mode) I hope you know what I'm talking about :D
So how can I fix it?
My folders structure:
src/
app/
views/
moduleA/
componenets/
modulea.module.ts
modulea-routing.module.ts
moduleB/
componenets/
moduleb.module.ts
moduleb-routing.module.ts
... app components etc
app.module.ts
app.routing.ts
My app routing
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
export const routes: Routes = [
{
path: 'modulea',
children: [
{
path: '',
loadChildren: './views/moduleA/modulea.module#ModuleAModule'
},
]
},
{
path: 'moduleb',
children: [
{
path: '',
loadChildren: './views/moduleB/moduleb.module#ModuleBModule'
},
]
},
];
Module A:
import { NgModule } from '#angular/core';
import { ModuleARouting } from './modulea-routing.module';
#NgModule({
imports: [
ModuleARouting
],
})
export class ModuleAModule { }
Module B:
import { NgModule } from '#angular/core';
import { ModuleBRouting } from './moduleb-routing.module';
#NgModule({
imports: [
ModuleBRouting
],
})
export class ModuleBModule { }
Module A and B routing files loading another module:
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
const routes: Routes = [
{
path: '',
data: {
title: 'ModuleA'
},
children: [
{
path: '',
redirectTo: 'module-a-a'
},
{
path: 'module-a-a',
loadChildren: './components/module-a-a.module#ModuleAAModule'
},
]
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ModuleARouting {}
And finally ModuleAA loads components
EDIT
I can edit any file (when compile is fail and waiting) to pass it done.
I had the same issue and was and error on module name . So check all names , routing names, component names and module names of the module that the error is happening.

Angular 2 error after authentication - Cannot find primary outlet to load

I have an error in console after authentication. After reload page CreateChartComponent page start working. Error just happen in authentication process.
Uncaught (in promise): Error: Cannot find primary outlet to load 'CreateChartComponent'
This is the login function.
login(event, username, password): void {
event.preventDefault();
this.authService.login(username, password).subscribe(
res => {
this.router.navigate(['drawing']);
},
err => {
// todo: handle error with a lable
console.log(err);
if (err.ok === false) {
this.errorMessage = 'Error logging in.';
}
});
}
}
Aditional information:
I send clear mode of code where I get same issue.
It's Router code:
// Import our dependencies
import { Routes } from '#angular/router';
import { AppComponent } from './app.component';
import { LoginComponent } from './home/login/login.component';
import { CreateChartComponent } from './home/drawing/create-chart.component';
import { AuthGuard } from './auth.guard';
// Define which component should be loaded based on the current URL
export const routes: Routes = [
{ path: '', component: CreateChartComponent, pathMatch: 'full', canActivate: [AuthGuard] },
{ path: 'login', component: LoginComponent },
{ path: 'drawing', component: CreateChartComponent, canActivate: [AuthGuard] },
];
and its create-chart.component.ts
import {
Component,
OnInit,
} from '#angular/core';
#Component({
selector: 'np-chart-create',
templateUrl: './create-chart.component.html',
styleUrls: ['./create-chart.component.css']
})
export class CreateChartComponent implements OnInit {
ngOnInit() {
}
}