如何使自定义 ModelBinder 自动应用于某种类型的所有属性

尼克·埃斯特拉达

编辑:所以事实证明我ModelBinder的实际上不是问题。问题出在我的ValueConverter. 把这个留在这里,因为我认为它说明了如何做一个自定义模型绑定器。


这个问题有很多代码。我正在努力做到尽可能彻底和精确。

我有一Measurement堂课。我的许多模型都有一个或多个类型的属性Measurement此类使用ValueConverter. 我想做的是在提交表单时将表单数据(即字符串)转换为这种类型。所以,我创建了一个自定义ModelBinder.

     public class MeasurementModelBinder : IModelBinder
    {

        public MeasurementModelBinder() { }

        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if(bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); }

            ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if(valueProviderResult == ValueProviderResult.None) { throw new Exception(); }

            string valueString = valueProviderResult.FirstValue;
            if (string.IsNullOrEmpty(valueString)) { throw new Exception(); }

            Measurement result = new Measurement(valueString);
            bindingContext.Result = ModelBindingResult.Success(result);

            return Task.CompletedTask;
        }
    }

我希望这MeasurementModelBinder适用于每个模型中这种类型的所有属性。所以我正在努力做到这一点。这是具有Measurement类型属性的模型的示例

    public class Material
    {
        [Key]
        public int Key { get; set; }
        public string Name { get; set; }
        public Measurement Density { get; set; }
        public Measurement Conductivity { get; set; }

        [Display(Name="Specific Heat")]
        public Measurement SpecificHeat { get; set; }
        public string Description { get; set; }
        public DateTime Created { get; set; }
        public DateTime Updated { get; set; }

        public Material() { }

        public Material(string name, Measurement density, Measurement conductivity, Measurement specificHeat, string description = "")
        {
            Name = name;
            Density = density;
            Description = description;
            Conductivity = conductivity;
            SpecificHeat = specificHeat;
        }

        public override string ToString() { return Name; }
    }

至于控制器,我现在只是在使用测试控制器,这是 Visual Studio 自动生成的带有视图的 MVC 实体框架控制器之一的修改版本。这是控制器中的操作之一。

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create(Material material)
        {
            material.Created = DateTime.Now;
            material.Updated = DateTime.Now;
            if (ModelState.IsValid)
            {
                _context.Add(material);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(material);
        }

CreatedUpdated磁场不受形式提供的,所以我填补他们自己。但是,其他所有内容都由表单填充,作为字符串。您可以Measurement在上面的自定义模型绑定器类中看到对象是如何构造的。

我创建了一个ModelBinderProvider类,如下所示。

    public class MeasurementModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if(context == null) { throw new ArgumentException(nameof(context)); }

            if(!context.Metadata.IsComplexType && context.Metadata.ModelType == typeof(Measurement))
            {
                return new MeasurementModelBinder();
            }

            return null;
        }
    }

我已经在Startup.ConfigureServices()方法中注册了提供者,就像这样。

    services.AddMvc(options =>
    {
        options.ModelBinderProviders.Insert(0, new MeasurementModelBinderProvider());
    });

这是正在提交的表格。

        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Name" class="control-label"></label>
                <input asp-for="Name" class="form-control" />
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Description" class="control-label"></label>
                <input asp-for="Description" class="form-control" />
                <span asp-validation-for="Description" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Density" class="control-label"></label>
                <input asp-for="Density" class="form-control" />
                <span asp-validation-for="Density" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Conductivity" class="control-label"></label>
                <input asp-for="Conductivity" class="form-control" />
                <span asp-validation-for="Conductivity" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="SpecificHeat" class="control-label"></label>
                <input asp-for="SpecificHeat" class="form-control" />
                <span asp-validation-for="SpecificHeat" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>

我希望通过提交此表单向材料表添加一条新记录,并填写所有字段。它不会这样做。相反,它添加了一个所有Measurement属性都为空的新记录

我尝试将[ModelBinder(BinderType = typeof(MeasurementModelBinder))]属性添加Measurement类中,但没有帮助。事实上,它导致了“无法解决服务”错误,当我通过添加services.AddScoped<IModelBinder, MeasurementModelBinder>();摆脱该错误时ConfigureServices(),我的操作仍然得到相同的结果。

我也尝试将[BindProperty(BinderType typeof(MeasurementModelBinder))]属性添加到模型本身的属性中,但没有帮助。此外,这是我宁愿不做的事情。有没有办法让它在所有Measurement类型属性上工作如果没有,有没有办法让它工作?

谢谢。

乌鲁图克姆

我尝试了您的代码,当我将[ModelBinder(BinderType = typeof(MeasurementModelBinder))]属性添加Measurable类时,它对我有用。我认为您应该将[ModelBinder(BinderType = typeof(MeasurementModelBinder))]属性添加Measurement类中。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在自定义ModelBinder中提取数据注释

来自分类Dev

将不同的属性应用于所有方法的自定义类属性

来自分类Dev

将不同的属性应用于所有方法的自定义类属性

来自分类Dev

HTML / CSS如何将CSS应用于具有自定义数据属性的“ a”?

来自分类Dev

HTML / CSS如何将CSS应用于具有自定义数据属性的“ a”?

来自分类Dev

如何添加自定义类型定义?

来自分类Dev

如何添加自定义类型定义?

来自分类Dev

如何将自定义主题应用于Google自定义搜索?

来自分类Dev

如何创建自定义属性类型

来自分类Dev

如何清除应用于元素的自定义样式?

来自分类Dev

如何将自定义ServiceStack RequestFilterAttribute应用于自动生成的服务?

来自分类Dev

如何将自定义渲染应用于除Symfony 2.1项目中的某些字段类型以外的所有表单字段

来自分类Dev

如何将CSS样式应用于自定义属性

来自分类Dev

如何仅将自定义属性应用于元素?

来自分类Dev

如何删除此自定义类型?

来自分类Dev

如何使bean作为自定义类型?

来自分类Dev

如何使用自定义类型malloc()?

来自分类Dev

CSS自定义属性如何级联?

来自分类Dev

如何验证JwtSecurityToken自定义属性

来自分类Dev

如何创建自定义的“文档属性”?

来自分类Dev

如何设置MSI自定义属性

来自分类Dev

如何定义带有px后缀的自定义类型

来自分类Dev

如何在保留类型自定义的同时使用AutoFixture构建自定义属性?

来自分类Dev

如何为自定义属性类型选择创建自定义源模型?

来自分类Dev

Formik - “脏”被应用于具有相同自定义组件的所有实例

来自分类Dev

如何评估具有自定义属性的自定义管道组件?

来自分类Dev

将自定义样式应用于页面上的所有按钮

来自分类Dev

jQuery自定义插件更改已应用于所有实例

来自分类Dev

自定义Bash提示并将修改应用于所有登录的用户

Related 相关文章

  1. 1

    在自定义ModelBinder中提取数据注释

  2. 2

    将不同的属性应用于所有方法的自定义类属性

  3. 3

    将不同的属性应用于所有方法的自定义类属性

  4. 4

    HTML / CSS如何将CSS应用于具有自定义数据属性的“ a”?

  5. 5

    HTML / CSS如何将CSS应用于具有自定义数据属性的“ a”?

  6. 6

    如何添加自定义类型定义?

  7. 7

    如何添加自定义类型定义?

  8. 8

    如何将自定义主题应用于Google自定义搜索?

  9. 9

    如何创建自定义属性类型

  10. 10

    如何清除应用于元素的自定义样式?

  11. 11

    如何将自定义ServiceStack RequestFilterAttribute应用于自动生成的服务?

  12. 12

    如何将自定义渲染应用于除Symfony 2.1项目中的某些字段类型以外的所有表单字段

  13. 13

    如何将CSS样式应用于自定义属性

  14. 14

    如何仅将自定义属性应用于元素?

  15. 15

    如何删除此自定义类型?

  16. 16

    如何使bean作为自定义类型?

  17. 17

    如何使用自定义类型malloc()?

  18. 18

    CSS自定义属性如何级联?

  19. 19

    如何验证JwtSecurityToken自定义属性

  20. 20

    如何创建自定义的“文档属性”?

  21. 21

    如何设置MSI自定义属性

  22. 22

    如何定义带有px后缀的自定义类型

  23. 23

    如何在保留类型自定义的同时使用AutoFixture构建自定义属性?

  24. 24

    如何为自定义属性类型选择创建自定义源模型?

  25. 25

    Formik - “脏”被应用于具有相同自定义组件的所有实例

  26. 26

    如何评估具有自定义属性的自定义管道组件?

  27. 27

    将自定义样式应用于页面上的所有按钮

  28. 28

    jQuery自定义插件更改已应用于所有实例

  29. 29

    自定义Bash提示并将修改应用于所有登录的用户

热门标签

归档