Подтвердить что ты не робот

Как я могу вызвать метод WebApi из метода действий MVC Controller?

Как я могу вызвать метод Web API из метода контроллера действия MVC. Это то, что я пытаюсь, это мой метод контроллера:

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 массив" (т.е. [1,2,3]) в тип 'ProductDetails.Models.ProductItems'. Десериализованный тип должен быть массивом или реализовывать коллекцию интерфейс, такой как IEnumerable, ICollection или IList. Чтобы заставить массивы JSON для десериализации добавьте JsonArrayAttribute к типу. Линия 1, позиция 1.

Может ли кто-нибудь помочь мне сделать это... или предложить мне какой-либо другой лучший метод или исправить меня, если я буду делать что-то неправильно... Я должен показать возвращенные данные на мой взгляд... данные должны быть вернулся к моему контроллеру

4b9b3361

Ответ 1

Как исключение указывает, что "не может десериализовать массив JSON...", у вас есть проблема со стороны приемника, например, с десериализацией не в вашем веб-методе 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;

Ответ 2

Когда ваш веб-сайт ASP.NET размещается вместе с контроллером Web API, вы можете вызвать Web API как обычный метод класса, чтобы избежать любых задержек, связанных с HTTP-запросом.

И проблема не в вызове Web API. Проблема заключается в десериализации результата, которая исходит из ExecuteStoreQuery, убедитесь, что в ней есть сериализуемая коллекция. Чтобы убедиться, вы можете просто попытаться преобразовать этот результат метода в список перед возвратом и возвратом из сериализуемого списка веб-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 и веб-API ASP.NET в одном проекте, вам не нужно все это с помощью HTTP-запроса и сериализации/десериализации, просто вызовите свой метод как обычный метод класса.