Skip to content

The model is null in POST method when api-version is not specified and AssumeDefaultVersionWhenUnspecified = true #745

Closed
@alisovoy

Description

@alisovoy

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:

NULL

If I change the type of parameter to object:

image

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

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions