如何解决.Net Core 3.1 Web Api的自定义OData DateTime序列化程序
我有一个带有数据模型对象的OData Api,该对象带有许多可为空的DateTime字段。
例如
public class Book : EntityBase
{
...
public DateTime? CreatedDate { get; set; }
public DateTime? UpdatedDate { get; set; }
...
}
使用OData API的客户端要求DateTime字段的格式为'yyyy-MM-dd'格式,而不是默认的长格式,例如'yyyy-MM-ddTHH:mm:ss'
public class CustomODataSerializerProvider : DefaultODataSerializerProvider
{
private readonly CustomODataEntityTypeSerializer _entityTypeSerializer;
public CustomODataSerializerProvider(IServiceProvider rootContainer)
: base(rootContainer)
{
_entityTypeSerializer = new CustomODataEntityTypeSerializer(this);
}
public override ODataEdmTypeSerializer GetEdmTypeSerializer(Microsoft.OData.Edm.IEdmTypeReference edmType)
{
if (edmType.Definition.TypeKind == EdmTypeKind.Entity || edmType.Definition.TypeKind == EdmTypeKind.Complex)
return _entityTypeSerializer;
else
return base.GetEdmTypeSerializer(edmType);
}
}
public class CustomODataEntityTypeSerializer : ODataResourceSerializer
{
public CustomODataEntityTypeSerializer(ODataSerializerProvider provider)
: base(provider) { }
public override Microsoft.OData.ODataProperty CreateStructuralProperty(Microsoft.OData.Edm.IEdmStructuralProperty structuralProperty,ResourceContext resourceContext)
{
var property = base.CreateStructuralProperty(structuralProperty,resourceContext);
if (property.Name.Contains("Date"))
{
property.Value = ((DateTime)property.Value).ToShortDateString();
}
return property.Value != null ? property : null;
}
}
我还尝试了“ property.Value =((DateTimeOffset)property.Value).DateTime.ToShortDateString();”而不是上面的。
然后使用来注册该序列化器
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.EnableDependencyInjection();
endpoints.Select().Expand().OrderBy().Filter().Count().MaxTop(10);
endpoints.MapODataRoute("odata","odata",a =>
{
a.AddService(Microsoft.OData.ServiceLifetime.Singleton,typeof(IEdmModel),sp => GetEdmModel(app.ApplicationServices));
a.AddService(Microsoft.OData.ServiceLifetime.Singleton,typeof(ODataSerializerProvider),sp => new CustomODataSerializerProvider(sp));
});
//endpoints.MapODataRoute("odata",GetEdmModel(app.ApplicationServices));
});
但是在调用OData端点时出现此错误
can't parse JSON. Raw result:
{"@odata.context":"https://localhost:5000/odata/$metadata#Book","value":[
我也尝试应用Json序列化器,但这对从OData端点提供的数据没有影响:
services
.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.IgnoreNullValues = false;
options.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
public class DateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader,Type typeToConvert,JsonSerializerOptions options)
{
Debug.Assert(typeToConvert == typeof(DateTime));
return DateTime.Parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer,DateTime value,JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy-MM-dd"));
}
}
我在.NET Core 3.1 Web Api中使用Microsoft.AspNetCore.OData 7.4.1。对于如何更改通过OData API提供的数据的DateTime格式/序列化的任何建议,将不胜感激。
解决方法
声明EDM时,您可以标记要使用Button federal;
private Object parliamonar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_federalparliamentary);
federal = findViewById(R.id.back160);
federal.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent reserve = new Intent(getApplicationContext(),parliamonar.class);
startActivity(reserve);
}
});
federal = findViewById(R.id.next164);
federal.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent reserve = new Intent(getApplicationContext(),sar.class);
startActivity(reserve);
}
});
}
public void onClick(View V) {
Intent back = new Intent((Context) parliamonar,federalparliamentary.class);
startActivity(back);
}
格式进行反序列化的特定字段,例如:
Edm.Date
对于诸如以下的简单控制器:
public static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EnableLowerCamelCase();
builder.EntitySet<Book>("Book");
builder.EntityType<Book>().Property(p => p.CreatedDate).AsDate();
builder.EntityType<Book>().Property(p => p.UpdatedDate).AsDate();
return builder.GetEdmModel();
}
您可以看到使用YYYY-MM-DD格式序列化的namespace WebAPI.Controllers
{
[ApiController]
[Route("[controller]")]
public class BookController : ControllerBase
{
private static readonly List<Book> Books = new List<Book>
{
new Book() {
BookId = 1,CreatedDate = new DateTime(2020,01,02),UpdatedDate = new DateTime(2020,02,03)
},new Book() {
BookId = 2,CreatedDate = null,UpdatedDate = null
},};
[EnableQuery]
public IEnumerable<Book> Get()
{
var result = Books.ToArray();
return result;
}
}
}
字段:
DateTime?
并且https:// localhost:5001 / odata / $ metadata XML声明这些字段的类型为{
"@odata.context": "https://localhost:5001/odata/$metadata#Book","value": [
{
"createdDate": "2020-01-02","updatedDate": "2020-02-03","bookId": 1
},{
"createdDate": null,"updatedDate": null,"bookId": 2
}
]
}
:
Edm.Date
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。