【问题标题】:Implement custom ModelBinder ASP.NET MVC实现自定义 ModelBinder ASP.NET MVC
【发布时间】:2018-01-28 20:43:37
【问题描述】:

我遇到了很多人已经遇到的同样问题 - Model Binder 不接受本地化的十进制输入。在所有主题、此处和其他论坛中,推荐的解决方案是实现自定义ModelBinder

我的问题是这些解决方案对我不起作用。让我们以这个解决方案为例:comma decimal seperator in asp.net mvc 5

当我引用所有命名空间时,仍然存在两个错误:

错误 CS0115 'DecimalModelBinder.BindModel(ControllerContext, ModelBindingContext)': 找不到合适的方法来覆盖 ...

错误 CS0173 无法确定条件表达式的类型 因为 'bool' 和 'decimal' 之间没有隐式转换

第二个引用整个return 语句。

MVC 框架中是否发生了一些变化,所以这段代码已经过时了,还是我做错了什么?

我最终得到的代码是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.ModelBinding;
using System.Web.Mvc;

namespace AetMuzickaOprema.App_Start
{
    public class DecimalModelBinder : System.Web.ModelBinding.DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, System.Web.ModelBinding.ModelBindingContext bindingContext) //first error
        {
            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

            return valueProviderResult == null ? base.BindModel(controllerContext, bindingContext) : Convert.ToDecimal(valueProviderResult.AttemptedValue); //second error

        }
    }
}

有问题的模型属性:

[Required]
[Range(typeof(decimal), "0", "999999999")]
public decimal Price { get; set; }

【问题讨论】:

  • 这里解释了如何以更新的方式进行自定义模型绑定。 docs.microsoft.com/en-us/aspnet/core/mvc/advanced/… 。如果您有问题,我会为您构建,但请先尝试。
  • 谢谢,我会尝试并告诉你:) 非常感谢
  • @PedroSouki 自从您发表评论以来,我一直在看这篇文章,但我对 MVC 太陌生,无法在我的情况下使用它。如果您愿意向我展示如何实现它以使十进制值同时接受“1,25”和“1.25”,我将不胜感激。

标签: c# .net asp.net-mvc asp.net-mvc-5 model-binding


【解决方案1】:

看来您最终要实现的是像这样的属性级绑定?:

[PropertyBinder(typeof(PropertyBBinder))]
public IList<int> PropertyB {get; set;}

如果正确,这篇文章提供了一个解决方案:Custom model binder for a property

谢谢。

【讨论】:

  • 实际上,这是我将在问题中包含的单个小数属性。我不知道这是否适用。无论如何感谢您的回答:)
【解决方案2】:

在 ASP.NET Core 1.1 (Microsoft.AspNetCore.Mvc.Core.Abstraction, 1.0.1.0) 中你会看到如下界面

using System.Threading.Tasks;

namespace Microsoft.AspNetCore.Mvc.ModelBinding
{
    //
    // Summary:
    //     Defines an interface for model binders.
    public interface IModelBinder
    {
        //
        // Summary:
        //     Attempts to bind a model.
        //
        // Parameters:
        //   bindingContext:
        //     The Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext.
        //
        // Returns:
        //     A System.Threading.Tasks.Task which will complete when the model binding process
        //     completes.
        //     If model binding was successful, the Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext.Result
        //     should have Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult.IsModelSet
        //     set to true.
        //     A model binder that completes successfully should set Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext.Result
        //     to a value returned from Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult.Success(System.Object).
        Task BindModelAsync(ModelBindingContext bindingContext);
    }
}

模型绑定器在Microsoft.AspNetCore.Mvc.ModelBinding.Binders 命名空间、程序集Microsoft.AspNetCore.Mvc.Core, Version=1.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 中定义。他们似乎都没有公开BindModel() 方法,更不用说虚拟方法了。您似乎正在尝试覆盖一个不存在的方法。

更好的方法是采用最适合您需求的现有ModelBinder,从它继承并覆盖ModelBindAsync()

【讨论】:

  • 感谢您的回复。我可以问一下在我的项目中哪里可以找到现有的ModelBinders 来打扰您吗?
  • “模型绑定器在 Microsoft.AspNetCore.Mvc.ModelBinding.Binders 命名空间、程序集 Microsoft.AspNetCore.Mvc.Core、版本=1.0.1.0、文化=中性、PublicKeyToken=adb9793829ddae60 中定义”。严格来说,这意味着您的项目中没有 MB。但是您可以定义一个并将其放在您需要的任何地方,例如在 Helpers 文件夹或类似的地方。只需从 DefaultModelBinder 继承并覆盖 BindModelAsync。或者简单地说,将 ModelBind 重命名为 ModelBindAsync 并考虑签名。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-11
  • 2020-07-18
  • 1970-01-01
相关资源
最近更新 更多