ApiController 的自定义日期时间模型绑定器

问题描述 投票:0回答:1

我正在使用 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());
全局注册它不起作用,因为模型绑定器永远不会被击中。

asp.net-core model-binding
1个回答
0
投票

创建自定义日期时间模型绑定器并在全局注册 通过 ...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。请在这里查看官方文档以获取更多详细信息。

© www.soinside.com 2019 - 2024. All rights reserved.