【问题标题】:ASP.NET Core API oData and API layer modelASP.NET Core API oData 和 API 层模型
【发布时间】:2019-10-15 02:51:19
【问题描述】:

我需要在 ASP.NET Core 应用程序中为我的 API 端点使用 OData,但所有示例都是关于直接使用数据模型类。在我的应用架构中,我有服务层,该服务的方法返回 DTO 类,然后映射到 API 视图类。

我的数据类(基础设施层):

public partial class Carrier : BaseEntity
{
    public string Name { get; set; }
    public string Code { get; set; }
    public string UsDotNumber { get; set; }
    public string McNumber { get; set; }

我的 DTO 课程:

public class CarrierBaseDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Code { get; set; }
    public string Fein { get; set; }
    public string McNumber { get; set; }

我的演示文稿(API)类:

public class CarrierAPI
{
    [JsonProperty(PropertyName = "name")]
    public string Name { get; set; }
    [JsonProperty(PropertyName = "code")]
    public string Code { get; set; }
    [JsonProperty(PropertyName = "fein")]
    public string Fein { get; set; }
    [JsonProperty(PropertyName = "mcNumber")]
    public string McNumber { get; set; }

我的服务方式:

    public List<CarrierBaseDto> SearchCarriersDto()
    {
        var query = _context.Carriers
            .Where(c => !c.Deleted);

        IQueryable<CarrierBaseDto> queryDto = query.ProjectTo<CarrierBaseDto>(_mapperConfig);
        return queryDto.ToList();
    }

我的控制器方法:

    [HttpGet]
    [Route("GetAll")]
    public IActionResult GetAll()
    {
        var carriers = _carrierService.SearchCarriersDto();
        var carriersApi = _mapper.Map<List<CarrierElementAPI>>(carriers);
        return new OkObjectResult(carriersApi);
    }

我想添加使用$orderBy$filter$fields 参数的能力。如何将其添加到我当前的架构中?

【问题讨论】:

    标签: c# api odata asp.net-core-2.0 asp.net-core-webapi


    【解决方案1】:

    我认为当他们最初设计 OData 时,它不打算在没有 DDD 的情况下使用,因为元数据应该允许您处理过滤器等,现在这对使用它造成了一定的限制。

    有一些 hacky 解决方法,但它们只能部分起作用。我能想到的最接近您可以做的事情是通常接受查询选项并应用它们,然后使用自动映射器投影到您的可查询项,

    唯一的问题是在您的自动映射器设置中从实体到 DTO 的映射不能复杂,必须通过表达式映射进行设置

    public Object[] Get(ODataQueryOptions<ProductDTO> options)
    {
        ODataQuerySettings settings = new ODataQuerySettings()
        {
            PageSize = 5
        };
    
        IQueryable results = options.ApplyTo(_products.AsQueryable().ProjectTo<ProductDTO>(), settings);
    
        results.ToArray()
    }
    

    【讨论】:

    • 那么如何使用$fields参数来实现呢?
    • 您可以/不能,您可以返回一个 Object[],但如果您正在过滤字段,您在技术上不会返回 DTO。
    • @OlegSh 我最初试图沿着这条路走下去,最终我只是说了算,决定只对实体进行操作。这是您可以获得的最接近您想要的东西,但它有其自身的局限性。如果我已经回答了您的问题,请标记为完成
    • 但实际上有时数据实体类可能无法通过 API 返回,因为它可能具有虚拟属性等...
    • 是的,但只有这几个选项,要么让你的数据符合 api,要么让你的 api 符合数据。或者您可以实现自己的动态过滤器
    猜你喜欢
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 2021-08-09
    相关资源
    最近更新 更多