I have the following float number : -95.83334
this is in my view model:
[DisplayFormat(DataFormatString = "{0:#.##}")]
public float? mx { get; set; }
this is in my view
@Html.HiddenFor(model => model.mx)
this is the generated html
<input data-val="true" id="mx" name="mx" type="hidden" value="-95,83334">
and this is the desired html
<input data-val="true" id="mx" name="mx" type="hidden" value="-95.83334">
so the question is, which is the best way to change the decimal separator for this hidden input? without alter the the rest of my project
DisplayFormat
is used when you use Html.DisplayFor
. And, it's only for formatting what's supposed to be displayed on the view. If you want to change the format of decimal numbers in general, you'll need to use a different culture.
Finally, this was the solution for me
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
@Html.HiddenFor(model => model.mx)
adding the line
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
before my hidden solved the problem. thanks for the ideas and guides!
@Html.HiddenFor(model => model.mx.ToString(new CultureInfo("en-us")));
Edit:
Sorry for the brief answer. I think it would have been useful if it had worked, unfortunately I missed something important in your code.
Your issue is a localization problem. I'm guessing your machine is running with a European culture. (Just noticed your comment about being it set as Spanish)
ToString() has been overloaded for some of the basic types, float included. One of these overloads accepts an IFormatProvider which CultureInfo implements. By passing a CultureInfo using the culture code for United States English, you can ensure the dot will be used instead of the comma as the decimal separator.
What I missed is that mx is a float?, which is short for Nullable. Nullable does not overload ToString in the same way, so you have a couple of alternatives.
If you are using C#6, you can use the null check operator to convert your float? back to a float. You could then use the ToString overload:
@Html.HiddenFor(model => model.mx?.ToString(CultureInfo.GetCultureInfo("en-us")));
Alternatively, you can use the String.Format overload, which accepts both a format string and an IFormatProvider:
@Html.HiddenFor(model => String.Format(CultureInfo.GetCultureInfo("en-us"), "{0:#.##}", model.mx));
I did not want to suggest changing the culture of your thread because this stood out in your question "without alter the the rest of my project" which I, perhaps mistakenly, assumed to mean you did not want to change the formatting of other components in your application. Changing the default thread culture could have a larger impact than you anticipate.
Edit 2:
Here is my attempt at an extension overload accepting an IFormatProvider. This was just an experiment and shouldn't be used in production... I'm including it purely for interest sake.
public static class HtmlExtensions
{
public static IHtmlString HiddenFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IFormatProvider formatter)
{
var value = expression.Compile().Invoke(helper.ViewData.Model);
var modelMetadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
var property = typeof(TModel).GetProperty(modelMetadata.PropertyName);
var attribute = property.GetCustomAttributes(typeof(DisplayFormatAttribute), false).SingleOrDefault() as DisplayFormatAttribute;
var displayValue = String.Format(formatter, attribute?.DataFormatString ?? "{0}", value);
TagBuilder tagBuilder = new TagBuilder("input");
tagBuilder.MergeAttribute("type", "hidden");
tagBuilder.MergeAttribute("value", displayValue);
return MvcHtmlString.Create(tagBuilder.ToString());
}
}
Use it like this
@Html.HiddenFor(mode => mode.myNumber, System.Globalization.CultureInfo.GetCultureInfo("en-us"))