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

发布于 2024-10-18 07:31:43 字数 1606 浏览 2 评论 0原文

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

我尝试添加自定义模型绑定器并覆盖 bindModel 函数,但我不知道如何解决其中的错误,因为文化已被设置回默认的 en-GB。

因此,我尝试向我的 BaseController 添加一个操作过滤器,以在那里设置文化,但不幸的是,bindModel 似乎在我的操作过滤器之前被触发。

我该如何解决这个问题?要么让文化不重置自身,要么在bindModel启动之前将其设置回来?

模型无效的控制器:

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

设置文化的过滤器:

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

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

    base.OnActionExecuting(filterContext);
}

自定义模型绑定器:

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;
   }
}

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.

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.

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.

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

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;
   }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉世弥音 2024-10-25 07:31:43

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

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

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

更新:好的,这是一个多语言应用程序。如何获得你想要的文化?您可以在 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;
    }
    //...
}

在模型绑定之前调用此方法,因此,您不需要自定义模型绑定程序。我希望它对你有用:)

You want your application to use a single culture, right?
If so, you can do this with the globalization tag of your 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:

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 :)

橘味果▽酱 2024-10-25 07:31:43

看看

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

    // ...

    return View();
}

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

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

    return View();
}

本文有完整的参考资料和其他执行此操作的方法。我用这两个,到目前为止它们对我来说已经足够了。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文