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 配列 "(すなわち[1,2,3]) をタイプ ' ProductDetails.Models.ProductItems' にデシリアライズできません。逆シリアル化された型は、配列であるかIEnumerableICollectionまたはのようなコレクション インターフェイスを実装する必要がありますIList。JSON 配列を強制的に逆シリアル化するにはJsonArrayAttribute、型に を追加します。行 1、位置 1。」

誰かがこれを行うのを手伝ったり、別のより良い方法を提案したり、どこかで間違っている場合は修正したりできますか? 返されたデータをビューに表示する必要があります。データはコントローラーに返される必要があります。

4

2 に答える 2

15

例外が「 JSON配列をデシリアライズできません...」と述べているため、シリアル化を使用したWeb APIメソッドではなくデシリアライズなど、レシーバー側に問題があります。

そして、あなたの問題は、Web API メソッドが次のようになっているため、間違った型に逆シリアル化しようとすることです。

public IEnumerable<ProductItems> GetProductDetail(int ID)

したがって、IEnumerable<ProductItems>(たとえばの配列)が返されますが、コントローラーアクションでは、呼び出しを使用しProductItems応答を逆シリアル化しようとします ProductItemsReadAsAsync<ProductItems>()

したがってReadAsAsync、配列に逆シリアル化するように変更するProductItemsと、機能するはずです。

var model = client
               .GetAsync(productDetailUrl)
               .Result
               .Content.ReadAsAsync<ProductItems[]>().Result;
于 2012-10-05T08:02:12.200 に答える
8

ASP.NETWebサイトがWebAPIコントローラーと一緒にホストしている場合、HTTP要求に関連する遅延を回避するために、通常のクラスメソッドとしてWebAPIを呼び出すことができます。

そして、問題はWebAPI呼び出しにはありません。問題は、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.NETMVCサイトとASP.NETWeb APIを1つのプロジェクトでホストしている場合は、HTTP要求とシリアル化/逆シリアル化でこれらすべてを行う必要はなく、メソッドを通常のクラスメソッドとして呼び出すだけです。

于 2012-10-05T07:02:46.310 に答える