【问题标题】:Web Api 2 Decimal delimiterWeb Api 2 十进制分隔符
【发布时间】:2016-07-08 07:17:10
【问题描述】:

如何为十进制数创建一个模型绑定器,如果用户以错误的格式发送它会引发异常?

我需要这样的东西:

2 = OK
2.123 = OK
2,123 = throw invalid format exception

【问题讨论】:

  • 如果绑定到decimal类型不成功,将会抛出异常。
  • 是的,反之亦然,但您需要默认值。它应该做的。你测试过这个吗?
  • @fabio 这不是真的。我刚刚测试了它。它取决于文化。我已经向我的 api 发送了 10.5,它绑定得很好,但是当我发送 10.5 时,它没有抛出任何异常。它只是将我的模型中的十进制值设置为 0,这是默认的十进制值。
  • 我认为如果您显示您发送的请求数据和您绑定到的模型会更好
  • 如果绑定失败,您的模型将作为null传递给控制器​​的方法

标签: c# asp.net asp.net-web-api asp.net-web-api2


【解决方案1】:

看这篇文章http://haacked.com/archive/2011/03/19/fixing-binding-to-decimals.aspx/

您可以使用标准活页夹进行简单检查

public class DecimalModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        ValueProviderResult valueResult = bindingContext.ValueProvider
            .GetValue(bindingContext.ModelName);
        ModelState modelState = new ModelState { Value = valueResult };
        object actualValue = null;

        if (valueResult.AttemptedValue.Contains(","))
        {
            throw new Exception("Some exception");
        }
        actualValue = Convert.ToDecimal(valueResult.AttemptedValue,
            CultureInfo.CurrentCulture);


        bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
        bindingContext.Model = actualValue;
        return true;
    }
}

编辑:根据@Liam 的建议,您必须先将此活页夹添加到您的配置中

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());

以上代码在小数点分隔符错误的情况下会引发异常,但您应该使用模型验证来检测此类错误。这是一种更灵活的方式。

public class DecimalModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        ValueProviderResult valueResult = bindingContext.ValueProvider
            .GetValue(bindingContext.ModelName);
        ModelState modelState = new ModelState { Value = valueResult };
        object actualValue = null;
        try
        {
            if (valueResult.AttemptedValue.Contains(","))
            {
                throw new Exception("Some exception");
            }
            actualValue = Convert.ToDecimal(valueResult.AttemptedValue,
                CultureInfo.CurrentCulture);
        }
        catch (FormatException e)
        {
            modelState.Errors.Add(e);
            return false;
        }

        bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
        bindingContext.Model = actualValue;
        return true;
    }
}

您不会抛出异常,而只是添加验证错误。您可以稍后在控制器中检查它

if (ModelState.IsValid)
{
}

【讨论】:

  • 您也需要添加有关如何实际绑定它的信息,即ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
  • 对于 WebAPI2,BindModel 方法返回 bool。我们这里不使用 MVC
  • 是的,抱歉,我确实注意到了这一点。因此我删除了评论。我没有意识到微软有两个同名但签名不同的接口.....对我来说似乎是个坏主意。有趣的是,Phill Haacked 的文章似乎也用错了……
  • 它可能在一些旧版本的 WebAPI 之间发生了变化。当前版本与 MVC 有很多不同
  • ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); 需要来自System.Web.Mvc 的IModelBinder 接口,但这里使用的接口来自System.Web.Http.ModelBinding
猜你喜欢
  • 2016-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多