AngularJS metoda POST przekazująca dane do API C#

0

Hej,

Mam do was pytanie, od kilku dni ogarniam angulara, w którym zrobiłem pobieranie poprzez get, danych z webAPI które utworzyłem w C#. Dane pobierają się prawidłowo, wszystko jest cacy. Teraz chciałbym się zabrać na metodę post, stworzyłem w webAPI, odpowiednią funkcję, dodaje się bez problemu poprzez PostMan. Siedzę już kilka godzin, przeczytałem wiele artykułów i obejrzałem wiele tutoriali, ale nie mogę zaimplementować tego do angulara. Czy jest opcja aby dodawać te dane w jakiś inny sposób niż przez webClient i metodę post? Wszystko odbieram i chce zapisywać w JSON.

Jeśli potrzebny będzie kod to oczywiście wkleję, ale najpierw chciałbym wiedzieć czy nie ma jakieś innej metody od POST. Nie jestem jeszcze biegły na tyle w TypeScript. W C# zrobiłem stronę gdzie zaprogramowałem dodawanie rekordów do API i tam wszystko działa mi prawidłowo.

0

Najszybciej jednak będzie jak wrzucisz kod :P Pokaż, proszę, zarówno jak robisz GETa jak i POSTa

0

Poniżej kod:

GET:

Klasa showVacations:

export class ShowComponent implements OnInit {

  constructor(private httpService: HttpService) { }

  public vacations = [];
  ngOnInit() {
    this.httpService.getVacations()
    .subscribe(vacations => this.vacations = vacations );
  }

}

http.service.ts:



export class HttpService {

    constructor(private http: HttpClient) { }

    getVacations(): Observable<Array<Vacation>> {
        return this.http.get<Array<Vacation>>('https://localhost:44316/api/vacation');
    }

    addVacation(vacation: Vacation): Observable<any> {
        return this.http.post('https://localhost:44316/api/vacation', vacation);
}
}

HTML od GET:

<div id="Vtable"><h1> Vacation List</h1>
<table class="table">
  <tbody>
        <td>   Name  </td>
        <td>  Vacation start  </td>
        <td>  Vacation end  </td>
        <td> Superior  </td>
    <tr *ngFor="let vacation of vacations">
  <td>   {{vacation.userName}}  </td>
  <td>  {{vacation.vacationStart}}  </td>
  <td>  {{vacation.vacationEnd}}  </td>
  <td>  {{vacation.superior}}  </td>
    </tr>
    </tbody>
</table>
</div>

POST:

create.component.ts:

export class CreateComponent implements OnInit {
  constructor(private httpService: HttpService) { }

  vacation: FormGroup;
  objVacation: Vacation;

  ngOnInit() {

  }
  onSubmit() {
    this.mapFormVacation();
    this.httpService.addVacation(this.objVacation)
    .subscribe(
      data => console.log('Success!', data)
    );
  }
    mapFormVacation() {
      this.objVacation.userName = this.vacation.value.userName;
      this.objVacation.vacationStart = this.vacation.value.vacationStart;
      this.objVacation.vacationEnd = this.vacation.value.vacationEnd;
      this.objVacation.superior = this.vacation.value.superior;
    }


}

HTML od POST:

<form #vacationForm="ngForm" (ngSubmit)="onSubmit()" novalidate>
    <h1>New vacation</h1>
    <div class="form-group">
        <div class="col-sm-12">
            <label for="userName">Name</label>
            <input name="userName" 
            type="text" 
            class="form-control" 
            id="userName" 
            placeholder="Name" 
            formControlName="userName"
            [(ngModel)]="userName"          
            >
            <BR>
        </div>
        <div class="col-sm-12">
                <label for="vacationS">Vacation Start</label>
                <input name="vacationStart"
                type="text" 
                class="form-control" 
                id="vacationS" 
                placeholder="Vacation Start" 
                formControlName="vacationStart"
                [(ngModel)]="vacationStart"    
                >
            </div>
            <div class="col-sm-12">
                    <label for="vacationE">Vacation End</label>
                    <input name="vacationEnd"
                    type="text" 
                    class="form-control" 
                    id="vacationE" 
                    placeholder="Vacation End" 
                    formControlName="vacationEnd"
                    [(ngModel)]="vacationEnd"    
                    >
                </div>
                <div class="col-sm-12">
                        <label for="superior">Superior</label>
                        <input name="superior"
                        type="text" 
                        class="form-control" 
                        id="superior" 
                        placeholder="Superior" 
                        formControlName="superior"
                        [(ngModel)]="superior"    
                        >
                    </div>          
    </div>
    <div>
        <button type="submit" class="submitButton">Submit</button>
    </div>
</form>

Service ten sam co w GET.

0

I dostaje wtedy:

screenshot-20190813121013.png

na pewno coś robię źle, tylko nie wiem co... Pomożecie?

0

Zmyliłeś trochę z tym angularJS w nazwie :P Zdebugguj sobie najpierw funkcję mapFormVacation i zobacz co tam masz za wartości bo tam ewidentnie coś nie gra.
No i dlaczego masz this.vacation.value.userName ? Do wartości kontrolki w formie lepiej się tak odwołać:

this.vacation.get('userName').value
0

Teraz dostaje:

screenshot-20190813124457.png

Czy mam coś źle zdefiniowane w HTML? Że nie czyta wartości z input?

Zapewne jest tam jakiś banał, ale poziom mojego doświadczenia z TypeScript i ogólnie z angularem to zaledwie 5 dni...

0

No trochę pomieszałeś w formach - ale nie ma co się dziwić, bo to jest chyba najcięższy temat (jak dla mnie). Pomieszałeś trochę dwa sposoby budowania formów - template driven forms i reactive forms. Jeżeli w html'u użyłeś

#vacationForm="ngForm"

to przekaż sobie go w ten sposób:

(ngSubmit)="onSubmit(vacationForm.value)"

i odbierz po stronie ts:

  onSubmit(form) {
    this.mapFormVacation(form);
    this.httpService.addVacation(this.objVacation)
    .subscribe(
      data => console.log('Success!', data)
    );
  }

zobacz jak wygląda obiekt form i poprzepisuj to w tej funkcji mapFormVacation.

@Edit aaa, no i z htmla wywal FormControlName , a w ts vacation: FormGroup; - to jest używane w reactive forms a w tym przypadku łatwiej przerobić to na template driven.

Zajrzyj tutaj, może trochę Ci to objaśni -> http://www.angular.love/2017/01/29/angular-2-template-driven-forms/

0
  1. Nic dziwnego, że dostajesz error skoro nie utworzyłeś nigdzie obiektu FormGroup a chcesz z niego wyciągać wartości.
    W twoim wypadku this.vacation === undefined.
  2. Zmiksowałeś dwa rozwiązania to nie zadziała
export class CreateComponent implements OnInit {
  constructor(private httpService: HttpService,  private formBuilder: FormBuilder) { }

  vacation: FormGroup;
  objVacation: Vacation;

  ngOnInit() {
    this.vacation = this.formBuilder.group({
      userName: [''],
      vacationStart:[''],
      vacationEnd:[''],
      superior:['']
    })
  }
  onSubmit() {
    this.mapFormVacation();
    this.httpService.addVacation(this.objVacation)
    .subscribe(
      data => console.log('Success!', data)
    );
  }
    mapFormVacation() {
      this.objVacation.userName = this.vacation.value.userName;
      this.objVacation.vacationStart = this.vacation.value.vacationStart;
      this.objVacation.vacationEnd = this.vacation.value.vacationEnd;
      this.objVacation.superior = this.vacation.value.superior;
    }

}
<form [formGroup]="vacation" (submit)="onSubmit()" novalidate>
    <h1>New vacation</h1>
    <div class="form-group">
        <div class="col-sm-12">
            <label for="userName">Name</label>
            <input name="userName" 
            type="text" 
            class="form-control" 
            id="userName" 
            placeholder="Name" 
            formControlName="userName"         
            >
            <BR>
        </div>
        <div class="col-sm-12">
                <label for="vacationS">Vacation Start</label>
                <input name="vacationStart"
                type="text" 
                class="form-control" 
                id="vacationS" 
                placeholder="Vacation Start" 
                formControlName="vacationStart"
                >
            </div>
            <div class="col-sm-12">
                    <label for="vacationE">Vacation End</label>
                    <input name="vacationEnd"
                    type="text" 
                    class="form-control" 
                    id="vacationE" 
                    placeholder="Vacation End" 
                    formControlName="vacationEnd"
                    >
                </div>
                <div class="col-sm-12">
                        <label for="superior">Superior</label>
                        <input name="superior"
                        type="text" 
                        class="form-control" 
                        id="superior" 
                        placeholder="Superior" 
                        formControlName="superior"
                        >
                    </div>          
    </div>
    <div>
        <button type="submit" class="submitButton">Submit</button>
    </div>
</form>
0

Do consoli działa bez zarzutów, potem odkomentowałem fragment kodu który zostawiłeś i:

screenshot-20190813140502.png

0

I co xD. To co ci się wyświetla to jest błąd formatowania lini.

0

Dobra dzięki, nareszcie inny error :D

screenshot-20190813141728.png

Zaraz spróbuję to sam ogarnąć. Dziękuje bardzo za pomoc!

0

Zastanawia mnie jedno, przez PostMana nie wywala kompletnie żadnego błędu przy wysyłaniu POST, a jak to robię tak jak poniżej... :

http.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Vacation } from '../vacation/vacations';
import { Observable } from 'rxjs';

@Injectable()
export class HttpService {

    constructor(private http: HttpClient) { }

    getVacations(): Observable<Array<Vacation>> {
        return this.http.get<Array<Vacation>>('https://localhost:44316/api/vacation');
    }

    addVacation(vacation: Vacation): Observable<any> {
        return this.http.post<Vacation>('https://localhost:44316/api/vacation', JSON.stringify(vacation), {
            headers: new HttpHeaders().append('Content-Type', 'application/json')});
}

}

Create.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpService } from '../config/http.service';
import { Vacation } from './vacations';
import { FormGroup, FormBuilder } from '@angular/forms';
import { VirtualTimeScheduler } from 'rxjs';

@Component({
  selector: 'app-create',
  templateUrl: './create.component.html',
  styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit  {
  constructor(private httpService: HttpService,  private formBuilder: FormBuilder) { }

  vacation: FormGroup;
  objVacation: Vacation;

  ngOnInit() {
    this.vacation = this.formBuilder.group({
      userName: [''],
      vacationStart: [''],
      vacationEnd: [''],
      superior: ['']
    });
  }
  onSubmit() {
    console.log(this.vacation);
    console.log(this.vacation.value);
    console.log(this.vacation.value.userName);
    console.log(this.vacation.getRawValue());
    this.httpService.addVacation(this.objVacation)
     .subscribe(
       data => {
        this.objVacation = data;
       }
     );
  }
}

HTML

<form [formGroup]="vacation" (ngSubmit)="onSubmit()" novalidate>
    <h1>New vacation</h1>
    <div class="form-group">
        <div class="col-sm-12">
            <label for="userName">Name</label>
            <input name="userName" 
            type="text" 
            class="form-control" 
            id="userName" 
            placeholder="Name" 
            formControlName="userName"         
            >
            <BR>
        </div>
        <div class="col-sm-12">
                <label for="vacationS">Vacation Start</label>
                <input name="vacationStart"
                type="text" 
                class="form-control" 
                id="vacationS" 
                placeholder="Vacation Start" 
                formControlName="vacationStart"
                >
            </div>
            <div class="col-sm-12">
                    <label for="vacationE">Vacation End</label>
                    <input name="vacationEnd"
                    type="text" 
                    class="form-control" 
                    id="vacationE" 
                    placeholder="Vacation End" 
                    formControlName="vacationEnd"
                    >
                </div>
                <div class="col-sm-12">
                        <label for="superior">Superior</label>
                        <input name="superior"
                        type="text" 
                        class="form-control" 
                        id="superior" 
                        placeholder="Superior" 
                        formControlName="superior"
                        >
                    </div>          
    </div>
    <div>
        <button class="submitButton">Submit</button>
    </div>
</form>

C# webAPI:
Controller:

    public class vacationController : ApiController
    {
        public IEnumerable<vacation> Get()
        {
            using (VacationsDBEntities1 entities = new VacationsDBEntities1())
            {
                return entities.vacation.ToList();
            }
        }

        public vacation Get(int id)
        {
            using (VacationsDBEntities1 entities = new VacationsDBEntities1())
            {
                return entities.vacation.FirstOrDefault(e => e.vacationID == id);
            }
        }

        public HttpResponseMessage Post([FromBody] vacation Vacation)
        {
            try
            {
                using (var entities = new VacationsDBEntities1())
                {
                    var response = entities.newVacation(Vacation.userName, Vacation.vacationStart,Vacation.vacationEnd, Vacation.superior);

                    var message = Request.CreateResponse(HttpStatusCode.Created, Vacation);
                    message.Headers.Location = new Uri(Request.RequestUri + Vacation.vacationID.ToString());
                    return message;
                }
            }
            catch (Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
            }
        }
    }
}

I dostaje błąd:

screenshot-20190813155731.png

0

Wytłumacz mi co chcesz tym osiągnąć JSON.stringify(vacation) ?
Skoro w api masz typ Vacation a nie String

0

screenshot-20190813162548.png

Zawartość typu Vacation, to chodzi Ci o klasę?

screenshot-20190813162625.png

0

No dobrze ale prosiłem jeszcze o screen z networku. Network -> zaznacz request -> Headers -> Request Payload na dole strony.
Nie znam C# ale wypisz na backendzie przed try obiekt Vacation.

0
  • zakładam po składni, że po prostu próbujesz na null'u wykonać operację o w tym miejscu.
Vacation.vacationID.ToString()
0

Nie mogę znaleźć tej opcji Request Payload

screenshot-20190813164123.png

0

Nic nie mam poniżej :(

screenshot-20190813170824.png

0

Responce czyli entities.newVacation zwraca INT = 1 :

screenshot-20190813173931.png

0

A co oznacza to "1" ?
xD @somekind może ty mu podpowiesz jak zapisać obiekt w bazie bo ja to nie ogarniam tych waszych c# konstrukcji :).

0

Dobra, sprawa była oczywiście banalna. Zrobiłem cały kod od nowa ale teraz stworzyłem bazę dla ułatwienia że daty są polami string (nchar(10)). Kiedy to skonfigurowałem w bazie danych, a następnie resztę z waszą pomocą, wszystko działa bez problemu. Jeśli ktoś potrzebuje komponentu który pobiera wartości z formularza, poniżej kod:

export class CreateComponent implements OnInit  {
  constructor(private httpService: HttpService,  private formBuilder: FormBuilder) { }

  vacation: FormGroup;
  objVacation: Vacation;

  ngOnInit() {
    this.vacation = this.formBuilder.group({
      userName: [''],
      vacationStart: [''],
      vacationEnd: [''],
      superior: ['']
    });
  }
  onSubmit() {
      const vacationData: Vacation = {
        userName: this.vacation.controls.userName.value,
        vacationStart: this.vacation.controls.vacationStart.value,
        vacationEnd: this.vacation.controls.vacationEnd.value,
        superior: this.vacation.controls.superior.value
      };
      this.httpService.addVacation(vacationData).subscribe(
      vacation => {
        console.log(vacation);
      }
    );
  }
}

Dzięki wielkie za pomoc, nie udało by mi się dojść do tego bez waszej pomocy. Teraz spróbuje to wszystko sam sobie ogarnąć z typem date.

1 użytkowników online, w tym zalogowanych: 0, gości: 1