是否可以在ODataController中返回不同的模型? [英] Is it possible to return different models in an ODataController?

查看:75
本文介绍了是否可以在ODataController中返回不同的模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在OData v4控制器中,是否可以为 Get() Get([FromIDataUri]键)返回不同的模型?

IN a OData v4 Controller, is it possible to return different models for the Get() and the Get([FromIDataUri] key)?

我喜欢使用ViewModels,并且当使用 Get()方法时,我想返回一个 xxxOverviewViewModel .使用 Get([FromIDataUri]键)方法时,我想返回xxxViewModel.

I like to use ViewModels, and when using the Get() method I'd like to return an xxxOverviewViewModel. When using the Get([FromIDataUri] key) method, I'd like to return a xxxViewModel.

这可能吗?如果可以,怎么办?

Is this possible, and if so, how?

我试图返回不同的模型,但是我总是得到 406 Acceptable .

I've tried to return different models, but I always get a 406 Acceptable.

Webapi.config:

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

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

这是我的 ComplaintConfiguration

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

推荐答案

您没有包含 ViewModel 类的定义,因此让我首先确保我们在同一页面上了解您的内容实际上是在努力实现.

You did not include definitions for your ViewModel classes, so let me first make sure we're on the same page regarding what you're actually trying to achieve.

当客户端从无参数的 Get()中请求投诉记录列表时,但是在客户端请求时,您似乎想返回一些受限字段您要包括其他字段的 Get([FromODataUri] int key)方法中的特定投诉.

It looks like you want to return some restricted set of fields when client requests a list of Complaint records from the parameters-less Get() but when the client requests a specific complaint from Get([FromODataUri] int key) method you want to include additional fields.

我使用以下层次结构为该假设建模:

I modeled this assumption using the following hierarchy:

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

Ran测试, GET/odata/ComplaintOData 返回了仅包含 Id Name 的列表, GET/odata/同样,按预期,ComplaintOData(1)返回了一条包含 Details 的记录,另外两个字段也是如此.

Ran tests, GET /odata/ComplaintOData returned a list with just Id and Name as expected, GET /odata/ComplaintOData(1) returned a single record containing Details in addition to the other two fields, also as expected.

除了在 builder.EntitySet< ComplaintTypeViewModel>("ComplaintOData"); 中的字符串参数外,我无需为控制器或 WebApiConfig.cs 更改代码.必须与ccontroller匹配(您的代码中有"ComplaintTypeOData" ).

I never had to change your code for the controller or the WebApiConfig.cs except the string parameter in builder.EntitySet<ComplaintTypeViewModel>("ComplaintOData"); which had to match the ccontroller (you have "ComplaintTypeOData" in your code).

自从开始工作以来,我试图弄清楚如何重现406.我已经更改了 ComplaintViewModel 以直接扩展 ComplaintTypeViewModel 而不是扩展 ComplaintOverviewViewModel (请注意,我刚刚复制了 Name 属性):

Since it worked, I tried to figure out how I can reproduce your 406. I've changed ComplaintViewModel to extend ComplaintTypeViewModel directly instead of extending ComplaintOverviewViewModel (note that I've just duplicated the Name property):

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的方法是,当我将 ComplaintViewModel 更改为时,其继承层次结构中完全没有 ComplaintTypeViewModel :

The only way I could reproduce your 406 is when I changed the ComplaintViewModel to not have ComplaintTypeViewModel in its inheritance hierarchy at all:

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代码,而 GET/odata/ComplaintOData 仍返回带有 Id 名称就可以了.

This finally gave me the 406 code from GET /odata/ComplaintOData(1) while GET /odata/ComplaintOData was still returning the list with Id and Name just fine.

因此,只要您的 ViewModel 类的 all 都从 builder.EntitySet< T>("name"),您可以从控制器的 Get()重载中返回任何一个.请检查您如何定义 ViewModels

So, it looks like as long as all of your ViewModel classes extend the same T from builder.EntitySet<T>("name") you can return any of them from Get() overloads in your controller. Please check how you define your ViewModels

这篇关于是否可以在ODataController中返回不同的模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆