tag route net mvc for busqueda asp asp.net-mvc globalization

route - ¿Cómo establecer separadores decimales en los controladores ASP.NET MVC?



search asp net core (4)

¿Puede analizar el texto utilizando la cultura invariante? Lo siento, no tengo el código NerdDinner en mi lugar, pero si está pasando decimales separados por puntos, el análisis debería estar bien si le dice que use la cultura invariante. . P.ej

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

Editar Sospecho que este es un error en el código NerdDinner por cierto, en la misma línea que su problema anterior.

Estoy trabajando con la aplicación NerdDinner tratando de enseñarme a mí mismo ASP.NET MVC. Sin embargo, me he topado con un problema con la globalización, donde mi servidor presenta números de punto flotante con una coma como separador decimal, pero el mapa de Virtual Earth los requiere con puntos, lo que causa algunos problemas.

En mi opinión ya he resuelto el problema con el mapeo de JavaScript , pero si ahora intento publicar una entrada de cena editada con puntos como separadores decimales, el controlador falla (lanza InvalidOperationException ) al actualizar el modelo (en el UpdateModel() ). Siento que también debo establecer la cultura adecuada en algún lugar del controlador, lo intenté en OnActionExecuting() pero eso no ayudó.


Acabo de revisar el problema en un proyecto real y, finalmente, encontré una solución funcional. La solución adecuada es tener una carpeta de modelos personalizada para el tipo decimal (y decimal? Si los está utilizando):

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; // in decimal? binding attemptedValue can be Null if (attemptedValue != null) { // 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, StringComparison.Ordinal) == -1 && attemptedValue.IndexOf(alternateSeperator, StringComparison.Ordinal) != -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; } }

Luego en Global.asax.cs en Application_Start ():

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

Tenga en cuenta que el código no es mío, de hecho lo encontré en el blog de Kristof Neirynck here . Acabo de editar unas pocas líneas y estoy agregando el cuaderno para un tipo de datos específico, sin reemplazar el cuaderno predeterminado.


Establece esto en tu web.config

<system.web> <globalization uiCulture="en" culture="en-US" />

Parece que estás usando un servidor que está configurado con un idioma que usa comas en lugar de lugares decimales. Puede ajustar la cultura a una que use los comma de una manera que su aplicación esté diseñada, como en-US.


Tengo una opinión diferente sobre esto, puede que te guste. Lo que no me gusta de la respuesta aceptada es que no verifica otros personajes. Sé que habrá un caso en el que el símbolo de moneda estará en la casilla porque mi usuario no sabe qué hacer. Así que sí, puedo registrar javascript para eliminarlo, pero ¿qué pasa si, por alguna razón, no está activado javascript? Entonces los personajes extra pueden pasar. O si alguien intenta enviarte un correo no deseado pasando personajes desconocidos ... ¡quién sabe! Así que decidí usar una expresión regular. Es un poco más lento, una fracción minúscula más lenta: en mi caso, las 1,000,000 iteraciones de la expresión regular tardaron un poco menos de 3 segundos, mientras que alrededor de 1 segundo para reemplazar una cadena en coma y período. Pero al ver que no sé qué personajes pueden surgir, entonces estoy feliz por el menor de los éxitos de rendimiento.

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

Básicamente, elimine todos los caracteres que no sean dígitos, para una cadena que no esté vacía. Convertir a decimal. Divide por 100. Devuelve el resultado.

Funciona para mi.