2017-05-11 1 views
0

Je suis novice en matière d'API web en général et j'ai des problèmes avec le noyau web api quand il s'agit de créer une nouvelle entrée de base de données en utilisant POST. L'appel ajax ressemble à;Web Api Core - impossible de poster du côté client

addSelectedContract = function (contractId, url, callback) { 
     // hard code url to get working 
     url = "http://localhost:17972/api/selectedcontracts"; 
     var contract = JSON.stringify({ contractId: contractId }); 
     $.ajax({ 
      type: "Post", 
      url: url, 
      data: contract, 
      contentType: "application/json" 
     }).done(callback(status)); 
     }; 

Ma méthode API ressemble à;

namespace Properties.API.Controllers 
{ 
    [Route("api/selectedcontracts")] 
    public class SelectedContractController : BaseController 
    { 
     private readonly ISirUoW SirUoW; 
     private readonly SirDb Db; 

     public SelectedContractController(SirDb db, ISirUoW repo, Services.IMailService mailService) 
      : base(mailService) 
     { 
      this.Db = db; 
      this.SirUoW = repo; 
     } 

     [HttpPost()] 
     public IActionResult Post([FromBody] SelectedContract contract) 
     { 
      try 
      { 
       this.SirUoW.SelectContract.Add(contract); 
       return Ok(new OperationStatus 
       { 
        Status = true, 
        OperationID = contract.SelectedContractId 
       }); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e); 
       var status = Mapper.Map<OperationStatus>(e); 
       return Ok(status); 
      } 
     } 

Mon test de powershell donne ce résultat;

Invoke-RestMethod http://localhost:xxxx/api/selectedcontracts -Method POST -Body (@{contractId="7"} | ConvertTo-Json) -ContentType "application/json" 
[ERROR] Invoke-RestMethod : The remote server returned an error: (500) Internal Server Error. 
[ERROR] At line:1 char:1 
[ERROR] + Invoke-RestMethod http://localhost:xxxx/api/selectedcontracts -Method POST -Bod ... 
[ERROR] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
[ERROR]  + CategoryInfo   : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke- 
[ERROR] RestMethod], WebException 
[ERROR]  + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRes 
[ERROR] tMethodCommand 
[ERROR] 

La classe SelectedContract est définie comme suit: namespace SIR.Domain.Poco { en utilisant Interfaces; en utilisant le système; en utilisant System.ComponentModel.DataAnnotations;

public class SelectedContract : IAuditCreated 
{ 
    [Key] 
    public int SelectedContractId { get; set; } 

    public int ContractId { get; set; } 

    public DateTime Created { get; set; } 

    [MaxLength(50)] 
    public string CreatedBy { get; set; } 
} 

} J'ai cherché autour par exemple le code et je ne vois pas ce que je fais mal.

EDIT: J'ai fait un changement bien que j'obtienne le même résultat. La classe SelectedContract est définie comme suit:

namespace SIR.Domain.Poco 
    { 
     using Interfaces; 
     using System; 
     using System.ComponentModel.DataAnnotations; 

     public class SelectedContract : IAuditCreated 
     { 
      [Key] 
      public int SelectedContractId { get; set; } 

      public int ContractId { get; set; } 

      public DateTime Created { get; set; } 

      [MaxLength(50)] 
      public string CreatedBy { get; set; } 
     } 
    } 

Cependant, j'envoie seulement un des champs, le ContractId. Je ne veux pas envoyer la clé primaire ou les champs d'audit. J'ai donc créé une classe DTO;

namespace Properties.API.Models 
    { 
     public class SelectedContractDto 
     { 
      public int ContractId { get; set; } 
     } 
    } 

Et modifié la signature de ma méthode Post dans l'API;

 [HttpPost()] 
     public IActionResult Post([FromBody] SelectedContractDto contract) 
     { 
      var selectedContract = new SelectedContract { ContractId = Convert.ToInt32(contract.ContractId) }; 
      try 
      { 
       this.SirUoW.SelectContract.Add(selectedContract); 
       return Ok(new OperationStatus 
       { 
        Status = true, 
        OperationID = selectedContract.SelectedContractId 
       }); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e); 
       var status = Mapper.Map<OperationStatus>(e); 
       return Ok(status); 
      } 
     } 

Toujours obtenir l'erreur 500 interne du serveur. J'ai eu un coup d'oeil dans Fiddler et trouvé cette erreur ainsi

An unhandled exception occurred while processing the request. 
InvalidOperationException: 'Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatter c2 s' must not be empty. At least one 'Microsoft.AspNetCore.Mvc.Formatters.IInputFormatter' is required to bind from the body. 
Microsoft.As fdc pNetCore.Mvc.ModelBinding.Binders.BodyModelBinderProvider.GetBinder(ModelBinderProviderContext context) 

Je ne peux pas trouver quoi que ce soit sur cette erreur en ligne.

Répondre

0

Je suppose que vous appelez est la méthode de frappe, mais après cela, il y a une erreur qui n'est pas affichée dans le bloc try-catch? Cochez "Common Language Runtime Exceptions" dans Déboguer -> Windows -> Paramètres d'exception et réessayez.

Afficher le résultat.

+0

Je mets un point d'arrêt dans la méthode mais ne l'atteint pas. – arame3333

+0

Veuillez ajouter une structure de classe SelectedContract et mettez à jour votre question. lire aussi [this] (http://stackoverflow.com/questions/24625303/why-do-we-have-to-specify-frombody-and-fromuri-in-asp-net-web-api) et faire Assurez-vous que vous utilisez [FromBody] correctement. – lolek

+0

lire [this] (http://stackoverflow.com/questions/41559050/string-value-is-empty-when-using-frombody-in-asp-net-web-api) et essayer de manipuler un peu votre ajax demande et utilise votre objet contrat sans la méthode JSON.stringify() – lolek