web-dev-qa-db-ja.com

MVCコントローラーアクションメソッドからWeb APIメソッドを呼び出すにはどうすればよいですか?

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モデルを取得しています

「Newtonsoft.Json.JsonSerializationException:JSON配列を逆シリアル化できません」(つまり[1,2,3])をタイプ 'ProductDetails.Models.ProductItems'に変換します。逆シリアル化された型は配列であるか、IEnumerable、ICollection、IListなどのコレクションインターフェイスを実装する必要があります。 JSON配列にデシリアライズを強制するには、JsonArrayAttributeを型に追加します。行1、位置1。」

誰かがこれを行うのを手伝ってもらえますか...または他の最善の方法を提案したり、間違っている場合は修正してください...返されたデータをビューに表示する必要があります...データはコントローラ

24
SoftwareNerd

例外には「Cannot deserialize JSON array ...」と記載されているため、受信側で問題が発生します。たとえば、シリアライゼーションを使用するWeb APIメソッドではないデシリアライゼーションがあります。

そして、あなたの問題は、Web APIメソッドが次のように見えるため、間違った型にデシリアライズしようとすることです:

_public IEnumerable<ProductItems> GetProductDetail(int ID)
_

したがって、_IEnumerable<ProductItems>_(たとえば、ProductItemsの配列)を返しますが、コントローラーアクションで、ReadAsAsync<ProductItems>()呼び出しで応答をoneProductItemsにデシリアライズしようとします

したがって、ReadAsAsyncを配列ProductItemsにデシリアライズするように変更すると、動作するはずです。

_var model = client
               .GetAsync(productDetailUrl)
               .Result
               .Content.ReadAsAsync<ProductItems[]>().Result;
_
15
nemesv

ASP.NET Webサイトが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を1つのプロジェクトでホストしている場合は、HTTPリクエストとシリアル化/逆シリアル化でこれらすべてを必要とせず、通常のクラスメソッドとしてメソッドを呼び出すだけです。

8
Regfor