3

I can't see why this would be happening but it is. I'm writing a csv file like this:

foreach (var row in record.rows)
{
    csv += "\n";
    csv += row.FooName + ",";
    csv += row.FooMoney + ",";
}

System.IO.File.WriteAllText(filePath + fileName, csv);

Here's what's fun. When debugging, row.FooMoney (which is of type Decimal) might be 10000. In the written csv it is 10,000 which, naturally, I do not want as commas are my delimiter.

I've tried row.FooMoney.ToString("F"/"G") to no avail...it appears to be formatted during the file write. What gives? Is this intentional?

UPDATE


Here's all the code associated with the issue:

public ActionResult PassJSON(string __obj)
{
    var filePath = Url.Content("~/Temp/");
    var fileName = "Report.csv";

    try
    {
        string csv = string.Empty;
        var records = JsonConvert.DeserializeObject<List<RootReportObject>>(__obj);
        csv += "Date Created,Ref #,Name,Vehicle #,Address,ProductID,Product,Weight1,Weight2,";

        foreach (var record in records)
        {
            var count = record.count;
            var value = record.title;

            csv += "\n" + value + ",,,,,,,,,";

            foreach (var row in record.rows)
            {
                csv += "\n";
                csv += row.DateCreated + ",";
                csv += row.RefNo + ",";
                csv += row.Name + ",";
                csv += row.VehicleNo + ",";
                csv += row.Address1 + ",";
                csv += row.ProductID + ",";
                csv += row.Product + ",";
                csv += row.Weight1.ToString(CultureInfo.InvariantCulture) + ",";
                csv += row.Weight2.ToString(CultureInfo.InvariantCulture) + ",";
            }
        }

        System.IO.File.WriteAllText(filePath + fileName, csv);

        return Json(filePath + fileName, JsonRequestBehavior.AllowGet);
    }
    catch (Exception e)
    {
        return Json(e, JsonRequestBehavior.AllowGet);
    }
}

[Serializable]
public class Row
{
    public int id { get; set; }
    public DateTime DateCreated { get; set; }
    public int RefNo { get; set; }
    public string Name { get; set; }
    public string VehicleNo { get; set; }
    public string Address1 { get; set; }
    public int? ProductID { get; set; }
    public string Product { get; set; }
    public Decimal Weight1 { get; set; }
    public Decimal Weight2 { get; set; }
}

[Serializable]
public class RootReportObject
{
    public bool __group { get; set; }
    public int level { get; set; }
    public int count { get; set; }
    public string value { get; set; }
    public string title { get; set; }
    public int collapsed { get; set; }
    public List<Row> rows { get; set; }
    public object groups { get; set; }
    public string groupingKey { get; set; }
}

Sample Output

8/16/2013 2:31:16 PM,72,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,50,
8/16/2013 2:31:34 PM,73,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,5,000,0,
8/16/2013 2:32:12 PM,74,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,50,
8/16/2013 2:33:15 PM,75,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,50,
8/16/2013 2:50:58 PM,76,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,50,
8/20/2013 7:19:32 PM,77,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,50,
8/20/2013 7:46:03 PM,78,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,40,
8/20/2013 7:55:56 PM,79,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,1,
8/20/2013 8:13:58 PM,80,John Doe,,9021 Beverly Hills Blvd,427,Corn,0,50,
8/21/2013 8:05:25 PM,81,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,5,
8/22/2013 7:33:03 PM,82,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,50,
8/22/2013 7:40:42 PM,83,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,5,
8/22/2013 8:05:25 PM,84,John Doe,LP1234,9021 Beverly Hills Blvd,427,Corn,0,5,000,

UPDATE #2


I deleted the original report.csv to find that the next call to write the report yielded a 404 error from IIS. Evidently the WriteAllText() is no longer writing. Unfortunately I'm not sure what to do about this either. I've altered the code in an attempt to remove any previous version before the write occurs but still get nothing

Altered Code

if (System.IO.File.Exists(filePath + fileName))
  System.IO.File.Delete(filePath + fileName);

System.IO.File.WriteAllText(filePath + fileName, csv);
return Json(filePath + fileName, JsonRequestBehavior.AllowGet);
Mike H.
  • 1,731
  • 9
  • 31
  • @tnw "FooMoney (which is of type Decimal) " – Servy Nov 12 '13 at 19:44
  • A property of a custom object. It's a Decimal. – Mike H. Nov 12 '13 at 19:44
  • May take a peek at this question: http://stackoverflow.com/questions/17810211/convert-decimal-to-string-without-commas-or-dots – tnw Nov 12 '13 at 19:46
  • I doubt that `WriteAllText` is the culprit. What does `csv` look like if you just print it to the screen or inspect it in the debugger? – Brian Rasmussen Nov 12 '13 at 19:47
  • @BrianRasmussen looks perfectly fine. No commas for thousand+ numbers. – Mike H. Nov 12 '13 at 19:48
  • @MikeHometchko Are you opening this in Excel? If so, then Excel is probably the one putting the commas in - try opening in a regular text editor. – Joe Enos Nov 12 '13 at 19:50
  • @JoeEnos the end goal is to use the file in Excel, yes...but the csv, even before being opened in Excel, contains the formatted numbers. – Mike H. Nov 12 '13 at 19:51
  • 4
    @MikeHometchko Then you've got something wrong in your question here. If the value of the `csv` variable doesn't have the commas, and you're writing that value directly to the file, then your file will not have those commas. The `WriteAllText` method definitely is not injecting commas in there. – Joe Enos Nov 12 '13 at 19:54
  • @JoeEnos I appreciate the input Joe, I've added to the question to hopefully open a few more options. – Mike H. Nov 12 '13 at 20:09
  • Even if I edit the original JSON to make the weights strings and put commas in those strings, it deserializes into decimals properly and writes to the output without commas. (`string __obj = "[{\"rows\":[{\"Product\":\"Corn\",\"Weight1\":0,\"Weight2\":\"50\"},{\"Product\":\"Corn\",\"Weight1\":0,\"Weight2\":\"50,000\"}]}]"; `). What .NET framework and OS are you using, and this is real .NET, not Mono, right? – Joe Enos Nov 12 '13 at 20:21
  • @JoeEnos I've found the issue but still looking for a solution...question has been updated. Also, it is indeed .NET 4.0, pure MVC4. – Mike H. Nov 12 '13 at 21:17

2 Answers2

4

Using row.FooMoney.ToString("f") should prevent the thousands separators from being written.

If you're using an odd culture setting which is overriding the default behavior, you can force this via row.FooMoney.ToString("f", CultureInfo.InvariantCulture).

Note that, if you're using .NET 4 or later, you can make this far more efficient via:

System.IO.File.WriteAllLines(System.IO.Path.Combine(filePath, fileName),
   record.Rows.Select(row => row.FooName + "," + row.FooMoney.ToString("f")));
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Note that `CultureInfo.InvariantCulture` also changes other aspects of formatting. Probably quite important will be that it forces `.` as a decimal separator, never `,`, which is probably something the OP will want anyway. –  Nov 12 '13 at 19:49
  • I appreciate the response but it's not culture settings unfortunately. I'll look at the optimized WriteAllLines there though so thanks for the suggestion! – Mike H. Nov 12 '13 at 19:50
  • @MikeHometchko WriteAllText just writes a string, so theres' no conversion happening there... – Reed Copsey Nov 12 '13 at 19:53
  • @ReedCopsey you'd think so wouldn't you? I just can't find any other logical explanation right now...I'm tirelessly running through my code as if it was a problem in a "How Not To Program in.." book. – Mike H. Nov 12 '13 at 19:55
  • @MikeHometchko have you tried `csv += row.FooMoney.ToString("f", CultureInfo.InvariantCulture);` yet? – Scott Chamberlain Nov 12 '13 at 19:56
  • @ScottChamberlain hi Scott! Yea I have, no joy. – Mike H. Nov 12 '13 at 19:57
1

Your filePath variable will contain a path relative to your web application, not to your file system. WriteAllText requires a path on your filesystem.

To get the physical path, you would do Server.MapPath("~/Temp"), which will return c:\websites\mysite\Temp or whatever. From there, you should use Path.Combine(filePath, fileName) to get your full file path and save the file to that location.

Joe Enos
  • 39,478
  • 11
  • 80
  • 136
  • Well cool, thanks for the help...it works perfectly now on local...but tosses a 500 error on my live test bed. I'm thinking it has to do with pathing/routing. Any ideas? – Mike H. Nov 12 '13 at 21:36
  • 500 should get logged in your machine's Event Viewer. My guess would be the IIS user account doesn't have access to write on that directory in the filesystem. You'd need to add file system rights to the appropriate user (depending on how you've got IIS set up, you'll need to figure out which user it is). – Joe Enos Nov 12 '13 at 21:42
  • Actually it was my original problem that led to this one, take a look for a chance at more green checks if you want :P http://stackoverflow.com/questions/19935331/json-deserialization-throws-circular-reference-only-in-local-build – Mike H. Nov 12 '13 at 21:56