如何从MVC Controller Action Method调用Web Api方法?

时间:2012-10-05 06:52:59

标签: json asp.net-mvc-4 asp.net-web-api json.net

如何从MVC动作控制器方法调用Web API方法。这就是我想要的,这是我的控制器方法:

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

我的Web API方法:

private ProductEntities products = new ProductEntities();

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

   return produc;
}

当我这样做时,我在返回数据后在我的MVC操作方法中收到错误@ var model

  

“Newtonsoft.Json.JsonSerializationException:无法反序列化JSON   数组“(即[1,2,3])到'ProductDetails.Models.ProductItems'类型。   反序列化类型必须是数组或实现集合   界面如IEnumerable,ICollection或IList。强制JSON数组   要反序列化,请将JsonArrayAttribute添加到该类型中。第1行,   位置1.“

任何人都可以帮我这样做......或者建议我使用其他最好的方法或纠正我,如果我在任何地方做错了......我必须在我的视图中显示返回的数据......数据应该是回到我的控制器

2 个答案:

答案 0 :(得分:15)

由于异常状态“无法反序列化 JSON数组...”,您在接收方方面遇到问题,例如反序列化不在您的带有序列化的Web api方法中。

您的问题是您尝试反序列化为错误的类型,因为您的web api方法如下所示:

public IEnumerable<ProductItems> GetProductDetail(int ID)

因此它会返回IEnumerable<ProductItems>(例如ProductItems的数组),但在您的控制器操作中,您尝试通过调用将响应反序列化为一个 ProductItems ReadAsAsync<ProductItems>()

因此,将您的ReadAsAsync更改为反序列化为数组ProductItems,它应该有效:

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

答案 1 :(得分:8)

当您的ASP.NET网站与Web API控制器一起托管时,您可以将Web API称为普通类方法,以避免与HTTP请求相关的任何延迟。

问题不在Web API调用中。问题在于结果反序列化,来自ExecuteStoreQuery,确保你有可序列化的集合。为了确保,您可以在返回之前尝试将此方法结果转换为列表,并从web api方法可序列化列表返回,然后本地化问题。

UPD:因此,问题的根源在于ExecuteStoreQuery方法返回的内容。它返回ObjectResult。它实际上实现了IEnumerable,但是它是从EF返回的,并且在某些情况下例如是Json反序列化器无法解析的对象之间的循环依赖关系。

要解决问题,只需将ObjectResult明确转换为例如列表:

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

当问题实际上是来自EF的对象集合中的循环依赖性时,您可以在Json.NET中将其关闭

并检查客户端反序列化:

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

但是当你在一个项目中托管ASP.NET MVC站点和ASP.NET Web API时,你不需要所有这些与HTTP请求和序列化/反序列化的东西,只需将你的方法称为普通的类方法。 / p>