2017-10-04 3 views
2

OData v4コントローラでは、Get()Get([FromIDataUri] key)の異なるモデルを返すことはできますか?ODataControllerで異なるモデルを返すことは可能ですか?

私はViewModelsを使いたいのですが、Get()メソッドを使用している場合はxxxOverviewViewModelを返したいと思います。 Get([FromIDataUri] key)メソッドを使用する場合は、xxxViewModelを返したいと思います。

これは可能ですか?あれば、どうですか?

私は別のモデルを返そうとしましたが、私はいつも406 Acceptableを取得します。

Webapi.config:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     config.EnableCors(); 

     config.MapODataServiceRoute("ODataRoute", "odata", GetEdmModel()); 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 

     config.Filter().Expand().Select().OrderBy().MaxTop(null).Count(); 
    } 

    private static IEdmModel GetEdmModel() 
    { 
     var builder = new ODataConventionModelBuilder(); 
     builder.EntitySet<ComplaintViewModel>("ComplaintOData"); 
     return builder.GetEdmModel(); 

    } 
} 

ComplaintODataController

public class ComplaintODataController : ODataController 
{ 
    private readonly QueryProcessor _queryProcessor; 

    public ComplaintODataController(QueryProcessor queryProcessor) 
    { 
     _queryProcessor = queryProcessor; 
    } 

    [EnableQuery] 
    public IQueryable<ComplaintOverviewViewModel> Get() 
    { 
     var result = _queryProcessor.Handle(new GetAllComplaintsQuery()); 
     return result; 
    } 

    // WHEN CALLING THIS METHOD I GET A 406: 
    [EnableQuery] 
    public ComplaintViewModel Get([FromODataUri] int key) 
    { 
     var result = _queryProcessor.Handle(new GetComplaintByIdQuery { Id = key }); 
     return result; 
    } 
} 

EDIT:

public IQueryable<ComplaintOverviewViewModel> Handle(GetAllComplaintsQuery query) 
{ 
    // .All is an IQueryable<Complaint> 
    var result = _unitOfWork.Complaints.All.Select(c => new ComplaintOverviewViewModel 
    { 
     ComplaintType = c.ComplaintType.Description, 
     CreationDate = c.CreationDate, 
     Customer = c.Customer, 
     Description = c.Description, 
     Id = c.Id, 
     SequenceNumber = c.SequenceNumber, 
     Creator = c.Creator.Name 
    }); 

    return result; 
} 

とTHI:

マイGetAllComplaintsQuery.Handle方法は、次のようになりますSは両方のモデルのための傘のクラスを作成し、getメソッドは、あなたが望むものをそれぞれ返す必要があり、私のComplaintConfiguration

public class ComplaintConfiguration : EntityTypeConfiguration<Complaint> 
{ 
    public ComplaintConfiguration() 
    { 
     Property(p => p.SequenceNumber).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed); 
     Property(p => p.Description).IsRequired(); 
    } 
} 
+0

コードを共有できますか? – Marusyk

答えて

0

です。ただ、アクションから

public ComplaintViewModel Get([FromODataUri] int key)

EnableQueryAttribute[EnableQuery]を削除する

public class myMainModel 
{ 
    public xxxOverviewViewModel x {get;set;} 
    public xxxOverviewViewModel y {get;set;} 
} 

myMainModel Get() 
{ 
    .... 
    return myMainModel.x; 
} 

myMainModel Get(int key) 
{ 
    .... 
    return myMainModel.y; 
} 
+0

@apemene私はこれを試しましたが、私のモデルにはキーが定義されていないという例外があります。この例外は 'WebApiConfig.cs'の' return builder.GetEdmModel'でスローされます。 'builder.EntitySet (" ComplaintOData ");' – Martijn

0

てみたODataクエリ構文を使用して照会することができます。コレクションの場合はIQueryable<>です。単一のエンティティを返す場合は、その属性を使用しないでください。

UPDATESまた

あなたののViewModelクラスの定義が含まれていなかったパラメータint keyid

+0

私は '[EnableQuery]'属性を削除しましたが、まだ '406 Not Acceptable'メッセージが出ます。 – Martijn

+0

@Martijnどのように呼びますか?これを参照してくださいhttps://stackoverflow.com/a/27191598/4275342 – Marusyk

+0

私はそれが記載されているとおりに正確に一致するようにコードを修正しましたが、私はまだ406を取得します:/ – Martijn

1

に名前を変更しようとするので、私が最初に私たちはに関する同じページにしていることを確認してみましょうどのようなあなたは実際に達成しようとしています。

あなたは、クライアントがGet()パラメータ-lessから苦情レコードのリストを要求したときには、クライアントは、追加のフィールドを含めるGet([FromODataUri] int key)方法から特定の苦情を要求するときにフィールドのいくつか制限されたセットを返すようにしたいように見えます。

私は、次の階層使ってこの仮定をモデル化:

public class ComplaintTypeViewModel 
{ 
    public int Id { get; set; } 
} 

public class ComplaintOverviewViewModel : ComplaintTypeViewModel 
{ 
    public string Name { get; set; } 
} 

public class ComplaintViewModel : ComplaintOverviewViewModel 
{ 
    public string Details { get; set; } 
} 

を期待通りにGET /odata/ComplaintODataがちょうど同上名前でリストを返され、テストを実施しました、GET /odata/ComplaintOData(1)はほかに詳細を含む単一のレコードを返さ他の2つのフィールドにも期待どおりに表示されます。

builder.EntitySet<ComplaintTypeViewModel>("ComplaintOData");の文字列パラメータ(コードに"ComplaintTypeOData"がある)と一致していた文字列パラメータを除いて、コントローラまたはWebApiConfig.csのコードを変更する必要はありませんでした。

それが働いていたので、私は(私はちょうどNameプロパティを複製してきたことに注意)の代わりにComplaintOverviewViewModelの延長の直接ComplaintTypeViewModelを拡張するためにComplaintViewModelを変更したあなたの406を再現できる方法を見つけ出すことを試みた:

public class ComplaintTypeViewModel 
{ 
    public int Id { get; set; } 
} 

public class ComplaintOverviewViewModel : ComplaintTypeViewModel 
{ 
    public string Name { get; set; } 
} 

public class ComplaintViewModel : ComplaintTypeViewModel 
{ 
    public string Name { get; set; } 
    public string Details { get; set; } 
} 

これもうまくいきました。 GET /odata/ComplaintODataがあった

public class ComplaintTypeViewModel 
{ 
    public int Id { get; set; } 
} 

public class ComplaintOverviewViewModel : ComplaintTypeViewModel 
{ 
    public string Name { get; set; } 
} 

public class ComplaintViewModel 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Details { get; set; } 
} 

はこれが最終的にGET /odata/ComplaintOData(1)から私に406コードを与えた:私はComplaintViewModelないに全くその継承階層にComplaintTypeViewModelを持って変更されたとき、私はあなたの406を再現することができ

唯一の方法ですIdの名前を返しています。名前はです。

だから、それは限りクラスは、あなたのコントローラでGet()過負荷からそれらのいずれかを返すことができbuilder.EntitySet<T>("name")から同じTを拡張し、あなたののViewModelのすべてなどのように見えます。 ViewModels

+0

ありがとうございます。その間、私は自分のコードを 'ApiController'に入れました。これにより、コードを 'ODataController'に戻すことができます。 – Martijn

+0

残念ながら。私はそれが働いたと思ったが、odataを使ってモデルをクエリするとうまくいきません。 '%24orderby = CreationDate%20desc&%24top = 20&%24select = Id%2CSequenceNumber%2CCreationDate%2CCustomer%2CDescription&%24count = true'を' Get() 'メソッドに追加してみませんか? PS:私の最初の投稿では、ComplaintTypeViewModelはComplaintViewModelでなければなりません – Martijn

+0

@Martijn、もちろん動作します。あなたはあまりにもエスケープしています。 '$ orderby = CreationDate%20desc&$ top = 20&$ select = Id%2cSequenceNumber%2cCreationDate%2cCustomer%2cDescription&$ count = true' –

関連する問題