我正在使用 ASP.NET Web Api 和 ApiController 创建 API。需要将所有日期时间值调整为 utc。假设有一个模型
public class Product
{
public string Name { get; set; }
public DateTime Created { get; set; }
}
和控制器:
[ApiController]
public class SomeController : ControllerBase
{
[HttpPost]
[Route("api/profucts")]
public async Task<ActionResult> Create(Product product)
{
//.... do smth
return Ok();
}
有没有办法插入模型类的 DateTime 属性的绑定并在那里做一些调整?
创建自定义日期时间模型绑定器并通过
...config.ModelBinderProviders.Insert(0, new MyDateTimeBinderProvider());
全局注册它不起作用,因为模型绑定器永远不会被击中。
创建自定义日期时间模型绑定器并在全局注册 通过 ...config.ModelBinderProviders.Insert(0, new MyDateTimeBinderProvider());不起作用,因为模型活页夹永远不会得到 命中
根据您的场景和描述,您似乎无法点击您的模型活页夹。要在您的 MyDateTimeBinderProvider 中调用模型绑定器,我们应该在 BinderTypeModelBinder 中定义您的模型绑定器名称。
在我的测试中,我已经成功地调用了,我主要集中在为什么你的活页夹没有被击中而不是转换的东西。你可以看看下面:
型号:
假设我们有以下模型:
public class MyProductClass
{
public string Name { get; set; }
public DateTime Created { get; set; }
}
模型活页夹:
public class DateConversionModelBinder : IModelBinder
{
public DateConversionModelBinder()
{
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var model = new MyProductClass();
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
注意: 我只是创建了一个演示 DateConversionModelBinder。没有写额外的逻辑。
如果您需要转换代码:
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var request = bindingContext.HttpContext.Request;
var stream = request.Body;// At the begining it holding original request stream
var originalReader = new StreamReader(stream);
var originalContent = originalReader.ReadToEndAsync();
var retrieveObject = JsonConvert.DeserializeObject<dynamic>(originalContent.Result);
var model = new MyProductClass();
DateTime dateTime = Convert.ToDateTime(retrieveObject.created);
TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("China Standard Time");
DateTime cstTime = TimeZoneInfo.ConvertTime(dateTime, TimeZoneInfo.Local, cstZone);
DateTime fromLocalTimeToUTC = TimeZoneInfo.ConvertTimeToUtc(cstTime, cstZone);
model.Created = fromLocalTimeToUTC;
model.Name = retrieveObject.name;
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
模型绑定提供者:
public class ProductEntityBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.ModelType == typeof(MyProductClass))
{
return new BinderTypeModelBinder(typeof(DateConversionModelBinder));
}
return null;
}
}
注意: 如您所见,我已经在 th provider 中定义了 Model 和 ModelBinder Name。
Program.cs文件:
builder.Services.AddControllers(options => { options.ModelBinderProviders.Insert(0, new ProductEntityBinderProvider()); });
输出:
注意: 如您所见,我可以通过 ProductEntityBinderProvider 命中 DateConversionModelBinder。请在这里查看官方文档以获取更多详细信息。