英文:
ASP.NET Core + Angular project gives me errors when I try to run it
问题
I see that you're facing some issues with your ASP.NET Core and Angular project. It appears that you're encountering Angular-related errors in your project setup.
Here's a summary of the key issues:
-
You're getting an error related to the use of
[formGroup]
in your HTML template. This might be due to the missing import of theReactiveFormsModule
in your Angular module. Ensure you import it like this:import { ReactiveFormsModule } from '@angular/forms';
And add it to the
imports
array in your module:imports: [ CommonModule, ReactiveFormsModule, ],
-
You also have an issue with the use of
loginForm
in your HTML template. Ensure that you have declared and initializedloginForm
in your component, something like this in yourlogin.component.ts
:import { FormGroup, FormBuilder, Validators } from '@angular/forms'; // Inside your LoginComponent class loginForm: FormGroup; constructor(private formBuilder: FormBuilder) { this.loginForm = this.formBuilder.group({ email: ['', Validators.required], // Example: Add your form controls here password: ['', Validators.required], }); }
-
Make sure you have imported and declared your
LoginComponent
correctly in your module. It seems that you're importingFooterComponent
instead ofLoginComponent
in yourlogin.module.ts
.Ensure that you have the correct import for
LoginComponent
and declare it in your module'sdeclarations
array.
Please check these issues, and if you encounter any specific errors or have more details to provide, feel free to share them for further assistance.
英文:
I'm trying something new and that would be using ASP.NET Core as my backend while using Angular for the frontend. While the backend was a breeze to configure, the frontend haven't been as close. When I try running the application, I receive the following errors in teh console:
> integrafechado@0.0.0 prestart
> node aspnetcore-https
> integrafechado@0.0.0 start
> run-script-os
> integrafechado@0.0.0 start:windows
> ng serve --port 44488 --ssl --ssl-cert "%APPDATA%\ASP.NET\https\%npm_package_name%.pem" --ssl-key "%APPDATA%\ASP.NET\https\%npm_package_name%.key"
Initial Chunk Files | Names | Raw Size
vendor.js | vendor | 3.03 MB |
styles.css, styles.js | styles | 440.48 kB |
polyfills.js | polyfills | 434.76 kB |
main.js | main | 181.56 kB |
runtime.js | runtime | 6.53 kB |
| Initial Total | 4.07 MB
Build at: 2023-06-12T15:15:32.894Z - Hash: bdb0de9435970ca7 - Time: 2757ms
Error: src/api-authorization/login/login.component.html:6:13 - error NG8002: Can't bind to 'formGroup' since it isn't a known property of 'form'.
6 [formGroup]="loginForm"
~~~~~~~~~~~~~~~~~~~~~~~
src/api-authorization/login/login.component.ts:16:15
16 templateUrl: "./login.component.html",
~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component LoginComponent.
Error: src/api-authorization/login/login.component.html:6:26 - error TS2339: Property 'loginForm' does not exist on type 'LoginComponent'.
6 [formGroup]="loginForm"
~~~~~~~~~
src/api-authorization/login/login.component.ts:16:15
16 templateUrl: "./login.component.html",
~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component LoginComponent.
Error: src/api-authorization/login/login.component.html:7:25 - error TS2341: Property 'login' is private and only accessible within class 'LoginComponent'.
7 (ngSubmit)="login(loginForm.value)"
~~~~~
src/api-authorization/login/login.component.ts:16:15
16 templateUrl: "./login.component.html",
~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component LoginComponent.
Error: src/api-authorization/login/login.component.html:7:31 - error TS2339: Property 'loginForm' does not exist on type 'LoginComponent'.
7 (ngSubmit)="login(loginForm.value)"
~~~~~~~~~
src/api-authorization/login/login.component.ts:16:15
16 templateUrl: "./login.component.html",
~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component LoginComponent.
Error: src/api-authorization/login/login.component.html:69:1 - error NG8001: 'app-footer' is not a known element:
1. If 'app-footer' is an Angular component, then verify that it is part of this module.
2. If 'app-footer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
69 <app-footer></app-footer>
~~~~~~~~~~~~
src/api-authorization/login/login.component.ts:16:15
16 templateUrl: "./login.component.html",
~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component LoginComponent.
** Angular Live Development Server is listening on localhost:44488, open your browser on https://localhost:44488/ **
× Failed to compile.
Here's the login.component.html file:
<div class="login-container">
<div id="container-main" class="login-container-main">
<label id="login-label" for="login-form" class="login-text">Login</label>
<div id="container-form" class="login-container-form">
<form id="login-form"
[formGroup]="loginForm"
(ngSubmit)="login(loginForm.value)"
name="login-form"
target="self"
enctype="application/x-www-form-urlencoded"
class="login-form">
<div class="login-container-labels">
<div id="email-label-div" class="login-container1">
<label id="email-label" for="email-input" class="login-text1">
E-mail
</label>
</div>
<div id="senha-label-div" class="login-container2">
<label id="password-label" for="password-input" class="login-text2">
Senha
</label>
</div>
<div id="register-div" class="login-container3">
<label id="noregister-label"
for="register-button"
class="login-text3">
Não tem conta?
</label>
<button id="register-button"
name="register-button"
type="button"
class="login-button Link button">
Registrar
</button>
</div>
</div>
<div class="login-container-inputs">
<div id="email-input-div" class="login-container4">
<input formControlName="email"
type="email"
id="email-input"
required
autofocus
placeholder="exemplo@exemplo.com"
class="input" />
</div>
<div id="senha-input-div" class="login-container5">
<input formControlName="password"
type="password"
id="password-input"
required
minlength="8"
placeholder="Sua senha"
class="input" />
</div>
<div id="login-div" class="login-container6">
<button type="submit" class="login-button1 button">
<span class="login-text4">
<span class="login-text5">Logar</span>
<br />
</span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<app-footer></app-footer>
login.module.ts:
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { FooterComponent } from "./footer.component";
@NgModule({
declarations: [
FooterComponent
],
imports: [
CommonModule
],
exports: [
FooterComponent
]
})
export class FooterModule { }
login.component.ts:
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-useless-escape */
/* eslint-disable no-case-declarations */
import { Component, OnInit } from "@angular/core";
import { AuthorizeService, AuthenticationResultStatus } from "../authorize.service";
import { ActivatedRoute, Router } from "@angular/router";
import { BehaviorSubject } from "rxjs";
import { LoginActions, QueryParameterNames, ApplicationPaths, ReturnUrlType } from "../api-authorization.constants";
// The main responsibility of this component is to handle the user's login process.
// This is the starting point for the login process. Any component that needs to authenticate
// a user can simply perform a redirect to this component with a returnUrl query parameter and
// let the component perform the login and return back to the return url.
@Component({
selector: "app-login",
templateUrl: "./login.component.html",
styleUrls: ["./login.component.css"]
})
export class LoginComponent implements OnInit {
public message = new BehaviorSubject<string | null | undefined>(null);
constructor(
private authorizeService: AuthorizeService,
private activatedRoute: ActivatedRoute,
private router: Router) { }
async ngOnInit() {
const action = this.activatedRoute.snapshot.url[1];
switch (action.path) {
case LoginActions.Login:
await this.login(this.getReturnUrl());
break;
case LoginActions.LoginCallback:
await this.processLoginCallback();
break;
case LoginActions.LoginFailed:
const message = this.activatedRoute.snapshot.queryParamMap.get(QueryParameterNames.Message);
this.message.next(message);
break;
case LoginActions.Profile:
this.redirectToProfile();
break;
case LoginActions.Register:
this.redirectToRegister();
break;
default:
throw new Error(`Invalid action '${action}'`);
}
}
private async login(returnUrl: string): Promise<void> {
const state: INavigationState = { returnUrl };
const result = await this.authorizeService.signIn(state);
this.message.next(undefined);
switch (result.status) {
case AuthenticationResultStatus.Redirect:
break;
case AuthenticationResultStatus.Success:
await this.navigateToReturnUrl(returnUrl);
break;
case AuthenticationResultStatus.Fail:
await this.router.navigate(ApplicationPaths.LoginFailedPathComponents, {
queryParams: { [QueryParameterNames.Message]: result.message }
});
break;
default:
throw new Error(`Invalid status result ${(result as any).status}.`);
}
}
private async processLoginCallback(): Promise<void> {
const url = window.location.href;
const result = await this.authorizeService.completeSignIn(url);
switch (result.status) {
case AuthenticationResultStatus.Redirect:
// There should not be any redirects as completeSignIn never redirects.
throw new Error("Should not redirect.");
case AuthenticationResultStatus.Success:
await this.navigateToReturnUrl(this.getReturnUrl(result.state));
break;
case AuthenticationResultStatus.Fail:
this.message.next(result.message);
break;
}
}
private redirectToRegister(): any {
this.redirectToApiAuthorizationPath(
`${ApplicationPaths.IdentityRegisterPath}?returnUrl=${encodeURI("/" + ApplicationPaths.Login)}`);
}
private redirectToProfile(): void {
this.redirectToApiAuthorizationPath(ApplicationPaths.IdentityManagePath);
}
private async navigateToReturnUrl(returnUrl: string) {
// It's important that we do a replace here so that we remove the callback uri with the
// fragment containing the tokens from the browser history.
await this.router.navigateByUrl(returnUrl, {
replaceUrl: true
});
}
private getReturnUrl(state?: INavigationState): string {
const fromQuery = (this.activatedRoute.snapshot.queryParams as INavigationState).returnUrl;
// If the url is coming from the query string, check that is either
// a relative url or an absolute url
if (fromQuery &&
!(fromQuery.startsWith(`${window.location.origin}/`) ||
/\/[^\/].*/.test(fromQuery))) {
// This is an extra check to prevent open redirects.
throw new Error("Invalid return url. The return url needs to have the same origin as the current page.");
}
return (state && state.returnUrl) ||
fromQuery ||
ApplicationPaths.DefaultLoginRedirectPath;
}
private redirectToApiAuthorizationPath(apiAuthorizationPath: string) {
// It's important that we do a replace here so that when the user hits the back arrow on the
// browser they get sent back to where it was on the app instead of to an endpoint on this
// component.
const redirectUrl = `${window.location.origin}/${apiAuthorizationPath}`;
window.location.replace(redirectUrl);
}
}
interface INavigationState {
[ReturnUrlType]: string;
}
and finally, footer.module.ts:
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { FooterComponent } from "./footer.component";
@NgModule({
declarations: [
FooterComponent
],
imports: [
CommonModule
],
exports: [
FooterComponent
]
})
export class FooterModule { }
I'm not completely sure about what is right or wrong, VS2022 creates the new project with the base for authentication in a folder called api-authorization, but I tried using Angular's forms, although ASP.NET Core handles authentication with the middlewares. As far as I've seen, you have to create the login template for the application. Is there a simpler way to use the created login html? I'd be happy to provide more details if needed
答案1
得分: 0
我告诉Jason在问题评论中,用.net6开始一个新项目解决了这个问题,但我有一种可能是我不小心删除了一些东西的感觉,所以.net的版本在这里没有任何影响。现在它能运行了。
英文:
As I've told Jason in the question comments, starting a new project with .net6 instead of .net7 solved it, but I've a feeling I might've deleted something by accident, so the version of.net makes no difference here. Now it works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论