1
votes

Angular 6 HttpClient Post n'atteignant pas la méthode de publication d'API dans le contrôleur d'API DotNet Core 2.2

J'ai mis à niveau MVC / AngularJS 1.x vers DotNet Core 2.2 / Angular 6.x. avec @ angular / common / http

La plupart du temps, cela a été un jeu d'enfant, mais l'API Web me tue. Je me suis mis au travail en quelques minutes, mais j'ai passé une semaine à tout essayer sous le soleil pour que le Web Post fonctionne.

Ce que j'ai fait ici est vraiment simple à reproduire. p>

  1. Allez dans Visual Studio 17 et cliquez sur Fichier / Nouveau projet

  2. Choisissez Installé / Visual C # /. NET Core

  3. Sélectionnez le modèle: Application Web ASP.NET core

  4. Sur l'écran secondaire, définissez les listes déroulantes en haut sur .NET Core et ASP.NET Core 2.2

  5. Sélectionnez le modèle angulaire du bouclier rouge "A"

  6. Laissez le projet extraire les dépendances et reconstruire.

TOUT est l'application de démonstration prête à l'emploi de Microsoft, à l'exception de:

  1. Ajoutez les boutons à l'écran.

  2. Ajoutez du code aux .ts pour appeler le contrôleur d'API

  3. Ajoutez le paramètre d'entrée à la méthode get dans le contrôleur

  4. Ajouter une méthode de publication très simple au contrôleur

J'essaye également d'obtenir DotNet Core 2.0 / Angular 4.x. avec @ angular / http travailler avec exactement les mêmes résultats. L'obtention était très facile, mais j'ai essayé toutes les configurations sous le soleil pour que le poste fonctionne. Je ferai également un article comme celui-ci pour l'autre version. Pour le moment, j'essaie juste de faire fonctionner tout ce que je peux et de laisser AngularJS 1.x derrière.

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;

namespace NG_22.Controllers
{
    [Route("api/[controller]")]
    public class SampleDataController : Controller
    {
        private static string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        [HttpGet("[action]")]
        public IEnumerable<WeatherForecast> WeatherForecasts(int startDateIndex = 0)
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                DateFormatted = DateTime.Now.AddDays(index + startDateIndex).ToString("d"),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            });
        }
        [HttpPost("[action]")]
        public WeatherForecast PostWeatherForecast([FromBody] WeatherForecast weatherForecast)
        {
            var forecast = weatherForecast;
            //return weatherForecast;
            return new WeatherForecast()
            {
                DateFormatted = DateTime.Now.ToString("d"),
                TemperatureC = 30,
                Summary = Summaries[2]
            };
        }



        public class WeatherForecast
        {
            public string DateFormatted { get; set; }
            public int TemperatureC { get; set; }
            public string Summary { get; set; }

            public int TemperatureF
            {
                get
                {
                    return 32 + (int)(TemperatureC / 0.5556);
                }
            }
        }
    }
}
<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

<p *ngIf="!forecasts"><em>Loading...</em></p>

<table class='table table-striped' *ngIf="forecasts">
  <thead>
    <tr>
      <th>Date</th>
      <th>Temp. (C)</th>
      <th>Temp. (F)</th>
      <th>Summary</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let forecast of forecasts">
      <td>{{ forecast.dateFormatted }}</td>
      <td>{{ forecast.temperatureC }}</td>
      <td>{{ forecast.temperatureF }}</td>
      <td>{{ forecast.summary }}</td>
    </tr>
  </tbody>
</table>
<button class='btn btn-default pull-left' (click)="OnClick('Prior')">Previous</button>
<button class='btn btn-default pull-left' (click)="OnClick('Next')">Next</button>
<button class='btn btn-default pull-right' (click)="OnClick('Post')">Post</button>
import { Component, Inject } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders  } from '@angular/common/http';

@Component({
  selector: 'app-fetch-data',
  templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
  public Http: HttpClient;
  public BaseURL: string;
  public HttpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  };
  public startDateIndex = 0;
  public forecasts: WeatherForecast[] = [];
  public forecast: WeatherForecast = {
    dateFormatted: "3/27/2020",
    temperatureC: 0,
    temperatureF: 32,
    summary: "Cold Post"
  };

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this.Http = http;
    this.BaseURL = baseUrl;

    http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts')
      .subscribe(result => { this.forecasts = result; }, error => console.error(error));
  }
  public OnClick(pControl: string) {
    //console.log("LogOn.OnClick * pControl=" + pControl);
    switch (pControl) {
      case "Prior":
        this.startDateIndex -= 5;
        this.Http.get<WeatherForecast[]>(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
          .subscribe(result => { this.forecasts = result; }, error => console.error(error));
        break;
      case "Next":
        this.startDateIndex += 5;
        this.Http.get<WeatherForecast[]>(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
          .subscribe(result => { this.forecasts = result; }, error => console.error(error));
        break;
      case "Post":
        console.log("Post * this.forecast=" + JSON.stringify(this.forecast) + "this.HttpOptions=" + JSON.stringify(this.HttpOptions));
        this.Http.post<WeatherForecast>(this.BaseURL + '/api/SampleData/PostWeatherForecast/', this.forecast, this.HttpOptions);
    }
  }
}

interface WeatherForecast {
  dateFormatted: string;
  temperatureC: number;
  temperatureF: number;
  summary: string;
}


7 commentaires

Avez-vous essayé Stringify les données que vous transmettez au contrôleur? Vous utilisez stringify dans le journal mais pas dans l'appel


Je n'ai pas été dans ce genre de choses depuis un moment, mais je me souviens de problèmes lorsque votre URL a été générée en tant que / WeatherForecast? StartDateIndex = "2" au lieu de / WeatherForecast / 2 ou vice versa. Je verrai si je peux déterrer quelque chose.


Donc je crois que c'est vos attributs [Http *]. Lisez docs.microsoft. com / en-us / aspnet / core / mvc / controllers /… . Essayez de changer [Route ("api / [controller]")] en [Route ("api / [controller] / [action]")] et [HttpGet ("[action]")] en [HttpGet]. Je suis presque sûr que ce sera une combinaison de cela.


*** Avez-vous essayé Stringify les données que vous transmettez au contrôleur? Vous utilisez stringify dans le journal mais pas dans l'appel *** J'ai essayé cela, cela n'a pas fonctionné, même si j'ai changé l'en-tête en texte au lieu de JSON


*** Je n'ai pas été dans ce genre de choses depuis un moment, mais je me souviens de problèmes lorsque votre URL a été générée en tant que / WeatherForecast? StartDateIndex = "2" au lieu de / WeatherForecast / 2 ou vice versa. **** Le Get, qui utilise le startindex, fonctionne correctement. Le seul problème est avec la poste


**** Donc je crois que c'est vos attributs [Http *]. Lisez docs.microsoft.com/en-us/aspnet/core/mvc/controllers/…. Essayez de changer [Route ("api / [controller]")] en [Route ("api / [controller] / [action]")] et [HttpGet ("[action]")] en [HttpGet]. Je suis presque sûr que ce sera une combinaison de cela. *** Merci! Je vais essayer. À un moment donné, en jouant avec le code, je l'ai fait frapper la méthode Controller post, mais les paramètres sont apparus comme nuls


*** Je n'ai pas été dans ce genre de choses depuis un moment, mais je me souviens de problèmes lorsque votre URL a été générée en tant que / WeatherForecast? StartDateIndex = "2" au lieu de / WeatherForecast / 2 ou vice versa. **** J'ai changé [Route ("api / [controller]")] en [Route ("api / [controller] / [action]")] et changé [HttpGet ("[action]")] en [HttpGet ] et remplacé [HttpPost ("[action]")] par [HttpPost] Le résultat était identique. Le Get fonctionne bien mais le message ne touche pas. Cela a cependant rationalisé le code.


4 Réponses :


2
votes

Résolu !!!!!

Le problème était qu'il n'y avait rien d'abonné. Si personne n'écoute, cela ne prend pas la peine d'appeler le Post. J'ai ajouté un .subscribe et cela a bien fonctionné.

import { Component, Inject } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders  } from '@angular/common/http';

@Component({
  selector: 'app-fetch-data',
  templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
  public Http: HttpClient;
  public BaseURL: string;
  public HttpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  };
  public startDateIndex = 0;
  public forecasts: WeatherForecast[] = [];
  public forecast: WeatherForecast = {
    dateFormatted: "3/27/2020",
    temperatureC: 0,
    temperatureF: 32,
    summary: "Cold Post"
  };

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this.Http = http;
    this.BaseURL = baseUrl;

    http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts')
      .subscribe(result => { this.forecasts = result; }, error => console.error(error));
  }
  public OnClick(pControl: string) {
    //console.log("LogOn.OnClick * pControl=" + pControl);
    switch (pControl) {
      case "Prior":
        this.startDateIndex -= 5;
        this.Http.get<WeatherForecast[]>(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
          .subscribe(result => { this.forecasts = result; }, error => console.error(error));
        break;
      case "Next":
        this.startDateIndex += 5;
        this.Http.get<WeatherForecast[]>(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
          .subscribe(result => { this.forecasts = result; }, error => console.error(error));
        break;
      case "Post":
        console.log("Post * this.forecast=" + JSON.stringify(this.forecast) + "this.HttpOptions=" + JSON.stringify(this.HttpOptions));
        this.Http.post<WeatherForecast>(this.BaseURL + '/api/SampleData/PostWeatherForecast/', this.forecast, this.HttpOptions)
          .subscribe(result => { console.log("Posted" + JSON.stringify(result)); }, error => console.error(error));          
    }
  }
}

interface WeatherForecast {
  dateFormatted: string;
  temperatureC: number;
  temperatureF: number;
  summary: string;
}


0 commentaires

1
votes

Réponse améliorée. L'interface n'est pas nécessaire et d'autres améliorations plus petites et suppression du code inutile.

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;

namespace NG_22.Controllers
{
    [Route("api/[controller]/[action]")] 
    public class SampleDataController : Controller
    {
        private static string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };
        [HttpGet]
        public IEnumerable<WeatherForecast> WeatherForecasts(int startDateIndex = 0)
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                DateFormatted = DateTime.Now.AddDays(index + startDateIndex).ToString("d"),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            });
        }
        [HttpPost]
        public object PostWeatherForecast([FromBody] WeatherForecast weatherForecast)
        {
            var forecast = weatherForecast;
            //return weatherForecast;
            return new
            {
                DateFormatted = DateTime.Now.ToString("d"),
                TemperatureC = 30,
                Summary = Summaries[2]
            };
        }



        public class WeatherForecast
        {
            public string DateFormatted { get; set; }
            public int TemperatureC { get; set; }
            public string Summary { get; set; }
            public int TemperatureF
            {
                get
                {
                    return 32 + (int)(TemperatureC / 0.5556);
                }
            }
            public object Data { get; set; }
        }
    }
}
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
<p *ngIf="!forecasts"><em>Loading...</em></p>
<table class='table table-striped' *ngIf="forecasts">
  <thead>
    <tr>
      <th>Date</th>
      <th>Temp. (C)</th>
      <th>Temp. (F)</th>
      <th>Summary</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let forecast of forecasts">
      <td>{{ forecast.dateFormatted }}</td>
      <td>{{ forecast.temperatureC }}</td>
      <td>{{ forecast.temperatureF }}</td>
      <td>{{ forecast.summary }}</td>
    </tr>
  </tbody>
</table>
<button class='btn btn-default pull-left' (click)="OnClick('Prior')">Previous</button>
<button class='btn btn-default pull-left' (click)="OnClick('Next')">Next</button>
<button class='btn btn-default pull-right' (click)="OnClick('Post')">Post</button>
import { Component, Inject } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders  } from '@angular/common/http';

@Component({
  selector: 'app-fetch-data',
  templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
  public Http: HttpClient;
  public BaseURL: string;
  public HttpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  };
  public startDateIndex = 0;
  public forecasts: any;
  public forecast = { dateFormatted: "3/27/2020", temperatureC: 0, temperatureF: 32, summary: "Cold Post", Data: { color: "red", Size: "Large" } };

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this.Http = http;
    this.BaseURL = baseUrl;

    http.get(baseUrl + 'api/SampleData/WeatherForecasts')
      .subscribe(result => { this.forecasts = result; }, error => console.error(error));
  }
  public OnClick(pControl: string) {
    //console.log("LogOn.OnClick * pControl=" + pControl);
    switch (pControl) {
      case "Prior":
        this.startDateIndex -= 5;
        this.Http.get(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
          .subscribe(result => { this.forecasts = result; }, error => console.error(error));
        break;
      case "Next":
        this.startDateIndex += 5;
        this.Http.get(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
          .subscribe(result => { this.forecasts = result; }, error => console.error(error));
        break;
      case "Post":
        console.log("Post * this.forecast=" + JSON.stringify(this.forecast) + "this.HttpOptions=" + JSON.stringify(this.HttpOptions));
        this.Http.post(this.BaseURL + '/api/SampleData/PostWeatherForecast/', this.forecast, this.HttpOptions)
          .subscribe(result => { alert("Posted" + JSON.stringify(result)); }, error => console.error(error));          
    }
  }
}


0 commentaires

0
votes
    using DMChess_Data.Model;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace DMChess_Data
{
    public class Entities
    {
        private dmchessContext DMCConnection = new dmchessContext();
        private Guid AppId = new Guid("B6C093C8-AE8C-40CD-9E0D-3BD2118422EC");
        public bool SaveChanges()
        {
            try
            {
                DMCConnection.SaveChangesAsync();
            }
            catch(Exception pException)
            //catch (Microsoft.EntityFrameworkCore.)
            //catch (System.Data.Entity.Validation.DbEntityValidationException ex)
            {
                var ex = pException;

                //foreach (var eve in ex.EntityValidationErrors)
                //{

                //    var type = eve.Entry.Entity.GetType().Name;
                //    var state = eve.Entry.State;
                //    foreach (var ve in eve.ValidationErrors)
                //    {
                //        var propertyName = ve.PropertyName;
                //        var ErrorMessage = ve.ErrorMessage;
                //    }
                //}
                //var m = ex;
                throw;
            }
            DMCConnection.SaveChanges();
            return true;
        }

        #region AUsers
        public AUsers AUsersGet(Guid pId, string pPassword)
        {
            return DMCConnection.AUsers.FirstOrDefault(x => x.KAppId == AppId && x.KId == pId && x.Password == pPassword);
        }
        public AUsers AUsersGet(string pEmailAddress, string pPassword)
        {
            return DMCConnection.AUsers.FirstOrDefault(x => x.KAppId == AppId && x.EmailAddress == pEmailAddress);
        }

        #endregion

        #region DProfiles

        public DProfiles DProfileGet(Guid pKUserId, int pKIdx)
        {
            return DMCConnection.DProfiles.FirstOrDefault(x => x.KAppId == AppId && x.KUserId == pKUserId && x.KIdx == pKIdx);
        }

        public List<DProfiles> DProfilesGet(string pUserIdName)
        {
            return DMCConnection.DProfiles.Where(x => x.KAppId == AppId && x.UserIdToLower == pUserIdName.ToLower()).ToList();
        }
        #endregion
    }
}

0 commentaires

0
votes
    using D2Chess.Server.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;

namespace D2Chess.Controllers
{
    [Route("api/[controller]/[action]")]
    public class WebController : Controller
    {
        #region Init

        private JsonSerializer jsonSerializer = new JsonSerializer();
        private Repository repository = new Repository();
        public WebController(IHubContext<D2Chess.Server.IO.Hub> hubContext) { D2Chess.Server.IO.Hub.StaticContext = hubContext; }

        #endregion

        #region Classes

        public class Parms {

            public Guid? TokenId { get; set; }
            public string Action { get; set; }
            public object Data { get; set; }
        }
        public class Result
        {
            public bool Success { get; set; }
            public object Data { get; set; }
            public Result(bool pSuccess, object pData = null) { this.Success = pSuccess; this.Data = pData; }
        }

        #endregion

        #region Sync Methods

        [HttpGet]
        public object Get(string pAction, string pKey = "", Guid? pTokenId = null)
        {
            return repository.WebGet(pAction, pKey, pTokenId);
            //var result = repository.WebGet(pAction, pKey, pTokenId);
            //return result;
        }

        [HttpPost]
        public object Post([FromBody] object pParms)
        {
            var parms = ((JObject)pParms).ToObject<Parms>();
            return repository.WebPost(parms.Action, parms.Data, parms.TokenId);
            //var result = repository.WebPost(parms.Action, parms.Data, parms.TokenId);
            //return result;
        }

        #endregion
    }
}

0 commentaires