加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – asp.net MVC 1.0和2.0货币模型绑定

发布时间:2020-12-16 07:08:31 所属栏目:asp.Net 来源:网络整理
导读:我想创建模型绑定功能,以便用户可以输入’,”’.等等,用于绑定到我的ViewModel的double值的货币值. 我能够通过创建自定义模型绑定器在MVC 1.0中执行此操作,但是自从升级到MVC 2.0后,此功能不再有效. 有没有人有任何想法或更好的解决方案来执行此功能?更好的
我想创建模型绑定功能,以便用户可以输入’,”’.等等,用于绑定到我的ViewModel的double值的货币值.

我能够通过创建自定义模型绑定器在MVC 1.0中执行此操作,但是自从升级到MVC 2.0后,此功能不再有效.

有没有人有任何想法或更好的解决方案来执行此功能?更好的解决方案是使用一些数据注释或自定义属性.

public class MyViewModel
{
    public double MyCurrencyValue { get; set; }
}

一个首选的解决方案是这样的……

public class MyViewModel
{
    [CurrencyAttribute]
    public double MyCurrencyValue { get; set; }
}

下面是我在MVC 1.0中进行模型绑定的解决方案.

public class MyCustomModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext)
    {
        object result = null;

        ValueProviderResult valueResult;
        bindingContext.ValueProvider.TryGetValue(bindingContext.ModelName,out valueResult);
        bindingContext.ModelState.SetModelValue(bindingContext.ModelName,valueResult);

        if (bindingContext.ModelType == typeof(double))
        {
            string modelName = bindingContext.ModelName;
            string attemptedValue = bindingContext.ValueProvider[modelName].AttemptedValue;

            string wantedSeperator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator;
            string alternateSeperator = (wantedSeperator == "," ? "." : ",");

            try
            {
                result = double.Parse(attemptedValue,NumberStyles.Any);
            }
            catch (FormatException e)
            {
                bindingContext.ModelState.AddModelError(modelName,e);
            }
        }
        else
        {
            result = base.BindModel(controllerContext,bindingContext);
        }

        return result;
    }
}

解决方法

你可以尝试一下这些行:

// Just a marker attribute
public class CurrencyAttribute : Attribute
{
}

public class MyViewModel
{
    [Currency]
    public double MyCurrencyValue { get; set; }
}


public class CurrencyBinder : DefaultModelBinder
{
    protected override object GetPropertyValue(
        ControllerContext controllerContext,ModelBindingContext bindingContext,PropertyDescriptor propertyDescriptor,IModelBinder propertyBinder)
    {
        var currencyAttribute = propertyDescriptor.Attributes[typeof(CurrencyAttribute)];
        // Check if the property has the marker attribute
        if (currencyAttribute != null)
        {
            // TODO: improve this to handle prefixes:
            var attemptedValue = bindingContext.ValueProvider
                .GetValue(propertyDescriptor.Name).AttemptedValue;
            return SomeMagicMethodThatParsesTheAttemptedValue(attemtedValue);
        }
        return base.GetPropertyValue(
            controllerContext,bindingContext,propertyDescriptor,propertyBinder
        );
    }
}

public class HomeController: Controller
{
    [HttpPost]
    public ActionResult Index([ModelBinder(typeof(CurrencyBinder))] MyViewModel model)
    {
        return View();
    }
}

更新:

这是对活页夹的改进(参见前面代码中的TODO部分):

if (!string.IsNullOrEmpty(bindingContext.ModelName))
{
    var attemptedValue = bindingContext.ValueProvider
        .GetValue(bindingContext.ModelName).AttemptedValue;
    return SomeMagicMethodThatParsesTheAttemptedValue(attemtedValue);
}

为了处理集合,您需要在Application_Start中注册绑定器,因为您将无法再使用ModelBinderAttribute来装饰列表:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    ModelBinders.Binders.Add(typeof(MyViewModel),new CurrencyBinder());
}

然后你的行动看起来像这样:

[HttpPost]
public ActionResult Index(IList<MyViewModel> model)
{
    return View();
}

总结重要部分:

bindingContext.ValueProvider.GetValue(bindingContext.ModelName)

此绑定器的进一步改进步骤是处理验证(AddModelError / SetModelValue)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读