Export .sdif file to the client’s desktop

One of the user requirements of the swim team website is to send the .sdif file that I blogged about here from the webpage to the user’s browser – or download it to the users file system. Since the file is dynamic and I can’t write to the file system of the web server, I need a way to generate the file and then have a dialog box “Save To” open.

The first step was to add a UI project to the solution that matches the MVC project that the swim team currently users. I love the organization of the initial project – it was very easy and logical to drop in a new Web project:

image

I then opened up the home controller and added a base method and ported the code from the Console UI:

[HttpPost] public ActionResult GetSdifFile() { string fileName = @"C:\Users\Public\PracticeMeetSetup.SD3"; MeetSetupFactory factory = new MeetSetupFactory(); Collection<string> collection = factory.CreateMeetSetUp(72); File.WriteAllLines(fileName, collection); return View(); }

Basically, I need to rip out the disk write code and replace it with something that can go to the browser. Being a traditional ASP.Net guy, I immediately thought of something like this:

public void Guess(string filePath) { try { using (StreamReader sr = new StreamReader(filePath)) { String line; while ((line = sr.ReadLine()) != null) { Response.Write(line + "<br />"); } } } catch (Exception ex) { Response.Write("<p>The file could not be read:"); Response.Write(ex.Message + "</p>"); } }

I then thought “Wait, this is MVC…” so I thought of something like this:

[HttpPost] public ActionResult GetSdifFile() { MeetSetupFactory factory = new MeetSetupFactory(); Collection<string> collection = factory.CreateMeetSetUp(72); return View(collection); }

And the view displaying the contents of the collection:

<h2>GetSdifFile</h2> <% foreach (string _currentString in Model){ %> <%= Html.Encode(_currentString) %> <br /> <% } %>

And here are the results:

image

So it is a start – I guess they could copy/paste the contents of the page. However, the User Case is for them to click a button and get a .sdif file that saves to their file system (via, I assume, a Save Dialog box).

I wrote a new function that returns JSON:

public JsonResult CurrentMeetSdifFile() { MeetSetupFactory factory = new MeetSetupFactory(); Collection<string> collection = factory.CreateMeetSetUp(72); JsonResult result = new JsonResult(); result.Data = collection; result.JsonRequestBehavior = JsonRequestBehavior.AllowGet; return result; }

Since the browser doesn’t know what to do with JSON (I only tested in IE), then you get a save dialog box:

image

Saving that to the desktop, I open in note pad and get the following results:

image

The results are losing their line formatting.

This is the right track – but I have bit more work to do.

My 1st step was to add a parameter of the actual meet that the user wants:

public JsonResult CurrentMeetSdifFile(int meetId) { MeetSetupFactory factory = new MeetSetupFactory(); Collection<string> collection = factory.CreateMeetSetUp(meetId); Etc… }

I then tried it from the browser:

image

Ugh, it looks like with the default routing engine, I need to make the parameter have the name id. I have a choice. I can either add a new route with an explicit meetId or I can use the id variable name. I chose option B as a path of least resistance:

public JsonResult CurrentMeetSdifFile(int id) { MeetSetupFactory factory = new MeetSetupFactory(); Collection<string> collection = factory.CreateMeetSetUp(id); JsonResult result = new JsonResult(); result.Data = collection; result.JsonRequestBehavior = JsonRequestBehavior.AllowGet; return result; }

With the routing set up, I now need to fix the JSON output to stick a new line after each string in the collection.

My 1st attempt was just to throw an Environment.NewLine into the Json result:

image

Yikes! It looks like I am mixing formatting. “\r\n” is coming down as a literal value. I need a way to tell notepad that they are line breaks.

I binged around a bit and looked at attack overflow. This post seems to have the answer. I tried to add

result.ContentType = "text/html";

But then the browser displayed the data:

image

Note the “\r\n” is still there.

I then tried some other ways of breaking (using the \\n for example), nothing.

I then stepped back and thought that I was approaching the problem incorrectly. Instead of sending back JSON from the function, what if I sent something else? A quick tour through MSDN showed me a file result class. That is what I need and here is an example of my question.

A quick run through the overloads of the method, I realized that all I have to do is to convert the string collection into a FileStream and then send it out via the File class. I used the FileStreamResult class and the rest was pretty easy to wire up:

public FileStreamResult CurrentMeetSdifFile(int id) { MeetSetupFactory factory = new MeetSetupFactory(); Collection<string> collection = factory.CreateMeetSetUp(id); StringBuilder stringBuilder = new StringBuilder(); foreach(string _currentString in collection) { stringBuilder.Append(_currentString); stringBuilder.Append(Environment.NewLine); } byte[] byteArray = Encoding.ASCII.GetBytes(stringBuilder.ToString()); MemoryStream stream = new MemoryStream( byteArray ); FileStreamResult fileStreamResult = new FileStreamResult(stream,"text/plain"); return fileStreamResult; }

And if I want to get the popup, I change the output format to “.sdif” and I get the dialog box with the data formatted correctly.

image

And boom goes the dynamite…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: