0

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

6
  • You could forcefully change your thread's CultureInfo.CurrentCulture, if you want the change globally. Commented Nov 5, 2015 at 19:19
  • My guess is that DisplayFormat attribute is not needed here and that it is messing with your input value. Commented Nov 5, 2015 at 19:19
  • I try in my it's work fine and my CurrentCultur is en-US Commented Nov 5, 2015 at 19:20
  • Why? Its a hidden input so you cant even see it. And then because it does not match your server culture, binding would fail (unless you have a custom model binder) and the value of mx would be null. Commented Nov 5, 2015 at 20:38
  • @StephenMuecke because my app use the values Commented Nov 6, 2015 at 13:44

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

then how can i change the culture for this hidden only? i need to print commas in some cases and point in others, in the same view
What's the point of changing the culture for a hidden input? That doesn't make any sense.
because my app culture is es-CL and i need to work with point separated decimals not commas. i can't make maths operations with comma separated decimals
0

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!

Comments

0
@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"))

5 Comments

there is no override for method ToString that takes 1 parameter
Apologies, this was an answer, it was simply not a good one. I edited to add appropriate context.
i can use CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); while i print the float values and then use CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("es-CL"); to go back to my default culture again. however making this in a cshtml only take effect in this html and do not alter the rest of the project
i tried using your code @Html.HiddenFor(model => tring.Format(CultureInfo.GetCultureInfo("en-us"), "{0:#.##}", model.mx)); and i got this error Las plantillas solo se pueden usar con expresiones de acceso de campos, acceso de propiedades, índice de matriz de una dimensión o indizador personalizado de un parámetro. Detalles de la excepción: System.InvalidOperationException: Las plantillas solo se pueden usar con expresiones de acceso de campos, acceso de propiedades, índice de matriz de una dimensión o indizador personalizado de un parámetro.
I see that HtmlHelper methods are more sophisticated than I guessed. I thought my knowledge of localization would be transferable to this problem but I'm clearly out of my depth working with MVC. As an experiment, I created an extension overload to the HtmlHelper method HiddenFor which accepts an IFormatProvider but I can't suggest using it since I don't know how these providers work well enough to make a fully functional override. I'm a little surprised Microsoft didn't include this but maybe temporarily setting the default thread culture is the "correct" solution...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.