【问题标题】:How can I call a WebApi method from MVC Controller Action Method?如何从 MVC 控制器操作方法调用 Web Api 方法?
【发布时间】:2020-12-28 09:25:40
【问题描述】:

如何从 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'。 反序列化的类型必须是数组或实现集合 像IEnumerableICollectionIList 这样的接口。强制 JSON 数组 要反序列化,请将 JsonArrayAttribute 添加到类型中。 1号线, 位置 1。”

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

【问题讨论】:

  • 我会使用 ProductItem 而不是 ProductItems 作为类/对象名称。恕我直言,使用“var”字会阻碍这些问题的解决。

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


【解决方案1】:

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

而你的问题是你试图反序列化为错误的类型,因为你的 web api 方法看起来像:

public IEnumerable<ProductItems> GetProductDetail(int ID)

因此它返回IEnumerable&lt;ProductItems&gt;(例如ProductItems 的数组),但在您的控制器操作中,您尝试通过调用ReadAsAsync&lt;ProductItems&gt;() 将响应反序列化为one ProductItems

因此,将您的 ReadAsAsync 更改为反序列化为数组 ProductItems,它应该可以工作:

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

【讨论】:

  • 我收到一个异常说传递到字典中的模型项的类型是“ProductDetails.Models.ProductItems[]”,但是这个字典需要一个类型为“ProductDetails.Models.ProductItems”的模型项.
  • 现在问题是你的观点ProductDetail.cshtml 我猜你有@model ProductDetails.Models.ProductItems。如果您的 webapi 方法无论如何只返回一个ProductItems,您可以在控制器中写入return View(model[0]);。或者更改您的 webapi 方法以仅返回 ProductItems 而不是 IEnumerable&lt;ProductItems&gt;...
【解决方案2】:

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

【讨论】:

  • +1 用于指出问题中的问题,并指出您可以实例化控制器实例并调用方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
相关资源
最近更新 更多