2017-10-04 53 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; 
    } 
} 

編輯:

GetAllComplaintsQuery.Handle方法是這樣的:

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 s是我ComplaintConfiguration

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

你能分享代碼嗎? – Marusyk

回答

0

兩個模型創建傘類,有你的get方法返回你想要什麼分別。

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

嘗試剛剛從行動

public ComplaintViewModel Get([FromODataUri] int key)

EnableQueryAttribute刪除[EnableQuery]使用OData的查詢語法啓用查詢。這是可接受的收集IQueryable<>。當你想返回單個實體時,不要使用該屬性。

最新通報

也嘗試重命名參數int keyid

+0

我已經刪除了[EnableQuery]屬性,但我仍然收到了'406 Not Acceptable'消息。 – Martijn

+0

@Martijn你怎麼稱呼它?看到這個https://stackoverflow.com/a/27191598/4275342 – Marusyk

+0

我修改了代碼,以便它完全符合描述,但我仍然得到一個406:/ – Martijn

1

你沒有包括您視圖模型類的定義,所以讓我先確保我們在同一頁上關於什麼你實際上正在努力實現。

它看起來像你想,當客戶端從參數少Get()但是當客戶從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)返回一個包含詳細另外一個記錄到其他兩個領域,也如預期。

我從來不需要更改控制器或WebApiConfig.cs的代碼,但必須與ccontroller匹配的builder.EntitySet<ComplaintTypeViewModel>("ComplaintOData");中的字符串參數(您的代碼中有"ComplaintTypeOData")。

由於它的工作,我試圖找出我怎麼能重現你406我已經改變了ComplaintViewModel直接擴展ComplaintTypeViewModel而不是延長ComplaintOverviewViewModel(請注意,我只是複製了Name屬性):

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; } 
} 

這工作得很好。

我可以複製你的406唯一的辦法是,當我改變了它的繼承層次的ComplaintViewModelComplaintTypeViewModel可言:

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; } 
} 

這次終於給我的406代碼GET /odata/ComplaintOData(1)GET /odata/ComplaintOData是仍然返回列表Id名稱就好。

因此,它看起來就像只要你視圖模型類爲所有builder.EntitySet<T>("name")延伸相同T你可以從Get()過載在你的控制器返回任何人。請檢查你是如何定義你的ViewModels

+0

謝謝。與此同時,我將我的代碼放在一個'ApiController'中。感謝這一點,我可以將代碼移回到'ODataController'。 – Martijn

+0

不幸的是。我認爲它有效,但是當你用odata查詢模型時它不起作用。你可以嘗試在Get()方法中添加'?%24orderby = CreationDate%20desc&%24top = 20&%24select = Id%2CSequenceNumber%2CCreationDate%2Customer%2CDescription&%24count = true'? PS:在我的開幕帖子中,ComplaintTypeViewModel應該是ComplaintViewModel – Martijn

+0

@Martijn,當然它的作品。你逃避太多了。您只需要轉義參數值而不是名稱:'?$ orderby = CreationDate%20desc&$ top = 20&$ select = Id%2cSequenceNumber%2cCreationDate%2cCustomer%2cDescription&$ count = true' –

相關問題