2012-10-05 26 views
23

¿Cómo puedo llamar a un método de API web desde un método de controlador de acción MVC? Esto es lo que estoy tratando, esta es mi método de control:¿Cómo puedo llamar a un método de WebApi desde el Método de acción MVC Controller?

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); 
    } 
} 

Mi método de 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; 
} 

cuando estoy haciendo esto que estoy recibiendo un modelo var @ error en mi método de acción MVC después de devolver los datos diciendo

"Newtonsoft.Json.JsonSerializationException: no se puede deserializar JSON array" (es decir, [1,2,3]) en 'ProductDetails.Models.ProductItems' de tipo. El tipo deserializado debe ser una matriz o implementar una interfaz de recopilación como IEnumerable, ICollection o IList. Para forzar las matrices JSON para deserializar, agregue JsonArrayAttribute al tipo. Línea 1, posición 1."

Puede cualquiera que me ayude a hacer esto ... o me sugieren cualquier otro método o mejor me corrija si estoy haciendo mal en cualquier lugar ... he vuelto a mostrar la datos en mi opinión ... los datos deberían devolverse a mi controlador

+0

Usaría ProductItem en lugar de ProductItems para el nombre de clase/objeto. Y el uso de la palabra "var" dificulta este tipo de problemas, en mi humilde opinión. – granadaCoder

Respuesta

15

Como dice la excepción "No se puede deserializar matriz JSON ..." tiene un problema en el lado del receptor, por ejemplo, con la deserialización no en su método de API web con la serialización.

Y el problema es que intenta deserializar en el tipo incorrecto debido a su método de API web se ve como:

Por lo tanto, vuelve IEnumerable<ProductItems> (por ejemplo, una serie de ProductItems), pero en su acción de controlador intenta deserializar la respuesta en unoProductItems con la llamada ReadAsAsync<ProductItems>()

Así que cambiar su ReadAsAsync deserializar en una matriz ProductItems y debería funcionar:

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

estoy obteniendo una excepción que dice que el elemento del modelo pasado al diccionario es del tipo 'ProductDetails.Models.ProductItems []', pero este diccionario requiere un elemento de modelo de tipo 'ProductDetails.Models.ProductItems'. – SoftwareNerd

+0

Ahora el problema es su vista 'ProductDetail.cshtml' donde tiene Supongo' @model ProductDetails.Models.ProductItems'. Si su método webapi de todos modos devuelve solo un 'ProductItems' puede escribir' return View (modelo [0]); 'en su controlador. O cambie su método webapi para que solo devuelva 'ProductItems' en lugar de' IEnumerable '... – nemesv

8

Cuando su sitio web ASP.NET está alojando junto con el controlador Web API, puede llamar a la API Web como método de clase ordinario para evitar demoras relacionadas con HTTP solicitud.

Y el problema no está en la llamada a la API web. El problema está en la deserialización del resultado, que proviene de ExecuteStoreQuery, asegúrese de que tiene coll serializable ección en él. Para asegurarse, simplemente puede intentar convertir el resultado de este método en una lista antes de regresar y regresar de la lista serializable del método de la API web, luego localizar el problema.

UPD: Por lo tanto, la raíz del problema está en lo que devuelve el método ExecuteStoreQuery. Devuelve ObjectResult. En realidad, implementa IEnumerable, pero se devuelve de EF y, en algunos casos, hay p. dependencias cíclicas entre objetos, que los deserializadores Json no pudieron resolver.

Para resolver el problema, simplemente convierta explícitamente ObjectResult a, p. Ej. Lista:

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

Cuando un problema es en realidad con dependencias para bicicletas en colecciones de objetos que provienen de EF, puede apagarlo en Json.NET

y también comprobar su cliente deserialización lado:

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

Pero cuando aloja su sitio ASP.NET MVC y ASP.NET Web API en un proyecto, entonces no necesita todo esto con solicitud HTTP y serialización/deserialización, simplemente llame a su método como método de clase ordinario.

+0

me puede ayudar a hacer eso – SoftwareNerd

+0

@Anil acaba de cambiar, pruébelo – Regfor

+0

+1 para señalar tanto el problema en la pregunta, y también para señalar que puede instanciar una instancia del controlador y simplemente llame al método –

Cuestiones relacionadas