web-dev-qa-db-fra.com

Comment puis-je appeler une méthode Web Api à partir de la méthode d'action du contrôleur MVC?

Comment puis-je appeler une méthode d'API Web à partir d'une méthode de contrôleur d'action MVC. Voici ce que j'essaie, voici ma méthode de contrôleur:

public ActionResult ProductDetail(long id)
{
    using (var client = new HttpClient())
    {
        var productDetailUrl = Url.RouteUrl(
            "DefaultApi",
            new { httproute = "", controller = "ProductDetails", id = id },
            Request.Url.Scheme
        );
        var model = client
                    .GetAsync(productDetailUrl)
                    .Result
                    .Content.ReadAsAsync<ProductItems>().Result;

        return View(model);
    }
}

Ma méthode d'API Web:

private ProductEntities products = new ProductEntities();

public IEnumerable<ProductItems> GetProductDetail(int ID)
{            
   var produc= products.ExecuteStoreQuery<ProductItems>(
            "GetProductDetail @ProductID ", 
            new SqlParameter("@ProductID", ID)); 

   return produc;
}

Quand je fais cela, j'obtiens un modèle error @ var dans ma méthode d'action MVC après avoir renvoyé les données en disant

"Newtonsoft.Json.JsonSerializationException: impossible de désérialiser le tableau JSON" (c'est-à-dire [1,2,3]) dans le type 'ProductDetails.Models.ProductItems'. Le type désérialisé doit être un tableau ou implémenter une interface de collecte comme IEnumerable, ICollection ou IList. Pour forcer les tableaux JSON à désérialiser, ajoutez JsonArrayAttribute au type. Ligne 1, position 1. "

Quelqu'un peut-il m'aider à faire cela ... ou me suggérer une autre meilleure méthode ou me corriger si je me trompe quelque part ... Je dois montrer les données retournées à mon avis ... les données doivent être retournées à mon manette

24
SoftwareNerd

Comme l'exception indique "Cannot deserialize JSON array ...", vous avez un problème côté récepteur, par exemple avec la désérialisation pas dans votre méthode API Web avec la sérialisation.

Et votre problème est que vous essayez de désérialiser dans le mauvais type car votre méthode API Web ressemble à:

public IEnumerable<ProductItems> GetProductDetail(int ID)

Il renvoie donc IEnumerable<ProductItems> (Par exemple un tableau de ProductItems) mais dans l'action de votre contrôleur, vous essayez de désérialiser la réponse en nProductItems avec l'appel ReadAsAsync<ProductItems>()

Modifiez donc votre ReadAsAsync pour désérialiser en un tableau ProductItems et cela devrait fonctionner:

var model = client
               .GetAsync(productDetailUrl)
               .Result
               .Content.ReadAsAsync<ProductItems[]>().Result;
15
nemesv

Lorsque votre site Web ASP.NET héberge avec le contrôleur API Web, vous pouvez appeler l'API Web comme méthode de classe ordinaire pour éviter tout retard lié à la demande HTTP.

Et le problème n'est pas dans l'appel de l'API Web. Le problème est dans la désérialisation des résultats, qui vient d'ExecuteStoreQuery, assurez-vous d'avoir une collection sérialisable en elle. Pour vous en assurer, vous pouvez simplement essayer de convertir ce résultat de méthode en liste avant le retour et le retour de la liste sérialisable de la méthode web api, puis localiser le problème.

UPD: Donc, la racine du problème est dans ce que la méthode ExecuteStoreQuery retourne. Il renvoie ObjectResult . Il implémente en fait IEnumerable, mais il est renvoyé par EF et dans certains cas, il y a par exemple dépendances cycliques entre les objets, que les désérialiseurs Json ne pouvaient pas résoudre.

Pour résoudre le problème, il suffit de convertir explicitement ObjectResult en par exemple Liste:

public IEnumerable<ProductItems> GetProductDetail(int ID)
{            
    var products = products.ExecuteStoreQuery<ProductItems>(
              "GetProductDetail @ProductID ",     
              new SqlParameter("@ProductID", ID)); 
    return products.ToList<ProductItems>();
}

Lorsque le problème est en fait lié aux dépendances de cycle dans les collections de vos objets provenant d'EF, vous pouvez le désactiver dans Json.NET

Et vérifiez également votre désérialisation côté client:

var model = client.GetAsync(productDetailUrl).Result
                .Content.ReadAsAsync<List<ProductItems>>().Result;

Mais lorsque vous hébergez votre site ASP.NET MVC et votre API Web ASP.NET dans un seul projet, vous n'avez pas besoin de tout cela avec une requête HTTP et une sérialisation/désérialisation, appelez simplement votre méthode comme méthode de classe ordinaire.

8
Regfor