23

如何从 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;
}

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

" Newtonsoft.Json.JsonSerializationException: 无法将 JSON 数组 "(ie [1,2,3]) 反序列化为类型 ' ProductDetails.Models.ProductItems'。反序列化的类型必须是数组或实现集合接口,如IEnumerable,ICollectionIList。要强制 JSON 数组反序列化JsonArrayAttribute,请在类型中添加 。第 1 行,位置 1。”

任何人都可以帮我这样做,建议另一种更好的方法,或者如果我在任何地方做错了,可以纠正我吗?我必须在我的视图中显示返回的数据,数据应该返回到我的控制器。

4

2 回答 2

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;
于 2012-10-05T08:02:12.200 回答
8

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

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

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

要解决问题,只需将 ObjectResult 显式转换为例如 List:

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 请求和序列化/反序列化的东西,只需将你的方法调用为普通的类方法。

于 2012-10-05T07:02:46.310 回答