AngularJS metoda POST przekazująca dane do API C#

AngularJS metoda POST przekazująca dane do API C#
K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
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.

Chramar
  • Rejestracja:około 7 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Poznań
  • Postów:46
0

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

K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
0

Poniżej kod:

GET:

Klasa showVacations:

Kopiuj
export class ShowComponent implements OnInit {

  constructor(private httpService: HttpService) { }

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

}

http.service.ts:

Kopiuj


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:

Kopiuj
<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:

Kopiuj
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:

Kopiuj
<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.

edytowany 1x, ostatnio: kain555
K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
0

I dostaje wtedy:

screenshot-20190813121013.png

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

Kondziowsky
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 2 lata
  • Postów:219
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ć:

Kopiuj
this.vacation.get('userName').value
edytowany 2x, ostatnio: Kondziowsky
K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
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...

edytowany 1x, ostatnio: kain555
Kondziowsky
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 2 lata
  • Postów:219
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ś

Kopiuj
#vacationForm="ngForm"

to przekaż sobie go w ten sposób:

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

i odbierz po stronie ts:

Kopiuj
  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/

edytowany 3x, ostatnio: Kondziowsky
Schadoow
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Postów:1068
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
Kopiuj
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;
    }

}
Kopiuj
<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>
Zobacz pozostałe 3 komentarze
K5
Ok, do console.log działa, teraz dodałem kod od "onSubmit()" i "mapFormVacation()" który podałeś wcześniej i nadal nic :(
Schadoow
Co to znaczy nic? https://stackblitz.com/edit/angular-qvan62 dodałem parę consol.log'ow abyś obczaił jakie tam są obiekty w środku.
K5
Nie no, do logów wszystko ładnie się przekazuje, ale baza danych nadal pusta
Schadoow
No to już nie jest kwestia formularza tylko tego co dodaje do bazy :)
Schadoow
sprawdź swoje rest api
K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
0

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

screenshot-20190813140502.png

edytowany 1x, ostatnio: kain555
Kondziowsky
łap tutaj -> https://stackblitz.com/edit/angular-26dn2q?file=src%2Fapp%2Fapp.component.html można to zrobić w ten sposób (zobacz konsolę). Tutaj dodałem swoją klasę Vacation w .ts, Ty pewnie ją zaciągasz z pliku (domyślnie u siebie rozumiem masz jakieś inicjujące wartości - u mnie jest to pusty string '')
Schadoow
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Postów:1068
0

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

K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
0

Dobra dzięki, nareszcie inny error :D

screenshot-20190813141728.png

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

K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
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

Kopiuj
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

Kopiuj
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

Kopiuj
<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:

Kopiuj
    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

Schadoow
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Postów:1068
0

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

edytowany 1x, ostatnio: Schadoow
K5
Po prostu próbowałem już na 100 sposobów. Oczywiście próbowałem z samym vacation ale ten sam efekt. Z tego co ustaliłem to błąd 400 jest od złego formatu wejścia, dlatego próbuje to jakoś zmienić.
Schadoow
To próbując na pałę tego nie osiągniesz teraz wysyłasz z d**y string. Wklej zawartość typu Vacation w backendzie i zawartość z zakładki network.
Schadoow
Oczywiście ten stringify do wywalenia
K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
0

screenshot-20190813162548.png

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

screenshot-20190813162625.png

Schadoow
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Postów:1068
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.

Schadoow
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Postów:1068
0
  • zakładam po składni, że po prostu próbujesz na null'u wykonać operację o w tym miejscu.
Kopiuj
Vacation.vacationID.ToString()
edytowany 1x, ostatnio: Schadoow
Zobacz pozostałe 2 komentarze
K5
Generuje po stronie bazy, ale nie ma takiej możliwości że API potrzebuje jakiejkolwiek wartości vacationID oprócz null?
Schadoow
to czemu używasz obiektu Vacation zamiast response ? Domyślam się, że obiekt response to jest Vacation po zapisaniu do bazy więc id powinno być już uzupełnione.
Schadoow
Widzę, że nie za bardzo rozumiesz co robisz ;p. Do obiektu Vacation może pójść wszystko co mapper da rade zmapować na dany obiekt. oczywiście o ile nie dasz walidacji na to co przychodzi. Także obiekt z samymi nullami też będzie prawidłowy co nie oznacza, że możesz frywolnie próbować wywoływać metody na null'u.
K5
Ja już od wczoraj nie wiem co robię xd, siedzę od piątku po kilkanaście godzin dziennie nad jedną rzeczą, już powoli tracę nadzieje ze najprostrza funkcja w programowaniu nie bedzie mi działała, dlatego napisałem tutaj w celu pomocy :D powiedz mi co potrzebujesz aby mi jeszcze pomóc, albo nakierować :)
Schadoow
w sumie to już ci napisałem. Pokaż co zwraca wywołanie "entities.newVacation" tzn weź albu screena z debuggera z zwartościa albo wypisz na ekran zawartość obiektu i podeslij.
K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
0

Nie mogę znaleźć tej opcji Request Payload

screenshot-20190813164123.png

Schadoow
Poszukaj dobrze bo jest tam na pewno :) użyj scrolla. Bo to jest poniżej Request Headers
K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
0

Nic nie mam poniżej :(

screenshot-20190813170824.png

K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
0

Responce czyli entities.newVacation zwraca INT = 1 :

screenshot-20190813173931.png

Schadoow
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Postów:1068
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 :).

K5
newVacation to jest procedura w bazie. Przyjmuje cztery parametry. Wywoływana jest podczas operacji POST. Po tej stronie wydaje mi się że wszystko okej.
K5
Nie rozumiem jednej rzeczy, parametry pobierają się prawidłowo z pól w HTML, widać to po wyniku z console.log. webAPI również poprawnie działa bo kiedy wyślę JSON'a poprzez PostMan to rekord dodaje się do bazy. Więc gdzie jest kurde problem.
K5
Czy ja sobie ustawiłem za duże progi na początek? Napisanie aplikacji webowej w C# która robi to co chce osiągnąć napisałem w 10min. A nad tym męczę się już 4 dni... A wydaje się taką prostą rzeczą.
Schadoow
Czy ja wiem bardziej nie rozumiesz co wgl robisz przez co wszystko jest na pałę(np pomimo iż id jest generowane to brałeś je z requestu i operowałeś na nim =.=). Idea jest prosta jak masz generowany id przez bazy po zapisaniu musisz dostać/wziąć twój wpis. Wcześniejsze zamieszanie miałeś bo nie potrafiłeś dojść co działa a co nie działa w twojej aplikacji. I nie ma znaczenia tu technologia.
K5
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:27
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:

Kopiuj
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.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.