AutoMapper / AutoMapper.Extensions.OData

Creates LINQ expressions from ODataQueryOptions and executes the query.
MIT License
140 stars 38 forks source link

When using $expand asp.net core does not return the expanded collection #95

Closed mlop3s closed 3 years ago

mlop3s commented 3 years ago

Hi,

i've adapted an existing asp.net based rest api and although the query seems to work, the controller is not returning the expanded collection.

The Get is done like this:

[HttpGet("projects/{projectId}/issues", Name = "GetOdataGeminiIssues")]
[Produces("application/json")]
[ProducesResponseType(typeof(IQueryable<GeminiIssue>), Status200OK)]
[ProducesResponseType(Status400BadRequest)]
public async Task<IActionResult> GetGeminiIssues(long projectId, ODataQueryOptions<GeminiIssue> options)
        {
            var issues = await _geminiRepository
                    .GetQueryableIssues(projectId)
                    .GetQueryAsync(_mapper, options, new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = HandleNullPropagationOption.False } });

            return Ok(issues);
        }

The EDM Model. I had only builder.EntitySet("projects"); before, i've tried to define the relations to see if it works but no success there:

        private static IEdmModel GetEdmModel()
        {
            var builder = new ODataConventionModelBuilder();
            var issue = builder.EntityType<GeminiIssue>().Expand(10).Filter().Count().Select().Page();
            issue.HasMany<GeminiIssueHistory>(x => x.HistoryItems);
            issue.HasMany<GeminiCustomField>(x => x.CustomFields);
            builder.EntitySet<GeminiIssue>("projects");

            builder.EntitySet<GeminiIssueHistory>(nameof(GeminiIssueHistory));
            builder.EntitySet<GeminiCustomField>(nameof(GeminiCustomField));
            return builder.GetEdmModel();
        }

The models - this are the DTOs that i map to from EF Core.

    public class GeminiIssue
    {
        [Key]
        public decimal IssueId { get; set; }

        //... more properties

        public ICollection<GeminiIssueHistory>? HistoryItems { get; set; }

        public ICollection<GeminiCustomField>? CustomFields { get; set; }
    }

    public class GeminiIssueHistory
    {
        [Key]
        public decimal HistoryId { get; set; }

       //... more properties, however no link back to GeminiIssue
    }

The end points:

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();                
                endpoints.MapODataRoute("odata", "odata", GetEdmModel(), new DefaultODataBatchHandler());
                endpoints.Filter().OrderBy().Expand().Select().MaxTop(null);
            });

My request is straightforward: http://localhost:45179/odata/projects/184/issues?$expand=HistoryItems&$top=1

But I get no expansions:

{
    "@odata.context": "http://localhost:45179/odata/$metadata#Collection(Gemini.Shared.Models.GeminiIssue)",
    "value": [
        {
            "@odata.type": "#Gemini.Shared.Models.GeminiIssue",
            "IssueId": 90318,
            "IssueTypeId": 101,
            "ReportedById": 179,
            "Sprint": "",
            "CreatedDate": "2021-01-18T00:00:00+01:00",
            "AcceptedDate": null,
            "ResolvedDate": null,
            "ClosedDate": null,
            "ProjectId": 184,
            "Summary": "Some issue",
            "IssueResolutionId": 1,
            "IssueStatusId": 17,
            "IssueKey": "ISSUE-90318",
            "Version": null,
            "Description": "",
            "Status": "taken",
            "IssueUri": null
        }
    ]
}

And the packages:

    <PackageReference Include="AutoMapper.AspNetCore.OData.EFCore" Version="2.1.1" />
    <PackageReference Include="AutoMapper.Extensions.ExpressionMapping" Version="4.1.1" />
    <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.OData" Version="7.5.6" />
    <PackageReference Include="Microsoft.AspNetCore.OData.Versioning.ApiExplorer" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.0" />

The strange thing is that if i execute the query, it shows me that the expanded items are there, but they do not reach the client:

image

Is this a asp.net odata issue?

Thanks, Marco

BlaiseD commented 3 years ago

Correct.

If the data back is being returned to the controller then the problem should be unrelated to this library. Comparing your controller and OData configuration to our samples might help.