C# 为什么我的HTTP帖子在添加Microsoft.AspNetCore.OData.Versioning后不再传递正文内容
我正在开发一个ASP.NET Core 2.2 API,该API通过Microsoft.AspNetCore.OData v7.1.0 NuGet实现OData。我一切正常,所以我决定通过Microsoft.AspNetCore.OData.Versioning v3.1.0添加API版本控制 现在,控制器中的GET和GET{id}方法可以正确地进行版本控制。例如,我可以使用URL访问get list端点方法C# 为什么我的HTTP帖子在添加Microsoft.AspNetCore.OData.Versioning后不再传递正文内容,c#,asp.net-core,odata,api-versioning,microsoft-odata,C#,Asp.net Core,Odata,Api Versioning,Microsoft Odata,我正在开发一个ASP.NET Core 2.2 API,该API通过Microsoft.AspNetCore.OData v7.1.0 NuGet实现OData。我一切正常,所以我决定通过Microsoft.AspNetCore.OData.Versioning v3.1.0添加API版本控制 现在,控制器中的GET和GET{id}方法可以正确地进行版本控制。例如,我可以使用URL访问get list端点方法 ~/api/v1/addresscompliancecodes 或 但是,当我尝试创
~/api/v1/addresscompliancecodes
或
但是,当我尝试创建一个新记录时,请求路由到控制器中的正确方法,但现在请求正文内容没有传递到POST控制器方法
我一直在遵循Microsoft.ApsNetCore.OData.Versioning中的示例
我的控制器中有HttpPost方法
[HttpPost]
[ODataRoute()]
public async Task<IActionResult> CreateRecord([FromBody] AddressComplianceCode record, ODataQueryOptions<AddressComplianceCode> options)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.Add(record);
await _context.SaveChangesAsync();
return Created(record);
}
它在控制器的HttpPost方法中与[FromBody]一起工作
然而,在遵循API版本控制OData GitHub中的示例时,我现在使用的是如下所示的配置类,而不是以前的模型生成器
public class AddressComplianceCodeModelConfiguration : IModelConfiguration
{
private static readonly ApiVersion V1 = new ApiVersion(1, 0);
private EntityTypeConfiguration<AddressComplianceCode> ConfigureCurrent(ODataModelBuilder builder)
{
var addressComplianceCode = builder.EntitySet<AddressComplianceCode>("AddressComplianceCodes").EntityType;
addressComplianceCode
.HasKey(p => p.Code)
.Filter()
.Count()
.Expand()
.OrderBy()
.Page() // Allow for the $top and $skip Commands
.Select();
return addressComplianceCode;
}
public void Apply(ODataModelBuilder builder, ApiVersion apiVersion)
{
if (apiVersion == V1)
{
ConfigureCurrent(builder);
}
}
}
如果相关,我在Startup.cs->ConfigureServices中有以下代码
// Add Microsoft's API versioning
services.AddApiVersioning(options =>
{
// reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
options.ReportApiVersions = true;
});
// Add OData 4.0 Integration
services.AddOData().EnableApiVersioning();
services.AddMvc(options =>
{
options.EnableEndpointRouting = false; // TODO: Remove when OData does not causes exceptions anymore
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
我觉得问题在于这个模型有点不匹配,但我不明白为什么不匹配
19年3月18日更新-其他信息
这是我的实体类
[Table("AddressComplianceCodes")]
public class AddressComplianceCode : EntityBase
{
[Key]
[Column(TypeName = "char(2)")]
[MaxLength(2)]
public string Code { get; set; }
[Required]
[Column(TypeName = "varchar(150)")]
[MaxLength(150)]
public string Description { get; set; }
}
和EntityBase类
public class EntityBase : IEntityDate
{
public bool MarkedForRetirement { get; set; }
public DateTimeOffset? RetirementDate { get; set; }
public DateTimeOffset? LastModifiedDate { get; set; }
public string LastModifiedBy { get; set; }
public DateTimeOffset? CreatedDate { get; set; }
public string CreatedBy { get; set; }
public bool Delete { get; set; }
public bool Active { get; set; }
}
这是邮递员的请求正文
{
"@odata.context": "https://localhost:44331/api/v1/$metadata#AddressComplianceCodes",
"Code": "Z1",
"Description": "Test Label - This is a test for Z1",
"Active": true
}
有什么想法吗?事实证明,问题在于我没有在Postman请求正文中使用camel-case作为我的属性名。这不仅仅是Microsoft.AspNetCore.Odata的问题,但一旦我添加了Microsoft.AspNetCore.Odata.Versioning NuGet包,它就失败了,属性名的开头字符为大写。似乎Microsoft.AspNetCore.Odata.Versioning使用了自己的MediaTypeFormatter,它支持小写。我在下面的GitHub帖子中发现了这一点 事实证明,问题在于我没有在Postman请求主体中使用camel-case作为属性名。这不仅仅是Microsoft.AspNetCore.Odata的问题,但一旦我添加了Microsoft.AspNetCore.Odata.Versioning NuGet包,它就失败了,属性名的开头字符为大写。似乎Microsoft.AspNetCore.Odata.Versioning使用了自己的MediaTypeFormatter,它支持小写。我在下面的GitHub帖子中发现了这一点 没有定制的MediaTypeFormatter,但是在3.0中,这种行为确实发生了变化,因为对于大多数基于JSON的API来说,使用驼峰大小写似乎是默认的。然而,这很容易恢复
modelBuilder.ModelBuilderFactory = () => new ODataConventionModelBuilder();
// as opposed to the new default:
// modelBuilder.ModelBuilderFactory = () => new ODataConventionModelBuilder().EnableLowerCamelCase();
这里也是您执行或更改与模型生成器相关的任何其他设置的地方。将调用factory方法根据API版本创建新的模型生成器
值得指出的是,您确实需要绘制两次路线图。出于演示目的,配置了by查询字符串和by URL路径。您应该选择一个或另一个,并删除未使用的一个
我希望这会有所帮助。没有定制的MediaTypeFormatter,但在3.0中,这种行为确实发生了变化,因为对于大多数基于JSON的API来说,使用驼峰大小写似乎是默认的。然而,这很容易恢复
modelBuilder.ModelBuilderFactory = () => new ODataConventionModelBuilder();
// as opposed to the new default:
// modelBuilder.ModelBuilderFactory = () => new ODataConventionModelBuilder().EnableLowerCamelCase();
这里也是您执行或更改与模型生成器相关的任何其他设置的地方。将调用factory方法根据API版本创建新的模型生成器
值得指出的是,您确实需要绘制两次路线图。出于演示目的,配置了by查询字符串和by URL路径。您应该选择一个或另一个,并删除未使用的一个
我希望这会有所帮助。您能为我们发布一个较小的可重复示例,以尝试重现您的问题吗?您能为我们发布一个较小的可重复示例,以尝试重现您的问题吗?
public class EntityBase : IEntityDate
{
public bool MarkedForRetirement { get; set; }
public DateTimeOffset? RetirementDate { get; set; }
public DateTimeOffset? LastModifiedDate { get; set; }
public string LastModifiedBy { get; set; }
public DateTimeOffset? CreatedDate { get; set; }
public string CreatedBy { get; set; }
public bool Delete { get; set; }
public bool Active { get; set; }
}
{
"@odata.context": "https://localhost:44331/api/v1/$metadata#AddressComplianceCodes",
"Code": "Z1",
"Description": "Test Label - This is a test for Z1",
"Active": true
}
modelBuilder.ModelBuilderFactory = () => new ODataConventionModelBuilder();
// as opposed to the new default:
// modelBuilder.ModelBuilderFactory = () => new ODataConventionModelBuilder().EnableLowerCamelCase();