0

従来のWeb API 2データコントローラをOData v4スタイルのデータコントローラに移行する必要があります。これは、標準の1対1のテーブル間エンティティの関係では非常に簡単に機能しますが、データコントローラの応答にいくつかの異なるテーブル(実際の制約がない)を使用する必要があります。私はWebAPI.configファイルにこの新しいカスタム "エンティティ"を登録する方法を考え出すのに問題があります。Web API 2用のカスタムエンティティを作成する方法ODataデータコントローラ

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web.Http; 
using MyProject.Models; 

namespace MyProject.DataControllers 
{ 
    public class OrderDetailsController : ApiController 
    { 
     public OrderDetails GetOrderDetails(int id) 
     { 
      var ctx = new MyDatabaseEntities(); 
      var details = new OrderDetails(); 
      var order = ctx.Orders.FirstOrDefault(o => o.orderID == id); 
      if (order == null) 
      { 
       return details; //return an empty details object to the UI and abandon this code 
      } 

      //Data objects necessary for the order details page 
      IEnumerable<orderCertification> coupons = ctx.Coupons; 
      var importances  = ctx.OrderImportances.Where(x => x.ImportanceId == order.ImportanceId).Where(x => (x.Type == "IMPORTANCES")) ?? null; 
      var rankings  = ctx.OrderImportances.Where(x => x.ImportanceId == order.ImportanceId).Where(x => (x.Type == "RANK")) ?? null; 
      var profits   = ctx.OrderImportances.Where(x => x.ImportanceId == order.ImportanceId).Where(x => (x.Type == "PROFIT")) ?? null; 
      var address   = ctx.CustomerAddress.Where(c => c.OrderId == order.Id) ?? null; 
      var email   = ctx.CustomerEmail.Where(c => c.Id == order.Id).Where(x => x.Type == "EMAIL") ?? null;   
      var giftcards  = ctx.GiftCardAssignments.Where(c => c.CardID == order.CardID).FirstOrDefault().ToList() ?? null; 
      var customerCoupons = coupons.Where(c => giftCards.Any(o => o.GiftCardID == c.Id)).OrderBy(c => c.CouponName) ?? null; 

      //lots of other fun and crazy properties get set here!! etc etc. 

      //Set the order details properties 
      details.OrderImportances = importances; 
      details.OrderRankings  = rankings; 
      details.OrderProfits  = profits; 
      details.OrderAddress  = address; 
      details.OrderEmail   = email; 
      details.OrderGiftCards  = giftcards; 
      details.OrderCoupons  = customerCoupons; 
      details.OrderDescription = "This is my order description string."; 

      return details; 
     } 
    } 
} 

そしてここにある:ここで

using System.Linq; 
using System.Web.Http; 
using System.Web.OData.Builder; 
using System.Web.OData.Extensions; 
using System.Web.OData.Routing; 
using System.Web.OData.Routing.Conventions; 
using MyProject.Models; 

namespace MyProject 
{ 
    public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      // Web API configuration and routes 
      config.MapHttpAttributeRoutes(); 

      //OData configuration 
      ODataModelBuilder builder = new ODataConventionModelBuilder(); 
      builder.EntitySet<Order>("orders"); 
      builder.EntitySet<Customer>("customers"); 

      //what goes here for my "custom" entity? 

      var _model = builder.GetEdmModel(); 
      var defaultConventions = ODataRoutingConventions.CreateDefaultWithAttributeRouting(config, _model); 

      //var defaultConventions = ODataRoutingConventions.CreateDefault(); 
      var conventions = defaultConventions.Except(
        defaultConventions.OfType<MetadataRoutingConvention>()); 

      config.MapODataServiceRoute(
       routeName: "ODataRoute", 
       routePrefix: "api", 
       routingConventions: conventions, 
       pathHandler: new DefaultODataPathHandler(), 
       model: _model);   

      //ensure JSON responses 
      var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml"); 
      config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType); 
     } 
    } 
} 

は私のWeb API 2データコントローラがどのように見えるかの例です。ここで

は私WebAPIconfig.csがどのように見えるかの例です。私のOrderDetails()クラスの現在の外観の例:

using System.Collections.Generic; 

namespace MyProject.Models 
{ 
    public class OrderDetails 
    { 

     public IEnumerable<OrderImportance> OrderImportances { get; set; } 
     public IEnumerable<OrderImportance> OrderRankings { get; set; } 
     public IEnumerable<OrderImportance> OrderProfits { get; set; } 
     public string OrderAddress { get; set; } 
     public string OrderEmail { get; set; } 
     public IEnumerable<OrderGiftCard> OrderGiftCards { get; set; } 
     public IEnumerable<OrderCoupon> OrderCoupons { get; set; } 
     public string OrderDescription { get; set; } 

    } 
} 

私はどのようにODataを作るのですか?このWeb APIコントローラーのバージョン、およびWebAPIConfig.csのOrderDetailsクラスを登録するにはどうすればよいですか?

答えて

1

OrderDetailsは、キープロパティを持っていないようです。したがって、エンティティ・タイプ(キーを持つ名前付き構造化タイプ)ではなく、複合タイプ(一連のプロパティーからなるキーレス・ネーミング構造タイプ)です。

複合型は独自の識別情報(キー)を持たないため、ODataサービスのエンティティセットとして公開することはできません。つまり、OrderDetailsをモデルビルダーに設定したり、OrderDetailsのコントローラを別に作成したりすることはありません。

既存のGetOrderDetailsメソッドをODataに移行する最も簡単な方法は、ordersエンティティセットにバインドされたOData functionとして再定義することです。 Actions and Functions in OData v4 Using ASP.NET Web API 2.2は、OData関数の定義と構成に関する優れたチュートリアルを提供しますが、ここで必要なことの要点があります。

WebApiConfig.Registerに関数を宣言:

builder.EntityType<Order>().Function("GetOrderDetails").Returns<OrderDetails>(); 

ordersエンティティ・セットのコントローラ内の関数を定義する:

GET http://host/api/orders(123)/Default.GetOrderDetails 
次のよう

public class OrdersController : ODataController 
{ 
    // Other methods for GET, POST, etc., go here. 

    [HttpGet] 
    public OrderDetails GetOrderDetails([FromODataUri] int key) 
    { 
     // Your application logic goes here. 
    } 
} 

最後に、関数を呼び出します

Defaultがデフォルトのn通常はバインドされた関数を呼び出すときに必要となるサービスのスペースです。これを変更するには、builder.Namespaceを設定するか、config.EnableUnqualifiedNameCall(true)を使用して修飾されていない関数呼び出しを有効にすることができます。

+0

美しいです。私は設定でEnableUnqualifiedNameCall(true)を使用して終了しました。私のapi呼び出しは次のようになります:/ api/orders(250)/ GetOrderDetails /これは華麗です!実装も非常に簡単です。説明ありがとう。 – AussieJoe

+0

参考にして、私は自分自身を15アップして自分をアップアップします。 – AussieJoe

関連する問題