ASP.NET MVC3: Incoherencias en el tratamiento de doubles

Muy, muy, muy molesto…  ASP.NET MVC3 corriendo sobre un servidor web configurado en español (cultura es-ES).

Con la tabla de rutas estándar, cuatro acciones como las siguientes

  1. [HttpPost]
  2. public ActionResult Index(DoubleModel model)
  3. {
  4.     ViewBag.Valor = model.Valor;
  5.  
  6.     return View("Resultado");
  7. }
  8.  
  9. [HttpPost]
  10. public ActionResult IndexSoloDouble(double? valor)
  11. {
  12.     ViewBag.Valor = valor;
  13.  
  14.     return View("Resultado");
  15. }
  16.  
  17.  
  18. public ActionResult IndexRuta(double? id)
  19. {
  20.     ViewBag.Valor = id;
  21.     return View("Resultado");
  22. }
  23.  
  24. public ActionResult IndexGet(double? valor)
  25. {
  26.     ViewBag.Valor = valor;
  27.     return View("Resultado");
  28.     
  29. }

La clase DoubleMode simplemente tiene una propiedad double llamada Valor.

  1. La primera acción recibe un double via POST  dentro de un modelo
  2. La segunda recibe un double via POST sólo
  3. La tercera acción recibe un double como parámetro de ruta
  4. La cuarta acción recibe un double via querystring

Pues bien:

  1. La primera acción acepta 12,10 pero no 12.10 (usa la cultura del servidor web)
  2. La segunda acción acepta 12,10 pero no 12.10 (usa la cultura del servidor web)
  3. La tercera acción acepta 12.10 pero no 12,10 (usa la cultura ¿invariante?)
  4. La cuarta acción acepta 12.10 pero no 12, 10 (como la tercera, parece usar la invariante).

Aquí tenéis el código de la vista usada para enviar los datos:

  1. @using MvcApplication1.Models
  2. @model DoubleModel
  3.  
  4. @{
  5.     ViewBag.Title = "Index";
  6. }
  7.  
  8. <h2>Index</h2>
  9.  
  10. @{
  11.     Html.EnableClientValidation(false);
  12. }
  13.  
  14. @using (Html.BeginForm()) {
  15.     <div>
  16.     Introduce el valor:
  17.     <input type="hidden" name="Valor" value="12,10" />
  18.     </div>
  19.     <input type="submit" value="enviar 12,10 via POST" />
  20. }
  21.  
  22. @using (Html.BeginForm()) {
  23.     <div>
  24.     <input type="hidden" name="Valor" value="12.10" />
  25.     </div>
  26.     <input type="submit" value="enviar 12.10 via POST" />
  27. }
  28.  
  29.  
  30. @using (Html.BeginForm("IndexSoloDouble","Home"))
  31. {
  32.     <div>
  33.     <input type="hidden" name="Valor" value="12,10" />
  34.     </div>
  35.     <input type="submit" value="enviar 12,10 via POST (solo double)" />
  36. }
  37.  
  38.  
  39. @using (Html.BeginForm("IndexSoloDouble", "Home"))
  40. {
  41.     <div>
  42.     <input type="hidden" name="Valor" value="12.10" />
  43.     </div>
  44.     <input type="submit" value="enviar 12.10 via POST (solo double)" />
  45. }
  46.  
  47.  
  48.  
  49. @Html.ActionLink("Enviar 12,10 via GET", "IndexGet", new { valor = "12,10" }); | @Html.ActionLink("Enviar 12.10 via GET", "IndexGet", new { valor = "12.10" });
  50. <br/>
  51. @Html.ActionLink("Enviar 12,10 en ruta", "IndexRuta", new { id = "12,10" }); | @Html.ActionLink("Enviar 12.10 en ruta", "IndexRuta", new { id = "12.10" });

El problema parece estar en los ValueProviders de URL (RouteDataValueProvider y QueryStringVaueProvider), que parecen ignorar la cultura, mientras que el ValueProvider de POST (FormValueProvider) la respeta.

Lo dicho… muy molesto 🙁

Saludos!

Editado 16:43. PD: Iván Loire (@ivanloire) me comenta que este comportamiento es por diseño: los locales NO se aplican en los parámetros de URL para mantener las URLs canónicas. Si usáramos los locales del usuario podríamos tener URLs distintas que sirviesen el mismo contenido, y URLs válidas para un usuario podrían no serlo para otro. Es por ello que en MVC han optado por usar la cultura invariante en los ValueProviders de la URL. Dejo dos enlaces que me ha pasado Iván a dos posts donde se explica esto: http://bit.ly/tIZX64 y http://bit.ly/vCgbmf

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *