2009-04-27 23 views
18

我正在與嘗試自學ASP.NET MVC的NerdDinner應用程序一起工作。然而,我偶然發現了一個全球化問題,我的服務器用浮點數作爲小數點分隔符,但虛擬地球地圖要求它們帶有點,這會導致一些問題。如何在ASP.NET MVC控制器中設置小數點分隔符?

我已經解決the issue with the mapping JavaScript in my views,但如果我現在嘗試後用點的編輯晚餐條目小數點分隔符的控制器出現故障更新模型(在UpdateModel()梅託德)時(投擲InvalidOperationException)。我覺得我必須在控制器的某個地方設置適當的文化,我在OnActionExecuting()中嘗試過,但這並沒有幫助。

回答

54

我剛剛在一個真實的項目中重新討論了這個問題,並最終找到了一個工作解決方案。正確的解決辦法是有類型decimal(和decimal?如果你正在使用它們)的自定義模型綁定:

using System.Globalization; 
using System.Web.Mvc; 

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

     // Don't do this here! 
     // It might do bindingContext.ModelState.AddModelError 
     // and there is no RemoveModelError! 
     // 
     // result = base.BindModel(controllerContext, bindingContext); 

     string modelName = bindingContext.ModelName; 
     string attemptedValue = 
      bindingContext.ValueProvider.GetValue(modelName).AttemptedValue; 

     // Depending on CultureInfo, the NumberDecimalSeparator can be "," or "." 
     // Both "." and "," should be accepted, but aren't. 
     string wantedSeperator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator; 
     string alternateSeperator = (wantedSeperator == "," ? "." : ","); 

     if (attemptedValue.IndexOf(wantedSeperator) == -1 
      && attemptedValue.IndexOf(alternateSeperator) != -1) 
     { 
      attemptedValue = 
       attemptedValue.Replace(alternateSeperator, wantedSeperator); 
     } 

     try 
     { 
      if (bindingContext.ModelMetadata.IsNullableValueType 
       && string.IsNullOrWhiteSpace(attemptedValue)) 
      { 
       return null; 
      } 

      result = decimal.Parse(attemptedValue, NumberStyles.Any); 
     } 
     catch (FormatException e) 
     { 
      bindingContext.ModelState.AddModelError(modelName, e); 
     } 

     return result; 
    } 
} 

然後在Global.asax.cs中的的Application_Start():

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

請注意,代碼不是我的,我在Kristof Neirynck的博客here上發現它。我只編輯了幾行,併爲特定數據類型添加了活頁夾,而不是替換默認活頁夾。

4

集這你的web.config

<globalization uiCulture="en" culture="en-US" /> 

你似乎是使用服務器是安裝與使用逗號,而不是小數的語言。您可以根據應用程序的設計方式將文化調整爲使用逗號的文化,例如en-US。

+1

我已經有這個,由於某種原因它不起作用。 – 2009-04-28 08:28:22

+0

你的aspx頁面中的標題怎麼樣?他們中的任何一個人是否有爲文化設置的東西 – 2009-04-28 13:22:43

+0

@尼克:沒有,那裏沒有自定義的東西。 – 2009-05-11 19:25:52

0

你可以使用不變文化解析文本 - 對不起,我沒有NerdDinner代碼,但如果你傳遞點分隔的小數而不是解析應該可以,如果你告訴它使用不變的文化。例如。

float i = float.Parse("0.1", CultureInfo.InvariantCulture); 

編輯。順便提一下,我懷疑這是NerdDinner代碼中的一個錯誤,與前面的問題一樣。

0

我有不同的看法,你可能會喜歡它。我不喜歡接受的答案是它不檢查其他角色。我知道會出現這樣一種情況,貨幣符號會出現在框中,因爲我的用戶不知道的更好。所以是的,我可以檢查在JavaScript中刪除它,但如果由於某種原因JavaScript不在?然後額外的字符可能會通過。或者,如果有人試圖發送垃圾郵件,通過未知字符......誰知道!所以我決定使用正則表達式。它有點慢,只有很小的一小部分 - 對於我來說,正則表達式的迭代次數爲1,000,000次,時間不到3秒,而在昏迷和一段時間內,大約需要1秒的時間進行字符串替換。但由於我不知道可能會出現什麼角色,所以我很高興看到這樣的表演。

public class DecimalModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, 
            ModelBindingContext bindingContext) 
    { 
     string modelName = bindingContext.ModelName; 
     string attemptedValue = 
      bindingContext.ValueProvider.GetValue(modelName).AttemptedValue; 

     if (bindingContext.ModelMetadata.IsNullableValueType 
       && string.IsNullOrWhiteSpace(attemptedValue)) 
     { 
      return null; 
     } 

     if (string.IsNullOrWhiteSpace(attemptedValue)) 
     { 
      return decimal.Zero; 
     } 

     decimal value = decimal.Zero; 
     Regex digitsOnly = new Regex(@"[^\d]", RegexOptions.Compiled); 
     var numbersOnly = digitsOnly.Replace(attemptedValue, ""); 
     if (!string.IsNullOrWhiteSpace(numbersOnly)) 
     { 
      var numbers = Convert.ToDecimal(numbersOnly); 
      value = (numbers/100m); 

      return value; 
     } 
     else 
     { 
      if (bindingContext.ModelMetadata.IsNullableValueType) 
      { 
       return null; 
      } 

     } 

     return value; 
    } 
} 

基本上,刪除不數字所有字符,一個字符串,它不爲空。轉換爲十進制。除以100.返回結果。

適合我。

相關問題