6

在我的 Jquery 脚本中,我使用浏览器的 CultureInfo (en-UK) 发布了两个双打,它使用了.作为分数分隔符。我的 MVC 应用程序正在使用 locale nl-BE,作为分数分隔符的服务器上运行。

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult GetGridCell(double longitude, double latitude)
{
    var cell = new GridCellViewModel { X = (int)Math.Round(longitude, 0), Y = (int)Math.Round(latitude, 0) };
    return Json(cell);
}

由于解析问题,模型绑定失败。

我认为最好将我的 javascript 设置为 en-UK 并且对于我的 MVC 应用程序中的模型绑定也是如此。但我也不知道该怎么做。
有什么建议么?

4

2 回答 2

8

我不确定默认模型绑定器 (DefaultModelBinder) 的本地化程度如何,但您可以自己轻松创建一个绑定器,它可以处理特定于文化的数据解析,例如,创建一个新类,我们将其称为 DoubleModelBinder,复制以下内容:

public class DoubleModelBinder : IModelBinder
{
    /// <summary>
    /// Binds the value to the model.
    /// </summary>
    /// <param name="controllerContext">The current controller context.</param>
    /// <param name="bindingContext">The binding context.</param>
    /// <returns>The new model.</returns>
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var culture = GetUserCulture(controllerContext);

        string value = bindingContext.ValueProvider
                           .GetValue(bindingContext.ModelName)
                           .ConvertTo(typeof(string)) as string;

        double result = 0;
        double.TryParse(value, NumberStyles.Any, culture, out result);

        return result;
    }

    /// <summary>
    /// Gets the culture used for formatting, based on the user's input language.
    /// </summary>
    /// <param name="context">The controller context.</param>
    /// <returns>An instance of <see cref="CultureInfo" />.</returns>
    public CultureInfo GetUserCulture(ControllerContext context)
    {
        var request = context.HttpContext.Request;
        if (request.UserLanguages == null || request.UserLanguages.Length == 0)
            return CultureInfo.CurrentUICulture;

        return new CultureInfo(request.UserLanguages[0]);
    }
}

现在,我们在这里所做的是建立我们自己的语言感知双解析器。当我们实现 IModelBinder 接口时,我们需要创建一个 BindModel 方法。这是它的主要内容,但在我们解析任何内容之前,我们需要获取一个基于浏览器语言的 IFormatProvider。因此,我们使用 GetUserCulture 方法来尝试准备浏览器的语言。如果我们不能恢复到当前的文化。

当我们拥有它时,我们就可以解析该值。我们首先从 ValueProvider 中获取它(它实际上是许多值提供者的组合,例如来自 Form 集合、Request 集合等),然后我们使用发现的 IFormatProvider 来解析它,这就是我们现在拥有的 CultureInfo。

完成此操作后,将其添加到模型绑定器集合中非常简单;

ModelBinder.Binders[typeof(Double)] = new DoubleModelBinder();

试试看是否有帮助。

于 2010-07-04T18:38:08.207 回答
1

ModelBinding 使用 CurrentCulture 解析值。这是可以理解的,因为用户可能会在文本框中输入日期或小数,并且该值将被正确解析。

但我仍然认为大多数开发人员都以您的方式看待它:无论用户使用哪种语言,他们都希望通过使用相同的文化来解析所有值。他们希望以用户的格式显示值,但以中性格式(InvariantCulture)输入值。

这就是为什么我将 Application.BeginRequest 中的 CurrentCulture 设置为 CultureInfo.InvariantCulture。因此,所有 Binding 都使用不变的 Culture。如果您以后想要使用浏览器语言中的资源或格式值,则必须通过再次将 CurrentCulture 设置为用户的语言来切换回用户的语言。我在动作过滤器中执行此操作。

编辑:

OP 纠正了我,因为只有表单提交才具有文化意识:这是真的。请参阅 ValueProviderDictionary:PopulateDictionary 的来源,其中记录了它:

   We use this order of precedence to populate the dictionary:
   1. Request form submission (should be culture-aware)
   2. Values from the RouteData (could be from the typed-in URL or from the route's default values)
   3. URI query string
于 2010-07-04T19:06:31.567 回答