2

OData Json 形式のデータを返すことができる唯一の方法であるため、ApiController の現在の実装から ODataController に移行しようとしています。(ここの問題と同じですが、解決策はうまくいきませんでした)

私は ODataController のワークアウトを試みてきましたが、これに従って十分に機能していることがわかりまし。ただし、私のプロジェクトは、単純な「~/odata/Entity」のデフォルトの OData ルーティングとは異なるルーティングを実装しています。名前が重複するコントローラーがいくつかあるため、コントローラーを領域にグループ化する必要があります。

thisthisに続いて、カスタム ルーティングを実装することができました。実行すると、適切なコントローラーに到達して正常に通過したようです。ただし、Fiddler ではまだエラーが発生します

「'ObjectContent`1' タイプは、コンテンツ タイプ 'application/json;odata=minimalmetadata; streaming=true; charset=utf-8' の応答本文をシリアル化できませんでした。」

内部例外あり

関連するエンティティ セットが OData パスから見つかりませんでした。ペイロードをシリアル化するには、関連するエンティティ セットが必要です

そして今、私は何時間もそれで立ち往生しています。ルート ハンドラーを使用せず、単に "~/odata/Entity" を介してデータにアクセスするだけで、私のコードは十分に機能します。コントローラー コードを通過した後に失敗するのは、カスタム ルーティングを実装したときだけです。

どんな助けでも大歓迎です。

ここにいくつかのコードがあります:

Global.asax:

            //Added this on App_Start
            config.Services.Replace(typeof(IHttpControllerSelector), new CustomHttpControllerSelector(config)); 

            //Snippet from RegisterRoutes
            ODataConventionModelBuilder modelBuilder = new ODataConventionModelBuilder();
            modelBuilder.EntitySet<Entity>("Entities");
            IEdmModel model = modelBuilder.GetEdmModel();

            config.Routes.MapODataRoute(
                routeName: "ODataDefault",
                routePrefix: "{version}/{area}/{controller}",     //Works since I could reach my controller
                model: model);

コントローラ:

        [HttpGet]
        [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
        public IQueryable<Entity> Get()
        {
            EntitySet entitySet = new EntitySet();
            return entitySet.Entities;
        }

CustomHttpControllerSelector:

これから継承されます。基本的に、これはリクエストを解析して特定のコントローラー記述子を取得するだけです。

private HttpControllerDescriptor GetController(HttpRequestMessage request)
        {
            HttpControllerDescriptor descriptor = null;

            IHttpRouteData routeData = request.GetRouteData();

            // Get variables from the route data.
            string versionName = null;
            routeData.Values.TryGetValue("version", out versionName );

            string areaName = null;
            routeData.Values.TryGetValue("area", out areaName);

            string controllerName = null;
            routeData.Values.TryGetValue("controller", out controllerName);

            string fullName = string.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}", versionName, areaName, controllerName);

            // Search for the controller.
            // _controllerTypes is a list of HttpControllerDescriptors
            var type = _controllerTypes.Where(t => t.Key.EndsWith(fullName, StringComparison.OrdinalIgnoreCase)).Select(t => t.Value).FirstOrDefault();

            if (type != null)
            {
                descriptor = new HttpControllerDescriptor(_configuration, controllerName, type);
            }

            return descriptor;
        }
4

1 に答える 1

2

routePrefix の {controller} 部分を削除し、カスタムIODataRoutingConventionを実装して、ルートの最初の解析でコントローラー値が検出されない場合にデフォルトのコントローラー値を入力するだけで、最終的にこれを解決しました。コードは次のとおりです。

public string SelectController(ODataPath odataPath, HttpRequestMessage request)
{
     string controllerName = ""

     //do stuff here to select controller

     return controllerName;
}

これは、ApiController のマップ ルーティングのデフォルトおよび制約パラメーターの長い代用であると推測しています。

RouteTable.Routes.MapHttpRoute(
    name: "RouteName",
    routeTemplate: "{version}/{area}/{controller}",
    defaults: new { controller = controllerName },
    constraints: new { version = v1 }
);

注:これを回答として投稿していますが、誰かがより良い説明を持っている場合は、確認します。:)

于 2013-09-12T04:38:11.677 に答える