views:

1741

answers:

4

I'm working with the NerdDinner sample application and arrived at the section which deals with the Virtual Earth map. The application stores some values for the longitude and latitude. Unfortunately on my system floating point numbers are stored with a comma as the decimal separator, not a dot like in the US. So if I have a latitude of 47.64 it's retrieved and displayed as 47,64. Because that value is passed in a function call to the Virtual Earth API it fails at that point (e.g. JavaScript API expects 47.64, -122.13, but gets 47,64, -122,13).

I need to make sure that the application always uses dots. In a WebForms app I would have a common class which overrides the System.Web.UI.Page.InitializeCulture() method and I would be inheriting my pages from that class.

I am not sure about how to do the same with MVC. Do I need a customized ViewPage or something? Is there an easy way to solve this? Examples?

A: 

When you say

on my system floating point numbers are stored with a comma as the decimal separator

I assume you mean that they are formatted with a comma, floating point numbers are stored as float.

Whilst you can tackle the formatting issue by setting Cultures the "real" fix is to change the code. OK, it's not your code so maybe you don't want to do that on this occassion, but for general reference you need to ensure that when formatting floats or anything else you use the appropriate culture. In the case of fomatting a number for use by an API you would use the InvariantCulture.

I.e. use foo.ToString(CultureInfo.InvariantCulture) instead of foo.ToString() and likewise when using string.Format(...).

Edit I've just taken a look at the NerdDinner code and have realised that this error is in the Javascript not in C#, so my code above isn't going to help. I don't know if it is possible to format numbers in Javascript, but the real solution I think is to fix the model code to return a correctly formatted string.

Edit 2 I'd suggest you try the following: In the SearchController.cs change the Latitude and Longitude in JsonDinner to strings. i.e.

public class JsonDinner {
    public int      DinnerID    { get; set; }
    public string   Title       { get; set; }
    public string   Latitude    { get; set; }
    public string   Longitude   { get; set; }
    public string   Description { get; set; }
    public int      RSVPCount   { get; set; }
}

Then scroll down to the SearchByLocation method and change the Lat/Long lines to format the strings correctly for JavaScript:

Latitude = dinner.Latitude.ToString(CultureInfo.InvariantCulture),
Longitude = dinner.Longitude.ToString(CultureInfo.InvariantCulture),

This should mean that you do not need the fix you put in, and should fix your other question... where I will leave a comment. Hope this helps, I haven't fully tested is as I am not in your locale, but it certainly appears to work.

Steve Haigh
I am in Chapter 11 of that book. Haven't seen that JsonDinner class yet. :) Thanks for the effort, Steve, I will check it out soon (and will let you know)!
Pawel Krakowiak
Specifically, I'm here - http://nerddinnerbook.s3.amazonaws.com/Part11.htm
Pawel Krakowiak
I worked until the "Integrating the Map with Create and Edit Forms" section and that's where it breaks. You probably looked at the SVN version and it may be different code. I am just following the book writing it / pasting myself.
Pawel Krakowiak
Yeah, my fix only gets you a little further I'm afraid... the problem is that the VE Javascript just can't deal with comma separators - either passed in or retrieved. You can fix the issue of passing them in using my fix, but when you try and save a form the posted back data contains "." separators again and can't be parsed by the repository:-(
Steve Haigh
Probably you worded it in a better way, but that's essentially what I was trying to say from the very beginning. I still have no clue why <globalization /> tag in web.config does not fix it, though. I would expect it to work just like in WebForms app.
Pawel Krakowiak
+1  A: 

Because setting <globalization/> to en-US did not help at all I decided to create a custom class which initializes the proper culture settings and make sure that all views which require this behavior are inherited from my custom class.

NerdDinnerViewPage.cs:

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

namespace NerdDinner.Views
{
    public class NerdDinnerViewPage<T> : ViewPage<T> where T : class
    {
        protected override void InitializeCulture()
        {
            base.InitializeCulture();

            Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentCulture.Clone() as CultureInfo;

            if (Thread.CurrentThread.CurrentCulture != null)
            {
                Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparator = ".";
                Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator = ".";
            }
        }
    }
}

Edit.aspx:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="NerdDinner.Views.NerdDinnerViewPage<NerdDinner.Models.DinnerFormViewModel>" %>
Pawel Krakowiak
+1  A: 

I'm a Danish developer and was facing exactly the same problem. I found a working solution which has been kindly described by Kristof Neirynck on his dev blog:

Custom Model Binder

Best regards, Finn Vilsbaek

A: 

I'm using a simple quickfix in the TemplateEditor. My application is only using swedish (comma as decimal separator) so it's a single string.Replace but you could of course make it aware of multiple cultures.

In my Views/Shared/EditorTemplates/Decimal.ascx:

<%= Html.TextBox(string.Empty, ViewData.TemplateInfo.FormattedModelValue.ToString().Replace('.',',') %>

Jonas Stensved