具有全局数字格式的ASP.NET MVC模型绑定器

时间:2022-04-17 11:43:43

The default model binder is returning errors for properties that are of type double when my application is being used in countries that use different number formatting for decimals (e.g. 1.2 = 1,2). The culture of the site is set conditionally in my BaseController.

当我的应用程序在使用不同数字格式的小数(例如1.2 = 1,2)的国家/地区使用时,默认模型绑定器会返回类型为double的属性的错误。网站的文化是在我的BaseController中有条件地设置的。

I have tried adding a custom model binder and overriding the bindModel function but I can't see how to get around the error in there as the Culture has already been set back to the default of en-GB.

我已经尝试添加自定义模型绑定器并覆盖bindModel函数但我无法看到如何解决错误,因为Culture已经设置回默认的en-GB。

So I tried adding an action filter to my BaseController that sets the Culture there but unfortunately bindModel seems to get fired before my action filter.

所以我尝试在我的BaseController中添加一个动作过滤器来设置Culture,但不幸的是bindModel似乎在我的动作过滤器之前被触发了。

How can I get around this? Either by getting the Culture to not reset itself or set it back before bindModel kicks in?

我怎么能绕过这个?要么让文化不重置自己,要么在bindModel启动之前将其重新设置?

Controller where model comes in invalid:

模型进入无效的控制器:

public ActionResult Save(MyModel myModel)
{
    if (ModelState.IsValid)
    {
        // Save my model
    }
    else
    {
       // Raise error
    }
}

Filter where Culture is set:

筛选文化设置:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    CultureInfo culture = createCulture(filterContext);

    if (culture != null)
    {
         Thread.CurrentThread.CurrentCulture = culture;
         Thread.CurrentThread.CurrentUICulture = culture;
    }

    base.OnActionExecuting(filterContext);
}

Custom Model Binder:

自定义型号粘合剂:

public class InternationalDoubleModelBinder : DefaultModelBinder
{
   public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   {
       ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
       if (valueResult != null)
       {
           if (bindingContext.ModelType == typeof(double) || bindingContext.ModelType == typeof(Nullable<double>))
           {
               double doubleAttempt;

               doubleAttempt = Convert.ToDouble(valueResult.AttemptedValue);

               return doubleAttempt;
           }
        }
        return null;
   }
}

2 个解决方案

#1


3  

You want your application to use a single culture, right? If so, you can do this with the globalization tag of your web.config.

您希望您的应用程序使用单一文化,对吧?如果是这样,您可以使用web.config的全球化标记执行此操作。

<configuration>
    <system.web>
        <globalization
           enableClientBasedCulture="true"        
           culture="en-GB"
           uiCulture="en-GB"/>
    </system.web>
</configuration>

And then you can forget those custom model binder and use the default.

然后你可以忘记那些自定义模型绑定器并使用默认值。

UPDATE: Ok, it's a multi-language application. How do you get the culture you want? Can you call createCulture on the MvcApplication class? You could do this:

更新:好的,这是一个多语言应用程序。你如何获得你想要的文化?你能在MvcApplication类上调用createCulture吗?你可以这样做:

public class MvcApplication : HttpApplication
{
    //...
    public void Application_OnBeginRequest(object sender, EventArgs e)
    {
        CultureInfo culture = GetCulture();
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;
    }
    //...
}

This method is called before the model bind, so, again, you won't need the custom model binder. I hope it works for you :)

在模型绑定之前调用此方法,因此,您将不再需要自定义模型绑定器。我希望这个对你有用 :)

#2


-1  

Take a look in this article but, for short, if you could try this:

看看这篇文章,但简而言之,如果你可以试试这个:

public ActionResult Create(FormCollection values)
{
    Recipe recipe = new Recipe();
    recipe.Name = values["Name"];      

    // ...

    return View();
}

...or this, in case you have a Model:

......或者,如果你有一个模型:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Recipe newRecipe)
{            
    // ...

    return View();
}

The article has complete references and other ways of doing this. I use these 2 and they were enough for me up to now.

本文有完整的参考资料和其他方法。我使用这两个,到目前为止我们已经足够了。

#1


3  

You want your application to use a single culture, right? If so, you can do this with the globalization tag of your web.config.

您希望您的应用程序使用单一文化,对吧?如果是这样,您可以使用web.config的全球化标记执行此操作。

<configuration>
    <system.web>
        <globalization
           enableClientBasedCulture="true"        
           culture="en-GB"
           uiCulture="en-GB"/>
    </system.web>
</configuration>

And then you can forget those custom model binder and use the default.

然后你可以忘记那些自定义模型绑定器并使用默认值。

UPDATE: Ok, it's a multi-language application. How do you get the culture you want? Can you call createCulture on the MvcApplication class? You could do this:

更新:好的,这是一个多语言应用程序。你如何获得你想要的文化?你能在MvcApplication类上调用createCulture吗?你可以这样做:

public class MvcApplication : HttpApplication
{
    //...
    public void Application_OnBeginRequest(object sender, EventArgs e)
    {
        CultureInfo culture = GetCulture();
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;
    }
    //...
}

This method is called before the model bind, so, again, you won't need the custom model binder. I hope it works for you :)

在模型绑定之前调用此方法,因此,您将不再需要自定义模型绑定器。我希望这个对你有用 :)

#2


-1  

Take a look in this article but, for short, if you could try this:

看看这篇文章,但简而言之,如果你可以试试这个:

public ActionResult Create(FormCollection values)
{
    Recipe recipe = new Recipe();
    recipe.Name = values["Name"];      

    // ...

    return View();
}

...or this, in case you have a Model:

......或者,如果你有一个模型:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Recipe newRecipe)
{            
    // ...

    return View();
}

The article has complete references and other ways of doing this. I use these 2 and they were enough for me up to now.

本文有完整的参考资料和其他方法。我使用这两个,到目前为止我们已经足够了。