I am following this book, "ASP.Net Core 6 and Angular".
The author has a IsValidProperty() method in a C# class called ApiResult.cs. This is a generic class so we can use the ApiResult class with both types of data in the application so far: City, and Country.
This is the method code:
public static bool IsValidProperty(
string PropertyName,
bool throwExceptionIfNotFound = true)
{
var prop = typeof(T).GetProperty(
PropertyName,
BindingFlags.IgnoreCase |
BindingFlags.Public |
BindingFlags.Instance);
if (prop == null && throwExceptionIfNotFound)
throw new NotSupportedException(
String.Format(
$"ERROR: Property '{PropertyName}' does not exist.")
);
return prop != null;
}
When I navigate to the Countries Edit page, type T is Country.
This is the Country Entity Framework class:
[Table("Countries")]
[Index(nameof(Name))]
[Index(nameof(IS02))]
[Index(nameof(IS03))]
public class Country
{
[Key]
[Required]
public int Id { get; set; }
public string Name { get; set; } = null!;
[JsonPropertyName("iso2")]
public string IS02 { get; set; } = null!;
[JsonPropertyName("iso3")]
public string IS03 { get; set; } = null!;
public ICollection<City>? Cities { get; set; } = null!;
When the PropertyName passed to IsValidProperty() is Name, it seems to pass. But PropertyName for iso2, and iso3 are returning null and so the exception
$"ERROR: Property '{PropertyName}' does not exist.")
is thrown.
I don't know why this happens. BindingFlags.IgnoreCase is on and anyway Name passes when it is passed in as name.
Could the
[JsonPropertyName("iso2")]
attributes in the Entity class have anything to do with it?
He has those on there to match the Angular interface properties for country.
This is the form group in the Angular template to edit countries:
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<!-- Name -->
<mat-form-field>
<mat-label>Name:</mat-label>
<input matInput formControlName="name" required
placeholder="Type a name" />
<mat-error *ngIf="this.form.controls['name'].errors?.['required']">
Name is required
</mat-error>
<mat-error *ngIf="this.form.controls['name'].errors?.['isDupField']">
Name already exists: please choose another.
</mat-error>
</mat-form-field>
<!-- ISO2 -->
<mat-form-field>
<mat-label>
ISO 3166-1 ALPHA-2 Country code (2 letters)
</mat-label>
<input matInput formControlName="iso2" required
placeholder="Insert the ISO2 Country code" />
<mat-error *ngIf="this.form.controls['iso2'].errors?.['required']">
ISO 3166-1 ALPHA-2 Country code is required
</mat-error>
<mat-error *ngIf="this.form.controls['iso2'].errors?.['pattern']">
ISO 3166-1 ALPHA-2 Country code requirs 2 letters.
</mat-error>
<mat-error *ngIf="this.form.controls['iso2'].errors?.['isDupField']">
This code already exists: please choose another.
</mat-error>
</mat-form-field>
.
.
.
Then the TypeScript in the component sets up the form and the validators like this:
ngOnInit(): void {
this.form = this.fb.group({
name: ['',
Validators.required,
this.isDupeField("name")
],
iso2: ['',
[
Validators.required,
Validators.pattern(/^[a-zA-Z]{2}$/)
],
this.isDupeField("iso2")
],
iso3: ['',
[
Validators.required,
Validators.pattern(/^[a-zA-Z]{3}$/)
],
this.isDupeField("iso2")
]
});
isDupeField is in the Countries API controller and looks like this:
[HttpPost]
[Route("IsDupeField")]
public bool IsDupeField(
int countryId,
string fieldName,
string fieldValue)
{
return (ApiResult<Country>.IsValidProperty(fieldName, true))
? _context.Countries.Any(
string.Format("{0} == @0 && Id != @1", fieldName),
fieldValue,
countryId)
: false;
}
So this is finally where it gets passed to the public, static, IsValidProperty() method.
Anyway "iso2" coming up from the Angular form should match the json name by case and the actual Entity property name because of the Bindings.IgnorCase.
Has anyone dealt with this before? I'm used to just building the front end in RazorPages so this is a big learning curve for me.
Aucun commentaire:
Enregistrer un commentaire