Google Charts API in MVC C#

So I saw the new Google Charts API and decided it would be interesting to play with.  I had played with it 5 years ago or so when it first came out, and it has come a long way.  The developer documentation seems solid to work from, and its just javascript so it can't be that hard.  Plus, even if the doc isn't 100% easy to understand, any example they have is basically open source via view source, so you can easily figure out a lot.  The piece I was really after was the sliding bar to restrict ranges, it took a while, and was worth it.  I also added some cool functionality like clicking a data set in the legend and having it disappear.
I decided to embed it in MVC as that's the technology my current job has me using the most.  I wanted to make a generic wrapper in MVC for the Charts API so I could take any data set and throw it at any chart on the fly and see the different charts, without changing code.  Turned out rather awesome, though it doesn't work the best in IE always, Chrome is much more consistent.
So here we go, the first thing I will show is the nuts and bolts of the entire project, the one view that has all the javascript in it.  I will try to discuss the pieces here as there is a lot going on.
@model PPCOP_OrderProcessingReports.Models.ReportFetcher
@{
    ViewBag.Title = "Report";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.0','packages':['controls']}]}"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(drawChart);

      function drawChart() {
          var rawdata = @Html.Raw(Model.OrdersForGoogleChart())
          var data = google.visualization.arrayToDataTable(rawdata);

          $("#chart_div").empty();
          $("#chart_div").html('<div id="scatterchart_div"></div>' +
          '<div id="filter_div"></div>');

          var dashboard = new google.visualization.Dashboard(
            document.getElementById('chart_div'));

          var rangeSlider = new google.visualization.ControlWrapper({
              'controlType': 'NumberRangeFilter',
              'containerId': 'filter_div',
              'options': {
                  'filterColumnLabel': 'Range',
                  'ui.labelStacking': 'vertical',
                  'ui.showRangeValues': false
              }
          });

          // create columns array
          var columns = [];
          var series = {};
          for (var i = 0; i < data.getNumberOfColumns() ; i++) {
                  columns.push(i);
                  if (i > 0) {
                      // set the default series option
                      series[i - 1] = {};
                  }
          }

          var options = {
              width: '100%',
              height: 300,
              title: '@Html.Raw(Model.DataName)',
              legend: '',
              lineWidth: 1,
              hAxis: { title: '@Html.Raw(Model.LegendHAxis)' },
              vAxis: { title: '@Html.Raw(Model.DataName)' },
              pointSize: 1,
              series: series
          };

          var chart = new google.visualization.ChartWrapper({
              //'chartType': 'ScatterChart',
              //'chartType': 'LineChart',
              'chartType': '@Html.Raw(Model.ChartType)',
              'containerId': 'scatterchart_div',
              'options': options,
          });

          dashboard.bind(rangeSlider, chart);
          dashboard.draw(data);

          google.visualization.events.addListener(chart, 'ready', function () {
              google.visualization.events.addListener(chart.getChart(), 'select', function () {
                  var sel = chart.getChart().getSelection();
                  // if selection length is 0, we deselected an element
                  if (sel.length > 0) {
                      // if row is undefined, we clicked on the legend
                      if (sel[0].row == null) {
                          var col = sel[0].column;
                          //if (columns[col] == col) {
                          if (columns[col] == col) {
                              // hide the data series
                              columns[col] = {
                                  label: data.getColumnLabel(col),
                                  type: data.getColumnType(col),
                                  calc: function () {
                                      return null;
                                  }
                              };

                              // grey out the legend entry
                              series[col - 1].color = '#CCCCCC';
                          }
                          else {
                              // show the data series
                              columns[col] = col;
                              series[col - 1].color = null;
                          }
                          var view = new google.visualization.DataView(data);
                          view.setColumns(columns);
                          chart.getChart().draw(view, options);
                      }
                  }
              })
          });

          var table = document.createElement('table');
          $("#data_div").empty();
          var dataoutput = "<table style='width:100%;text-align:center;border: 1px solid black;'>";
          for(var x = 0; x < rawdata.length; ++x)
          {
              dataoutput += "<tr style='border: 1px solid black;'>";
              for(var y = 0; y < rawdata[0].length; ++y)
              {
                  dataoutput += "<td style='border: 1px solid black;'>"+rawdata[x][y]+"</td>";
              }
              dataoutput += "</tr>";
          }
          $("#data_div").html(dataoutput+"</table>");
      }
    </script>
    @using (Html.BeginForm()) {
        @Html.ActionLink("Load Data", "LoadData")
        @Html.ValidationSummary(true)
        <table>
            <tr>
        <td>Select Brand
        @Html.DropDownListFor(x=>x.BrandId, new SelectList(ViewBag.Brands,"Id","Name"))</td>
        <td>Select Time Buckets
        @Html.DropDownListFor(x=>x.TimeSpanId, new SelectList(ViewBag.TimeSpans,"Id","Name"))</td>
        <td>Select Source
        @Html.DropDownListFor(x=>x.SourceId, new SelectList(ViewBag.Sources,"Id","Name"))</td>
        <td>Select Data
        @Html.DropDownListFor(x=>x.DataId, new SelectList(ViewBag.DataTypes,"Id","Name"))</td>
        <td>Select Chart Type
        @Html.DropDownListFor(x=>x.ChartType, new SelectList(ViewBag.ChartTypes,"Name","Name"))</td>
                <td>Align Weeks (only on days)
        @Html.CheckBoxFor(x=>x.AlignWeeks)</td>
        <td><input type="submit" value="Update" /></td>
                </tr>
        </table>
    }
<br />
<div id="chart_div" style="width:100%; height:330px"></div>
The first thing to note is the included files.  Jquery 1.71, and two jsapi includes from google which give the chart api.  
The next thing to note is the javascript I wrote.  the first things done are the loading of the google objects.  After that the drawChart() function is created and it is invoked by the google.setOnLoadCallBack event.
The drawChart function is the nuts and bolts of the chart drawing.  What I do is pass the data to google via a two dimensional array that I construct in a class in my mvc from some database.  It is in simple [[1,1,1],[1,1,1]] structure.  Note I had to pass the semicolon from c# as razor was throwing a fit about it in the JavaScript behind the server tag.  
Once the data is loaded, google has a good function called arrayToDataTable that converts it on the fly to the correct data table type.  Next a few html operations are done in jquery to get the correct spot to dump the chart.  This is also where my range slider is declared and tied to the range of the data set.
After that I create column arrays.  This is needed for my hiding functionality.  Basically, I store the columns of the data set and if they are clicked in the legend, I hide them.  This is done lower in the code under the addlisteners on ready and select below the dashboard bind and draw.
The actual drawing of the chart is in the call ChartWrapper, it takes in the options object declared before it.  This is where I pass in the axis and title dynamically to draw the chart.  The chartWrapper call takes in chart type dynamically you can see, these are all controlled from the model, and influenced by the drop down lists you see at the bottom of the html page.
Next, I will show you the controller code.
public ActionResult Report()
        {
            var ctx = new PPCOPDataDataContext();
            ViewBag.Brands = (from a in ctx.tbl_Brands select a).OrderBy(c=>c.Name).ToList();
            ViewBag.TimeSpans = (from a in ctx.tbl_TimeSteps select a).OrderBy(c => c.Name).ToList();
            ViewBag.Sources = (from a in ctx.tbl_Sources select a).OrderBy(c => c.Name).ToList();
            ViewBag.DataTypes = (from a in ctx.tbl_SourceNames where a.SourceId == 0 select a).OrderBy(c => c.Name).ToList();
            ViewBag.ChartTypes = GetChartTypes();
            return View(new Models.ReportFetcher() { BrandId = 17, DataId = ViewBag.DataTypes[0].Id, DataName = ViewBag.DataTypes[0].Name, ChartType="ScatterChart", LegendHAxis = this.LegendHAxis.Split('|')[0] });
        }
        [HttpPost]
        public ActionResult Report(Models.ReportFetcher fetcher)
        {
            var ctx = new PPCOPDataDataContext();
            ViewBag.Brands = (from a in ctx.tbl_Brands select a).OrderBy(c => c.Name).ToList();
            ViewBag.TimeSpans = (from a in ctx.tbl_TimeSteps select a).OrderBy(c => c.Name).ToList();
            ViewBag.Sources = (from a in ctx.tbl_Sources select a).OrderBy(c => c.Name).ToList();
            ViewBag.DataTypes = (from a in ctx.tbl_SourceNames where a.SourceId == fetcher.SourceId select a).OrderBy(c => c.Name).ToList();
            ViewBag.ChartTypes = GetChartTypes();
            if (!(ViewBag.DataTypes as IList<tbl_SourceName>).Any(c => c.Id == fetcher.DataId))
            {
                fetcher.DataId = ViewBag.DataTypes[0].Id;
                fetcher.DataName = ViewBag.DataTypes[0].Name;
            }
            else
            {
                fetcher.DataName = (ViewBag.DataTypes as IList<tbl_SourceName>).Where(c => c.Id == fetcher.DataId).First().Name;
            }
            fetcher.LegendHAxis = this.LegendHAxis.Split('|')[fetcher.TimeSpanId];
            return View(fetcher);
        }

        public IList<ChartTypes> GetChartTypes()
        {
            var returner = new List<ChartTypes>();

            returner.Add(new ChartTypes() { Name = "ScatterChart" });
            returner.Add(new ChartTypes() { Name = "AreaChart" });
            returner.Add(new ChartTypes() { Name = "LineChart" });
            returner.Add(new ChartTypes() { Name = "Histogram" });
            returner.Add(new ChartTypes() { Name = "ColumnChart" });
            returner.Add(new ChartTypes() { Name = "BarChart" });
            returner.Add(new ChartTypes() { Name = "ComboChart" });

            return returner;
        }
You can see I have the Report get and post functions plus a getcharttypes function.  Things to note in here are me just constructing my model and returning it.  The get is all defaults and drop down populations with simple lists.  The GetChartTypes is an example of a function to return a list of types to put in a drop down list.  They are simply the names that google gave them so I can pass them straight to the dashboard object in javascript, real easy.  My post method gets the drop down selections and updates the model and responds it to update the chart.  
The last piece is the code that generates the array list.  It comes from a class called Report Fetcher you can see.  I obviously could extract that better but this is rather specific for the program so I didn't take it that far, though one could and create a very generic class that anyone could reuse.  I am not going to share that code as it ties in a lot of business logic now, but your just constructing a 2 dimensional array, not rocket science.  
Looking back, I should mention the checkbox that aligns days.  I was displaying order data here, and I wanted to line weeks up by day of week from the previous year, so I created a table of year offsets to line up thanksgiving day and offset all days of the year.  This allows us to view our order history from previous years for the same weeks, it works well.

Getting Your new Chicks (chickens, turkeys, and ducks)

So the local store called and said my chicks were in at 8PM last night and asked if I can pick them up by 9.  A 30 minute drive later and I was driving home with a box full of 5 bronze turkeys, 5 aracanas chickens, and 5 pekin ducks with the heater blasting because it is only 17 outside.  
This isn't my first go around with chicks, so I ran out to the shed, got my brooder boxes, chick feeders, waters and heat lamps, brought them in the house and set up shop.  
I use paper towels that I swap out a few times a day for bedding, it just quick and efficient to change and doesn't make a huge mess when I do, I know some say its harder on the feet, but it seems soft enough and I have never experienced foot problems so use this tactic.  I do have 2 brooder boxes, but wanted both heat lamps on the same box for a few days to make sure they were warm enough.  
http://www.backyardchickens.com/a/how-to-raise-baby-chicks-the-first-60-days-of-raising-baby-chickens says it should be 95 degrees in the brooder in the spot under the light the first week, and can drop 5 degrees a week until you reach ambient.  This seems to work for me.  
From what I have read, turkeys don't do the best with chickens and ducks because they are susceptible to diseases the other breeds carry, so I separated them with a barrier.  I added the water, dipped their noses in it, gave them some chick starter feed, then off to bed.
The whole thing sort of looks like a spaceship, but the kids and cats love looking in, and the peeping is one of my favorite things about spring.

Uploading Image Logo in MVC Razor C#

I am creating a web app that can be accessed from many different users and they can upload their own logo to display when they visit.  This is how I accomplished this with MVC 4.0 with Razor and C#. 

 

First, my requirements are to upload any image format to display on the web page.  I want them to load it from their computer, I will then store it in a directory based on the user in my images directory.  I want to resize the image to 128 max width while preserving scale of width to height.

First I put together the view piece.  This is rather simple, I just used the input type file tag.  I also put an image tag next to it to show the current logo if one had previously been uploaded.  This needs to exist in a form which I declare with the Html.BeginForm and decide to give it parameters, mostly the enctype="multipart/form-data".  It seems if I don't include this, the image doesn't get caught by the controller.

@using (Html.BeginForm("DepartmentEdit", "Admin", FormMethod.Post, new { enctype="multipart/form-data" }))
{
    @Html.ValidationSummary(true)

        <div class="editor-label">
            @Html.LabelFor(model => model.Logo)
        </div>
        <div class="editor-field">
            <img src="~/Images/@Model.Id/@Model.Logo" />
            <input type="file" name="file" />
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
}

Next, I moved to the controller.  Here I create a post version of my function to post not only my model to, but also the HttpPostedFileBase which is the uploaded file.  I check the file is there and an image, and then prepare to save it by first, making sure the directory I am saving it to exists, and then resizing them image.  I finish by saving a reference to the image in my data store and saving the image. 

[HttpPost]
        public ActionResult DepartmentEdit(DepartmentModel input, HttpPostedFileBase file)
        {
            if (file != null && file.ContentLength > 0 && file.ContentType.Contains("image"))
            {
                if (!Directory.Exists(Server.MapPath(String.Format("~/Images/{0}/", input.Id))))
                    Directory.CreateDirectory(Server.MapPath(String.Format("~/Images/{0}", input.Id)));
                input.Logo = System.IO.Path.GetFileNameWithoutExtension(file.FileName) + ".jpg";
                using (var bmp = new Bitmap(file.InputStream))
                {
                    int width;
                    int height;
                    if (bmp.Width > bmp.Height)
                    {
                        width = 128;
                        height = 128 * bmp.Height / bmp.Width;
                    }
                    else
                    {
                        height = 128;
                        width = 128 * bmp.Width / bmp.Height;
                    }
                    using (var thumb = new Bitmap(width, height))
                    using (var graphic = Graphics.FromImage(thumb))
                    {
                        graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                        graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

                        graphic.DrawImage(bmp, 0, 0, width, height);
                        using (var output = System.IO.File.Create(Server.MapPath(String.Format("~/Images/{0}/{1}", input.Id,input.Logo))))
                        {
                            thumb.Save(output, System.Drawing.Imaging.ImageFormat.Jpeg);
                        }
                    }
                }
            }
            ...
            return RedirectToAction("Index", "Admin");
        }

DIY Rabbit Cages, mostly from scrap.

Rabbit hutch / cage
I grew up with rabbits and always enjoyed the having them as pets.  I try to expose my children to the things I cherish from my childhood so this year I put get the kids bunnies for Easter on my list.  One of the first steps with any pet, is how to house it, so I set off to create some rabbit hutches.  These are meant to be inside hutches (inside garage / shed) as I am building an animal barn later this year to house such things.  I also have a good deal of materials around my house that I want to recycle so I am hoping to keep my costs under $100 dollars for 4 hutches, considering each would cost almost $200 in the store, this is a considerable savings when making 4.  Now, I could have just got wire cages, but I like the idea of a little more space and a dark area they can retreat to if they like.  Plus, we are considering breeding them, so a little extra space is good.
So my garage weekend project began, I started by cutting some new 2x4's to size and screwing them together with 3" screws.  The sides are 48 inches long and 19" tall.  Here is the first one, I constructed all 8 sides to start.
Once the sides were done, I screwed them together with 24" pieces and screened the screened sides while they were still easy to move.  I also put in support pieces for the bottom, I just ripped some 2x4 in half for these.
At this point, I got all 4 framed together and the flooring in the open half.  I should note the flooring is some plastic type that I thought may be better on their feet, we shall see if it holds up to their chewing.
Next, I screwed on the plywood (tore off a house I deconstructed recently) for the box half.  I also screwed some green treated 2x4 on the side for legs.  I didn't use green treated lumber for any part that could get chewed on for obvious reasons.  I then put a lower hutch under it and repeated for the other two.  Finally I created doors for them and they were done, as seen at the top of this post.  Not pretty, but functional and cheap.

Session Objects in MVC

So I was creating a new web app that needed some global configurations loaded depending on the user.  To do this, I wanted to create an object to store in session and be able to retrieve easily.  This is my first attempt at solving this, I will say I am not happy with this and it seems like it could be cleaner, though it is a start.  I will attempt to refine and post any better alternatives as I come across or develop them.  
The thing I like about MVC is how decoupled the pieces are, but sometimes you just need a global set of variables, for instance, a site that has multiple urls pointed at it that needs to render to a different user group depending on the calling URL / URI, this is what I did.
public class SessionObj
    {
        public IList<string> Pages { get; set; }
        public Department Department { get; set; }

        public SessionObj(string uri)
        {
            var ctx = new DBMLDataContext();
            var dept = (from a in ctx.Departments where a.URI == uri select a).FirstOrDefault();
            if (dept == null)
            {
                dept = new Department() { Id=-1, Pages=null, URI="", Address="", Calls=null, City="", Email="", Logo="", Members=null, Name="", Phone="", State="", Zip="" };
            }
            Department = dept;
            Pages = new List<string>();
            foreach (var p in dept.Pages)
            {
                Pages.Add(p.Name);
            }
        }
    }
The above class represents my session.  It basically looks at the URI and determines which department it is based on it.  It then loads some common session variables that the page layout for the site uses a lot, so putting it in the session is a nice way to reduce sql calls.  It isn't very heavy, only 4 or 5 string variables and 2 ints.
Next I need to tie this into the Global class.  I basically add the following to the Global.asax.cs MvcApplication class.
void Session_Start(object sender, EventArgs e)
        {
            HttpContext.Current.Session.Add("_SessionObj", new SessionObj(HttpContext.Current.Request.Url.Authority));
        }

        public static SessionObj GetMySessionObject(HttpContextBase current)
        {
            return current != null ? (SessionObj)current.Session["_SessionObj"] : null;
        }
And like that we now have that class in the session once the site is loaded for a user.  I can now load that data in a controller like such.

returner.Session = MvcApplication.GetMySessionObject(this.HttpContext);
Or in the view (layout) like this.
@Model.Session.Department.Name
Again, not the cleanest, but a working method that seems easily upgraded later as it doesn't tie into too many things. Let me know if you have a better way, I love better ways.