AspNetCoreOData icon indicating copy to clipboard operation
AspNetCoreOData copied to clipboard

Custom ODataSerializerProvider never instanciated and its GetEdmTypeSerializer method not called

Open magneticcore opened this issue 8 months ago • 1 comments

Assemblies affected ASP.NET Core OData 8.2.4

Describe the bug In a webapi project, I would like to customize ODataSerializerProvider by deriving it in ODataCustomODataSerializerProvider class to serialize a custom type, ie Dictionary<int, List>, in OData, but the ODataCustomODataSerializerProvider is never instanciated.

Reproduce steps

public class ODataCustomODataSerializerProvider : ODataSerializerProvider
{
    public ODataCustomODataSerializerProvider(IServiceProvider serviceProvider):
        base(serviceProvider)
    {
    }
    public override IODataEdmTypeSerializer GetEdmTypeSerializer(IEdmTypeReference edmType)
    {
        if (edmType.FullName() == typeof(Dictionary<int, List<int>>).FullName)
        {
            // return Do something
        }
        return base.GetEdmTypeSerializer(edmType);
    }
} 

To initialize it in OData, the following instructions are used in Startup:

 option.AddRouteComponents(Configuration["Mvc:ApiName"], GetEdmModelV1(), builder =>
 {
     builder.AddSingleton<ODataSerializerProvider, ODataCustomODataSerializerProvider>();
 });

Then in a OData derived controller, I call its method GetTest():

class ODataTestController: ODataController {
        [HttpGet("GetTest()")]
        public IActionResult GetTest()
        {
            var a = new Dictionary<int, List<int>>();
            a.Add(10, new List<int>() { 20, 20, 20 });
            a.Add(20, new List<int>() { 30, 30, 30 });

            return Ok(new TestInfoDto() { GroupTypes = a });
        }
}

With TestInfoDto, complexe type:

    public class TestInfoDto
    {
        public Dictionary<int, List<int>> GroupTypes { get; set; } = new Dictionary<int, List<int>>();
    }

Rregistered in OData by:

builder.AddComplexType(typeof(TestInfoDto));

Expected behavior The method GetEdmTypeSerializer of the ODataCustomODataSerializerProvider must be called when OData needs to serialize data from the method GetTest() of derived ODataController.

What is wrong? Or what is missing?

magneticcore avatar Mar 18 '25 08:03 magneticcore

@magneticcore I created sample based on your codes and made it work as expected. Please check that at: https://github.com/xuzhg/WebApiSample/blob/main/IssuesOnWebApi/issue1444_CustomSerializerProvider/readme.md.

Be noted, OData works fine using the POCO class, however, the Dictionary is not a POCO class, is there any reason that you have to use the Dictionary<int, List<int>> to define the property.

Be noted for OData team, OData core vocabulary introduces the 'Core.Dictionary' as Open complex type. Consider to use this Edm complex type to build the C# dictionary meanwhile use the OpenPropertyConstraint to limit the key/value type of the Dictionary.

xuzhg avatar Mar 18 '25 17:03 xuzhg