web-dev-qa-db-fra.com

L'entrée n'était pas valide .NET Core Web API

Je suis confronté à un problème étrange et j'ai presque passé 4 heures sans succès.

J'ai une API Web simple que j'appelle pour soumettre un formulaire.

API-

// POST: api/Tool
[HttpPost]
public void Post([FromBody] Object value)
{
    _toolService.CreateToolDetail(Convert.ToString(value));
}

HTML-

<!DOCTYPE html>
<html>
<body>

<h2>HTML Forms</h2>
<form name="value" action="https://localhost:44352/api/tool" method="post">
  First name:<br>
  <input type="text" id="PropertyA" name="PropertyA" value="Some value A">
  <br>
  Last name:<br>
  <input type="text" id="PropertyB" name="PropertyB" value="Some value B">
  <br><br>
  <!--<input type="file" id="Files" name="Files" multiple="multiple"/>-->
  <br><br>
  <input type="submit" value="Submit">

  </form>
</body>
</html>

Lorsque je clique sur le bouton d'envoi, je reçois l'erreur ci-dessous.

{"":["The input was not valid."]}

Configurations en classe de démarrage

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    services.AddSingleton<IConfiguration>(Configuration);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseMvc();
}

Cela ne se produit que pour la demande POST. La requête GET fonctionne bien. Même problème lors du test dans le client Postman REST. Toute aide s'il vous plaît? S'il vous plaît laissez-moi savoir si je peux fournir plus de détails.

25
Souvik Ghosh

N'utilisez pas FromBody. Vous soumettez en tant que x-www-form-urlencoded (c'est-à-dire un message de formulaire HTML standard). L'attribut FromBody est destiné à JSON/XML.

Vous ne pouvez pas gérer les deux soumissions de formulaire standard et Les corps de requête JSON/XML proviennent de la même action. Si vous devez demander l'action dans les deux sens, vous aurez besoin de deux points de terminaison distincts, l'un avec le paramètre décoré avec FromBody et l'autre sans. Il n'y a pas d'autre moyen. La fonctionnalité réelle de votre action peut être intégrée dans une méthode privée que les deux actions peuvent utiliser afin de réduire la duplication de code.

32
Chris Pratt

Je viens de travailler à travers une situation similaire ici; J'ai pu utiliser le [FromBody] sans aucun problème:

public class MyController : Controller
{
   [HttpPost]
   public async Task<IActionResult> SomeEndpoint([FromBody]Payload inPayload)
   {
   ...
   }
}

public class Payload
{
   public string SomeString { get; set; }
   public int SomeInt { get; set; }
}

Le défi que j’ai relevé était de s’assurer que les demandes étaient effectuées avec l’en-tête Content-Type défini comme "application/json". À l'aide de Postman, ma demande initiale a été renvoyée sous la forme "L'entrée n'était pas valide". L'ajout de l'en-tête Content-Type a résolu le problème pour moi.

11
Adam Schumph

Il suffit de changer [FromBody] en [FromForm].
L'attribut FromForm concerne les données entrantes provenant d'un formulaire soumis envoyé par le type de contenu application/x-www-url-formencoded, tandis que FromBody analysera le modèle de la manière par défaut, qui dans la plupart des cas sont: envoyé par le type de contenu application/json, à partir du corps de la demande.
Merci à https://stackoverflow.com/a/50454145/5541434

6
Pedram Ahmadpour

Comme mjwills et DavidG l'ont dit, vous devriez probablement utiliser une classe concrète dans l'implémentation de vos paramètres de contrôleur, quelque chose comme:

public class MyClass
{
    public string PropertyA { get; set; }

    public string PropertyB { get; set; }
}
0
Ben Krueger

Si vous examinez l'onglet Réseau de votre navigateur, vous remarquerez que votre formulaire envoie les valeurs d'entrée en tant que paramètres à votre URL, mais pas lui-même . Donc, le nommer valeur n'enverra pas une propriété appelée "valeur" à votre serveur.

Au lieu de cela, la méthode post attend une propriété appelée value , qui peut être de tout type (puisqu'il s'agit d'un objet), et ce paramètre n'est jamais rempli, car il les reçoit. autres paramètres: PropertyA, PropertyB et Files.

Votre URL de post complète devrait probablement ressembler à ceci maintenant:

https: // localhost: 44352/api/tool? PropertyA = X et PropertyB = Y & Files = Z

Notez également que vous n’avez pas spécifié d’URL à votre méthode Post , je ne suis donc pas sûr de savoir comment le client atteindra /api/Tool Vous aurez probablement besoin de spécifier cette URL sur votre contrôleur, en ajoutant l'attribut Route :

[Route ("api/tool")]

La route naturelle, sinon, est Nom d’hôte/Contrôleur/Méthode ou https: // localhost: 44352/api/post , si votre contrôleur est nommé Api. Sinon, il remplacera "api" par le nom du contrôleur.

0
ShadowKras

j'ai le même problème, ma solution était de désactiver l'attribut ApiController. Je ne sais pas pourquoi vous pouviez lire ceci [ https://docs.Microsoft.com/en-us/aspnet/core/web-api/?view= aspnetcore-2.2 # multipartform-data-request-inference] je ne comprends pas quel est le problème

[Produces("application/json")]
    [Route("api/[controller]")]
    //[ApiController]<<remove this
    public class PagosController : ControllerBase

et vous méthode

[HttpPost("UploadDescuento")]
public async Task<IActionResult> UploadDescuento(IEnumerable<IFormFile> files)

Changez le type de corps du texte au format requis, par exemple de texte à JSON (application).

0
tonderaimuchada