Using DTO's with OData & Web API

若如初见. 提交于 2019-12-04 01:54:37

I never really managed to work this one out. The ToNavigationPropertyArray() extension method helps a little, but does not handle infinite depth navigation.

The real solution is to create Actions or Functions to allow clients to request data requiring a more complicated query.

The other alternative is to make multiple smaller/simple calls then aggregate the data on the client, but this isn't really ideal.

Ovidiu Buligan

I have created an Automapper explicit navigation expansion utility function that should work with N-deph expands. Posting it here since it might help someone.

public List<string> ProcessExpands(IEnumerable<SelectItem> items, string parentNavPath="")
{
    var expandedPropsList = new List<String>();
    if (items == null) return expandedPropsList;

    foreach (var selectItem in items)
    {
        if (selectItem is ExpandedNavigationSelectItem)
        {
            var expandItem = selectItem as ExpandedNavigationSelectItem;
            var navProperty = expandItem.PathToNavigationProperty?.FirstSegment?.Identifier;

            expandedPropsList.Add($"{parentNavPath}{navProperty}");                    
            //go recursively to subproperties
            var subExpandList = ProcessExpands(expandItem?.SelectAndExpand?.SelectedItems, $"{parentNavPath}{navProperty}.");
            expandedPropsList =  expandedPropsList.Concat(subExpandList).ToList();
        }
    }
    return expandedPropsList;
}

You can call it with :

var navExp = ProcessExpands(options?.SelectExpand?.SelectExpandClause?.SelectedItems)

it will return a list with ["Parent" ,"Parent.Child"]

When you want to mark something for explicit expansion in AutoMapper, you need to also opt-back-in when calling ProjectTo<>().

// map
cfg.CreateMap<SalesOrderHeader, SalesOrderDto>()                
   .ForMember(dest => dest.SalesOrderLines, opt => opt.ExplicitExpansion());

// updated controller
[EnableQuery]
public IQueryable<SalesOrderDto> Get()
{
    return _dbContext.SalesOrders
        .ProjectTo<SalesOrderDto>(
            AutoMapperConfig.Config, 
            so => so.SalesOrderLines,
            // ... additional opt-ins
        );
}

While the AutoMapper wiki does state this, the example is perhaps a little misleading by not including the paired ExplicitExpansion() call.

To control which members are expanded during projection, set ExplicitExpansion in the configuration and then pass in the members you want to explicitly expand:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!