Closed
Description
I have a small OData Api with one Controller:
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class AssetsController : ODataController
{
public IEnumerable<Asset> Get()
{
return Assets;
}
public Asset Get(string key)
{
return Assets.FirstOrDefault(a => a.Id == key);
}
public IActionResult Post([FromBody] Asset asset, ApiVersion version)
{
Assets.Add(asset);
return Ok();
}
[MapToApiVersion("2.0")]
public IActionResult Patch([FromODataUri] string key, Delta<Asset> assetDelta, ApiVersion version)
{
var asset = Assets.FirstOrDefault(a => a.Id == key);
if (asset != null)
{
assetDelta.Patch(asset);
}
return Ok();
}
private static readonly List<Asset> Assets = new List<Asset>()
{
new Asset() { Id = "1", Author = "Johny", Name = "Car", Data = "some data 01" },
new Asset() { Id = "2", Author = "Karl", Name = "Boat", Data = "some data 02" },
new Asset() { Id = "3", Author = "Ben", Name = "Plane", Data = "some data 03" },
};
}
Model:
public class Asset
{
public string Id { get; set; }
public string Name { get; set; }
public string Data { get; set; }
public string Author { get; set; }
}
public class AssetModelConfiguration : IModelConfiguration
{
private EntityTypeConfiguration<Asset> ConfigureCurrent(ODataModelBuilder builder)
{
return builder.EntitySet<Asset>("Assets").EntityType;
}
public void Apply(ODataModelBuilder builder, ApiVersion apiVersion, string routePrefix)
{
ConfigureCurrent(builder);
}
}
and the setup:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddApiVersioning(options =>
{
options.ReportApiVersions = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
options.ApiVersionReader = ApiVersionReader.Combine(new QueryStringApiVersionReader(), new HeaderApiVersionReader("api-version"));
});
services.AddOData().EnableApiVersioning();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, VersionedODataModelBuilder modelBuilder)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.Select().Expand().Filter().OrderBy().MaxTop(100).Count();
endpoints.MapVersionedODataRoute("ODataRoute", "odata", modelBuilder);
});
}
If I do a post JSON without specifying the api-version:
POST https://localhost:44354/odata/assets HTTP/1.1
Content-Type: application/json
{"id":"4","name":"Car4","data4":"some data 01","author":"Jan4"}
the default version is taken correctly, BUT model is null:
If I change the type of parameter to object:
the input parameter is not null but of type "System.Text.Json.JsonElement".
Why the json cannot be deserialized without specifying explicitly the api version?
if I add ?api-version=X.X everything works as expected and the input is nicely deserialized to the Asset model