Angular Client
In Angular werden die Daten zum Server gesendet mit einem http.post oder http.put
this.http.post(this.url_Api_Base + "/" + ID , dataset ) |
Asp.Net Server: Web API
Im Asp.Net Core Server serden die Daten empfangen in einer httpPost Methode
[HttpPost("{id}")] public async Task<ActionResult> PostTimeRecord(int id, TimeRecord client_TimeRecord) { process data .. } |
Die Daten werden gesendet in einem unter Angular abliegenen Datenformat.
Allerdings sollte zu beachten sein, dass Angular Datenformate nicht so ernst nimmt wie C# Classen.
Angular Datenmodel
export interface TimeRecord {
idtimeRecord: number; iduserguid: String; project: String; activity: String; dtStart: Date; dtEnd: Date; PauseTime: number; DrivingTime: number; dtedit: Date; }
export interface TimeRecordApi { items: TimeRecord[]; total_count: number; }
|
Asp.Net Core Web API
Daten im ankommenden Web-Request
Die Daten kommen im Web Api wie folgt an
Name |
Value |
|
Type |
|
client_TimeRecord |
{APITimerecord.Models.TimeRecord} |
|
APITimerecord.Models.TimeRecord |
|
Activity |
"Daten mit HttpClient laden 4" |
|
string |
|
DrivingTime |
null |
|
float? |
|
DtEdit |
null |
|
System.DateTime? |
|
DtEnd |
{21.01.2021 15:03:00} |
|
System.DateTime? |
|
DtStart |
{21.01.2021 07:10:00} |
|
System.DateTime? |
|
IdtimeRecord |
2 |
|
int |
|
IduserGuid |
null |
|
string |
|
PauseTime |
null |
|
float? |
|
Project |
"Angular" |
|
string |
Angular send Daten
Angular Frontend: beim Click auf einen Button wird die httpPost Methode angesteuert.
save_create({ value, valid }) { if (valid) {
this.set_Dataset(); //set local Data to Dataset
this.timerecordsService.update_create_Dataset(this.idtimeRecord,this.timeRecord).subscribe(res => { if (this.sError_Message == 'Error when saving on server') { this.isHttpError = true; setTimeout(function() { this.errorMsg = false; });//.bind(this), 2000); } else { this.isHttpError = false; setTimeout(function() { this.successMsg = false; }); //.bind(this), 2000);
//this.load_DataSource(); //refresh Data from server } }); } else { console.log('Form is not valid.'); } } |
Und die http Sende Funktion ist:
update_create_Dataset(ID : number, dataset: TimeRecord) {
return this.http .post(this.url_Api_Base + "/" + ID , dataset ) }
|
Asp.Net Core Web Api
Upload Methode zum Speichern oder neu erstellen eines Datensatzes
Im Asp.Net Core Server werden die Daten unter httpPost entgegen genommen.
Hier wird die Post=Create Methode gleichzeitig verwendet mit der PUT=Update Methode.
Dabei wird nur überprüft, ob eine ID vorhanden ist
Asp.Net Core Controller Code:
httpPost = Create and Update
//POST: api/TimeRecords [HttpPost("{id}")] public async Task<ActionResult> PostTimeRecord(int id, TimeRecord client_TimeRecord) { // -------------< POST(): New or Update > ------------- //< check > if (client_TimeRecord == null) return BadRequest(); //</ check >
//< check id > int client_IDTimeRecord; if(id >0) { client_IDTimeRecord = System.Convert.ToInt32(client_TimeRecord.IdtimeRecord); if (id != client_IDTimeRecord) return BadRequest(); } //</ check id >
//< get Database Record > TimeRecord timeRecord; if ( id == 0 ) { timeRecord = new TimeRecord(); } else { timeRecord = await _context.TimeRecords.FirstOrDefaultAsync(rec => rec.IdtimeRecord == id); if (timeRecord == null) { return BadRequest("NoMatch for ID=" + id); } } //</ get Database Record >
//--< data >-- timeRecord.Project= client_TimeRecord.Project; timeRecord.Activity = client_TimeRecord.Activity; timeRecord.DtStart = client_TimeRecord.DtStart; timeRecord.DtEnd = client_TimeRecord.DtEnd; timeRecord.PauseTime = client_TimeRecord.PauseTime; timeRecord.DrivingTime = client_TimeRecord.DrivingTime; timeRecord.DtEdit = DateTime.Now; //--</ data >--
//--< Save >-- try { if (id > 0) { //< update Server > _context.Update(timeRecord); //</ update Server > } else { //< Add on Server > _context.TimeRecords.Add(timeRecord); _context.SaveChanges(); id = timeRecord.IdtimeRecord; //</ Add on Server > } //await _dbContext.SaveChangesAsync(true); } catch (DbUpdateConcurrencyException) { return BadRequest("Error in saving id=" + id); } //--</ Save >--
//< Output > return Ok(id); //</ Output > // -------------</ POST(): New or Update > ------------- }
|
http webclient
.service.ts
import { Injectable } from '@angular/core'; import { HttpClient } from "@angular/common/http"; import { BehaviorSubject, Observable } from 'rxjs'; import { catchError, map, startWith, switchMap } from 'rxjs/operators'; import { TimeRecord } from '../models/timerecords.model'; import { identifierModuleUrl } from '@angular/compiler';
@Injectable({ providedIn: 'root' }) export class TimerecordsService {
private url_Api_Base : string = "https://localhost:44388/api/TimeRecords";
resultsLength = 0; isLoadingResults = true; isRateLimitReached = false;
constructor(private http: HttpClient) { }
//----< get_Data_List >---- //*read web-API : entire List top20 get_Data_List(): Observable<TimeRecord[]> {
return this.http .get<TimeRecord[]>(this.url_Api_Base) .pipe( map((response: TimeRecord[]) => { return response; } ) ) } //----</ get_Data_List >----
//----< get_Dateset >---- //*read 1 Dataset from web-API get_Dataset(ID : number): Observable<TimeRecord> {
return this.http .get<TimeRecord>(this.url_Api_Base + "/" + ID ) .pipe( map((response: TimeRecord) => { return response; } ) ) } //----</ get_Dateset >----
//----< get_Dateset >---- //*read 1 Dataset from web-API update_create_Dataset(ID : number, dataset: TimeRecord) {
return this.http .post(this.url_Api_Base + "/" + ID , dataset ) } //----</ get_Dateset >----
}
|
Component.ts
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { NgForm } from '@angular/forms'; import { TimeRecord } from 'src/app/models/timerecords.model'; import { TimerecordsService } from 'src/app/services/timerecords.service'; import { merge, of as observableOf } from 'rxjs'; import { catchError, startWith, switchMap } from 'rxjs/operators';
@Component({ selector: 'app-edit-timerecord', templateUrl: './edit-timerecord.component.html', styleUrls: ['./edit-timerecord.component.css'] })
export class EditTimerecordComponent implements OnInit, OnDestroy { //*get form reference in .html @ViewChild('f', { static: false }) inputForm: NgForm;
//*data public timeRecord: TimeRecord;
//--< mapping >-- idtimeRecord: number; //*map to idtimeRecord iduserguid: String; project: String; activity: String; dtStart: Date; //*2021-01-20T08:00:00 Json, ISO Dates (Date-Time) dtEnd: Date; DrivingTime: number; PauseTime: number; sDateStart: String; sTimeStart: String; sTimeEnd: String; sTimeDriving: String; sTimePause: String; sDuration: String dtEdit: Date; //--</ mapping >--
//< variables > public resultsLength = 0; public isLoadingResults = true; public isHttpError = false; public sError_Message="Web Data error or http request error"; //</ variables >
// public color: ThemePalette = 'primary'; // public mode: ProgressSpinnerMode = 'indeterminate';
constructor( public timerecordsService: TimerecordsService, private route: ActivatedRoute, //*get ID ) { }
ngOnInit(): void { //--------< ngOnInit() >-------- this.route.params.subscribe(params => { //< get ID > //*get ID from URL like timerecords/1 this.idtimeRecord = +params['id']; // (+) converts string 'id' to a number console.log(this.idtimeRecord); //</ get ID >
//< get Dataset > this.load_DataSource(); //</ get Dataset >
}); //--------</ ngOnInit() >-------- }
ngOnDestroy() { }
//#region //====< functions >==== load_DataSource() { //--------< load_DataSource() >-------- .. //--------</ load_DataSource() >-------- }
save_create({ value, valid }) { if (valid) {
this.set_Dataset(); //set local Data to Dataset
this.timerecordsService.update_create_Dataset(this.idtimeRecord,this.timeRecord).subscribe(res => { if (this.sError_Message == 'Error when saving on server') { this.isHttpError = true; setTimeout(function() { this.errorMsg = false; });//.bind(this), 2000); } else { this.isHttpError = false; setTimeout(function() { this.successMsg = false; }); //.bind(this), 2000);
//this.load_DataSource(); //refresh Data from server } }); } else { console.log('Form is not valid.'); } }
map_Data() { //--------< map_Data() >-------- //*map Recordset to local variables console.log("timerecord=" + this.timeRecord); this.idtimeRecord = this.timeRecord.idtimeRecord; this.iduserguid = this.timeRecord.iduserguid; this.project = this.timeRecord.project; this.activity = this.timeRecord.activity; this.dtStart = new Date(this.timeRecord.dtStart); // this.dtEnd = new Date(this.timeRecord.dtEnd); //console.log("dtStart=" + this.dtStart.toString()); console.log("dtEnd=" + this.dtEnd.toString());
//< convert iso Date > //*convert Iso-Date-Time to Javascript Date: 2021-01-20T08:00:00 this.sDateStart = this.get_Date_String_from_Date(this.dtStart); this.sTimeStart = this.get_Time_String_from_Date(this.dtStart); this.sTimeEnd = this.get_Time_String_from_Date(this.dtEnd); this.sTimeDriving = this.get_Time_String_from_Float(this.DrivingTime); this.sTimePause = this.get_Time_String_from_Float(this.PauseTime); this.calculate_Duration(); //</ convert iso Date >
this.idtimeRecord = this.timeRecord.idtimeRecord; //--------</ map_Data() >-------- }
set_Dataset() { //--------< set_Dataset() >-------- //*map Recordset to local variables console.log("set_dataset:"); this.timeRecord.project=this.project; this.timeRecord.activity=this.activity; this.timeRecord.dtStart=this.dtStart; this.timeRecord.dtEnd=this.dtEnd; //--------</ set_Dataset() >-------- }
onInput_Change($event) { //--------< onInput_Change() >-------- //*Create a Date from ISO String //*String "2021-01-20" + "T" + "08:00:00" this.dtStart = new Date(this.sDateStart + "T" + this.sTimeStart + ":00"); this.dtEnd = new Date(this.sDateStart + "T" + this.sTimeEnd + ":00"); this.DrivingTime = this.get_DecimalNumber_from_Time_String(this.sTimeDriving); this.PauseTime = this.get_DecimalNumber_from_Time_String(this.sTimePause);
this.calculate_Duration(); //--------</ onInput_Change() >-------- }
|
Component.html
<div class="alert alert-success" *ngIf="isHttpError"> <p>{{ sError_Message }}</p> </div> <h4 class="page-title">Edit ID: {{ idtimeRecord }} </h4>
<style> div { margin: 4px; padding: 4px; /* background-color: #eeeeee; */ width: 600px; }
p { color: blue; }
::ng-deep .mat-focused .mat-form-field-label { /*change color of label*/ color: rgb(253, 250, 244) !important; }
::ng-deep.mat-form-field-underline { /*change color of underline*/ background-color: green !important; }
::ng-deep.mat-form-field-ripple { /*change color of underline when focused*/ background-color: green !important; ; } </style>
<form novalidate #f="ngForm" style="background-color: rgb(65, 109, 109);" (ngSubmit)="save_create(f)"> <div> <mat-form-field style="width: 300px;"> <mat-label>project</mat-label> <input type="text" name="ctlproject" matInput [(ngModel)]="project" maxlength="50"> </mat-form-field> </div> <div> <mat-form-field style="width: 500px;"> <mat-label>details</mat-label> <input type="text" name="ctldetails" matInput [(ngModel)]="activity" maxlength="255"> </mat-form-field> </div> <div> <mat-form-field style="width:150px;"> <mat-label>Date</mat-label> <input type="date" name="ctlsDateStart" matInput [(ngModel)]="sDateStart" > </mat-form-field> <mat-form-field style="width: 100px;"> <mat-label>Start</mat-label> <input type="time" name="ctlsTimeStart" matInput [(ngModel)]="sTimeStart" (change)="onInput_Change($event)"> </mat-form-field> <mat-form-field style="width: 100px;"> <mat-label>End</mat-label> <input type="time" name="ctlsTimeEnd" matInput [(ngModel)]="sTimeEnd" (change)="onInput_Change($event)"> </mat-form-field>
<mat-form-field style="width: 100px;"> <mat-label>+Driving</mat-label> <input type="time" name="ctlsDrivingTime" matInput [(ngModel)]="sTimeDriving" (change)="onInput_Change($event)"> </mat-form-field> <mat-form-field style="width: 100px;"> <mat-label>-Pause</mat-label> <input type="time" name="ctlsTimePause" matInput [(ngModel)]="sTimePause" (change)="onInput_Change($event)"> </mat-form-field>
<mat-form-field style="width: 100px;"> <mat-label>=Duration</mat-label> <input disabled type="time" name="ctlsDuration" matInput [(ngModel)]="sDuration" style="background-color: transparent;"> </mat-form-field> </div> <div class="form-group"> <button class="btn mat-raised-button btn-primary" [disabled]="!f.valid" >Save</button> </div> </form>
|