Out of Eggs, a web app built in ASP.NET MVC, jQuery & jQuery UI

I’m excited to announce outofeggs.com, a web app I’ve been working on for a while. It’s built on the techniques I’ve gone through in my Categorized Item List series (using ASP.NET MVC, jQuery & jQuery UI). Just create a list and see for yourself. The back end is SQL Server 2008.

It probably goes without saying that I could use any and all feedback: bugs that pop up, features you’d like to see, usability issues, etc. Also let me know if there’s any development-related aspects of the app you’d like me to share in a post that I haven’t covered yet.

Post to Twitter Post to Digg Post to Facebook

Drag and Drop Categorized Item List with jQuery and ASP.NET MVC – Part 4

Controllers and AJAX

This is part 4 of a series. In this post I’ll go through the controller classes and how to use jQuery and AJAX to update the database with the position (or state) of where each section and item is moved to.

Every section can be dragged and dropped into any of the 4 columns and in any position within that column. This is the reason for both the ColumnNum and SortOrder fields of the Sections table described in part 2.

First we’ll dive into jQuery. Going back to our sortable() call for the sections, we need to add code that fires after an update event. The important thing to note here is that the update event will fire for both the column moving from and to. If moving within the same column, it’ll fire only once.

As set up in part 3, the column num is stored in the id attribute of the “listColumn” div, so with a little parsing we can retrieve the column who’s state just changed.

Next we’ll need the new order of the sections within each changed column. The sortable(“serialize”) call forms the section IDs into a “form/ajax submittable string” like this:

section[]=3&section[]=1&section[]=4

For more detail see the jQuery UI sortable page. Look under Methods > serialize.

Now we’ll do an AJAX post to a method within the section controller we’ll create below. Here’s the resulting jQuery:

function InitSectionSorting()
{
    $(".listColumn").sortable(
    {
        …,
        //update event fires both for column leaving and receiving
        update: function(event, ui)
        {
            //Extract column num from current div id
            var colNum = $(this).attr("id").replace(/col_/, "");

            $.post("/Section/UpdateSortOrder",
            { columnNum: colNum, sectionIdQueryString: $(this).sortable("serialize") });
        }
    });
}

In SectionController.cs, we’ll now code the UpdateSortOrder method to receive the serialized string from jQuery and pass it as a string array to it’s model class.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateSortOrder(int columnNum, string sectionIdQueryString)
{
    string[] separator = new string[2] { "section[]=", "&" };
    string[] sectionIdArray = sectionIdQueryString.Split(separator, StringSplitOptions.RemoveEmptyEntries);

    secRepo.UpdateSortOrder(columnNum, sectionIdArray);
    secRepo.Save();

    return Content("Success");
}

The return Content(“Success”) is simply to see that the update was successful using Firebug. You should see the text “Success” within Firebug’s Console tab after you drag and drop a section. It’s optional so you can remove it.

Now on to Items. They can be moved to any section and in any position, so the jQuery and controller code is almost the same Sections.

jQuery:

function InitItemSorting()
{
    $(".itemList").sortable(
    {
        ...,
        //update event fires both for item list leaving and receiving
        update: function(event, ui)
        {
            //Extract section id from parent section box
            var sectionId = $(this).closest(".secBox").attr("id").replace(/section_/, "");

            $.post("/Item/UpdateSortOrder",
                { sectionId: sectionId, itemIdQueryString: $(this).sortable("serialize") });
        }
    });
}

ItemController.cs:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateSortOrder(long sectionId, string itemIdQueryString)
{
    string[] separator = new string[2] { "item[]=", "&" };
    string[] itemIdArray = itemIdQueryString.Split(separator, StringSplitOptions.RemoveEmptyEntries);

    itemRepo.UpdateSortOrder(sectionId, itemIdArray);
    itemRepo.Save();

    return Content("Success");
}

In a later series we’ll cover editing the text of (and deleting) sections and items.

Download the source code (requires Visual Studio 2008 and ASP.NET MVC 1.0)

Post to Twitter Post to Digg Post to Facebook

12 Mbps+ Broadband Internet Options in Fresno, CA (Fall 2009)

It’s Fall 2009 and time to upgrade my home internet service. For all those in Fresno, Clovis and the central valley area with similar needs to mine, hopefully this helps.

In Fresno the only real options I know of are AT&T (DSL or “U-verse”) and Comcast (cable). For the last few years we’ve had AT&T’s DSL Elite (6 Mbps @ $35/month), and that’s been fine, but a few things have changed…

We need more speed…12 Mbps+ speed!
Yes, 6 Mbps downstream is a lot already, but these days we’re watching HD-quality video from Netflix, Hulu and other sources (usually streamed or live). The kicker is my wife is now uploading 10+ gigs of pics after a weekend photo shoot and our 768 Kbps upstream just isn’t cutting it. Here are my “before” speed tests:

We don’t need a home phone line.
Actually we haven’t needed one for a while with two cell phones. But now there’s Google Voice for an extra phone number or Skype and other VOIP services. Cell service has gotten better at our house recently as well.

We don’t need cable or satellite TV.
Our current setup consists of a Tivo HD DVR with integrated Netflix streaming and Amazon VoD. I get excellent HD reception for over-the-air broadcast channels with an outdoor antenna. Plus there are plenty of Redbox kiosks and Blockbusters around the corner while the physical medium for movies still exists. This probably won’t work for hard core sports or movie enthusiasts, but it does for me, my wife and my kids.

Bottom line: We need faster internet and nothing else for our home. So what’s the best deal…

As usual, both AT&T and Comcast try to bundle packages together. They want you to buy it all: internet, phone and TV. For years it’s always been a hassle to subscribe to their services a la carte. For this reason I had to start on online chat with both companies to work out a deal. At least this removes the hassle of doing it over the phone. Usually someone responds via chat within minutes if not immediately.

Obviously internet coverage will vary by specific location, but here are the options I had at my address in 93720.

AT&T U-Verse

DSL only goes up to 6 Mbps downstream currently, but U-Verse has 12 Mbps and 18 Mpbs downstream options ($55 and $65/month respectively). I assume 1-2 Mbps upstream but I forgot to ask and it doesn’t say.

At first they said I needed to subscribe to at least their TV service in addition to internet to get the $55/month internet price. I said I wasn’t interested and they changed it to no TV service required but a $150 installation charge. Not great, but at least there’s no contract.

Comcast Cable

They have the same 12 Mbps and 18 Mbps downstream options for cheaper than DSL ($43 and $53 respectively). Like AT&T, there’s no contract, but they try and steer you away from a la carte. But in chat I got the “stand-alone” internet offer out of them and whittled it down from a $100 to a $50 installation charge. Tack on $3/month for the modem and I’m at $45/month. They also state a 2 Mbps upstream which if even close is awesome.

Winner: Comcast

Bottom line: $10/month cheaper and a $100 cheaper install than AT&T. $17/month cheaper and a $125 cheaper install than AT&T. Pretty easy decision.

Update 9/21/09

Comcast’s website and online chat say one thing (see below), but when I called 1-800-COMCAST, I found out the above applies to the bay area and not Fresno. What they offer here past their 6 Mbps package is a 16 Mbps package (not 12 or 18) with a 2 Mbps upstream.

The cost is cheaper $35/month + $3/month modem rental + $25 install, but it’s only good for a year. It’s not a contract though, so you can cancel anytime. I scheduled my install and plan on doing just that as after a year it doubles to $70/month. At that point I’ll shop around again for the best deal or attempt to negotiate the existing one.

Update 9/24/09

The Comcast guy just left my house. Initial speed tests rock!

The Comcast guy said I should see speeds “burst” when downloading larger files or streaming. And BTW, he also claimed that by the end of this year Comcast is rolling out 50 Mbps downstream / 12 Mbps upstream to all cable modem subscribers in Fresno with this same package. Their lower-cost 6 Mbps downstream package should also double in speed.

Update 10/28/09

The Business Journal reports Comcast’s “wideband” 50 mb/sec is also coming soon. I’ll post here with new speed tests when I’m upgraded.

Update 12/4/09

The cost of the modem rental went from $3/month to $5/month (making my cost now $40/month). Tweeted @comcastcares and they said the Motorola SB6120 (currently $93) is a good one. Considering buying it.

Post to Twitter Post to Digg Post to Facebook

Drag and Drop Categorized Item List with jQuery and ASP.NET MVC – Part 3

Views and Partial Views

This is part 3 of a series. In this post I’ll go through each of the Views (and the List controller). In this post In part 4 I’ll go through the controller classes and how to use jQuery and AJAX to update the database.

We already have the three repository classes in the Models folder. Now we need to add three controller classes to the Controllers folder: ListController.cs, SectionController.cs (for categories) and ItemController.cs.

Next we’ll create a proper View for individual list records. For now we’ll continue to use the single hardcoded list record, so we’ll redirect from the Home controller/Index action to the List controller/Details action with the ID of 1. The List controller code is simply:

using CategorizedItemsListDemo.Models;

namespace CategorizedItemsListDemo.Controllers
{
    public class ListController : Controller
    {
        private ListRepository listRepo = new ListRepository();

        public ActionResult Details(long id)
        {
            List singleList = listRepo.GetById(id);
            return View(singleList);
        }
    }
}

For now we don’t need to code up anything in the Section and Item controller classes, so we’ll move on to the views. The parent view we’ll use is the List/Details view. Since we’ll be looping through to add child Section records to the List record, and child Item records to each Section record, we’ll create two “partial views” (one for individual sections, one for individual items). This way user interface markup can be encapsulated without being repetitive (remember DRY – don’t repeat yourself).

Coming from an ASP.NET WebForms background, I equate partial views to the MVC way of doing user controls. They in fact use the same .ascx extension. I also added them to the /Views/Shared folder so the MVC engine can easily locate them. To sum it up, here are the three views added and the containing code:

/Views/List/Details.aspx

<% for (int i = 1; i <= 4; i++) { %>
    <div class="grid_3 listColumn" id="col_<% =i %>">
        <% foreach (Section sec in Model.Sections.Where(s => s.ColumnNum == i).OrderBy(s => s.SortOrder)) { %>
            <% Html.RenderPartial("SingleSection", sec); %>
        <% } %>
    </div>
<% } %>

Here the outside loop is simply going through each of the four columns setting the id attribute to the record id for use in jQuery. The inner loop is going through each Section in the List record (referenced by “Model” since the view is bound to the List model class). It simply uses a Lambda expression to render the Sections in the correct columns in the correct order. Then it passes off each individual Section to the SingleSection partial view.

/Views/Shared/SingleSection.ascx

<div class="secBox" id="section_<%= Model.SectionId %>">
    <div class="secHeader">
        <h2 class="secName"><%= Html.Encode(Model.SectionName) %></h2>
    </div>

    <div class="itemBox">
        <ul class="itemList">
            <% foreach (Item item in Model.Items.OrderBy(i => i.SortOrder)) { %>
                <% Html.RenderPartial("SingleItem", item); %>
            <% } %>
        </ul>
    </div>
</div>

Here we’re basically applying the same format from the List view to the Section partial view. Each Section is surrounded by a div with the id attribute set to the record id. “Model” is now bound to the Section model class, which we then use to display the Section name and loop through child Item records. We display Items in the correct sort order using a Lambda expression, then pass off each Item record to another partial view.

/Views/Shared/SingleItem.ascx

<li class="itemRow" id="item_<%= Model.ItemId %>">
    <span class="itemName"><%= Html.Encode(Model.ItemName) %></span>
</li>

This partial view is the simplest (for now). Again the id attribute is set to the record id. After that we simply render the item name.

That’s it. Now the app is rendering real data using MVC views. Nothing is hardcoded. To get things looking like they did in the initial layout, I populated the SQL database with sample data.

Download the source code (requires Visual Studio 2008 and ASP.NET MVC 1.0)

Post to Twitter Post to Digg Post to Facebook

Tech Company Mentality in Fresno

My friend Robert Schultz recently gave his opinion on software programmer mentality in Fresno. I personally think it speaks to a larger issue going on with tech companies themselves in the Fresno/Clovis area.

I was born and raised in Fresno, and for at least 90% of the last 12 years I’ve been a full-time software developer for 6 different companies in the area. I hate to say it, but with most of them it was only about a year or two before I had to put in my resignation. They all had great people and great potential. But there was always some big setback that eventually caused me to leave.

Most recently my issues with these companies have been with both business direction and how they valued their developers. As engineers, we want to create and have our ideas listened to and our accomplishments valued. Lack of this is the main fault of most of the places I’ve worked for in Fresno (some more than others of course). Developers should never be treated as just “task monkeys” and handed a to-do list of specific items to check off. Many fall into that trap simply because that’s how it’s been for them for so long. At the point that it becomes “just a job” and they can’t wait until the clock hits 5 or 6 every day, and that’s only if they’re lucky and not forced into overtime.

Some of us have entrepreneurial aspirations and some do not, and that’s fine. But I think all developers want to contribute ideas and be in on the decision-making process wherever we work. We want to innovate all the time, and from my experience companies around here give little effort if at all to encouraging this process. At companies like Google it’s part of your job description. It’s no secret that sometimes half their new services came out of their “innovation time” policy. Plenty of startups elsewhere do something similar. Managers and company owners need to be open with their business goals and ask their people to openly discuss ideas and company direction. I know I would enjoy my job more if that was part of my responsibilities.

And I don’t think companies realize this, but with poor developer treatment they are taking a huge hit in efficiency. Projects start going in the wrong direction because they’re not listening to their people. In turn employees start working at a 25% motivation level because they don’t feel valued. The company starts falling way behind in current technology. Then developers stuck in this old technology realize they’re not going anywhere with their skills. It’s a vicious cycle. Developers that get fed up start looking elsewhere for something better, and when they have a tough time finding a better job around Fresno, they leave. That’s part of the “brain drain” we hear about.

Back to company mentality, we’re still behind in technology for the most part in Fresno from what I’ve experienced. Where are the companies really using social media or blogging regularly? Why do I still hear more about building Windows apps than mobile apps? Why do all these local companies spend so much time and money hosting their own servers (for internal use or external clients) instead of co-locating? It isn’t new news anymore that using cloud services (Google, Amazon or otherwise) are much more reliable, speedier and secure. Why are people still maintaining Exchange servers and installing Office on every workstation? Even Microsoft, who benefits from all the companies sticking with “classic” Exchange and Office setups realizes this is inevitable. They can host Exchange for you and are coming out with a browser-based version of Office 2010. Even Washington DC moved to Google Apps. At least consider What Would Google Do? This is 2009 people!

Myself and a handful of good developers I know in Fresno are very rooted here and thus determined to find the best place to work that they can. (That or start their own company). For me it’s because family and friends around here come before my career. Take that away from me and I’m out to bigger “tech hubs.” I know personally some good developers here that aren’t as rooted are just waiting for the right opportunity to leave. The business case for local startups Plastic Jungle (only local company I’ve seen on TechCrunch) and Vine Global (winner of last year’s Start-It-Up contest) to stay put were not enough, so recently they both left.

On behalf of all software developers in Fresno and Clovis (let alone the startup scene and effect on the economy locally), I sure hope this trend turns around soon.

Post to Twitter Post to Digg Post to Facebook

←Older