<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ToDerp.Data.Models;
using ToDerp.Data.Services;


namespace ToDerp.Areas.Api.Controllers
{
    public class TodoController : Controller
    {
        private DerpRepository _repo;

        public TodoController()
        {
            _repo = new DerpRepository(); // *very* poor man's IOC
        }
        //
        // GET: /Api/Todo/

        public JsonResult Index()
        {
            var items = _repo.AllItems().OrderBy(i => i.Completed).ThenByDescending(i => i.CreatedAt);
            return Json(items.ToArray(), JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public JsonResult Item(TodoItem item)
        {
            _repo.Add(item);
            return Json(item);
        }

        [HttpPut]
        public JsonResult Item(int id, TodoItem item)
        {
            var dbItem = _repo.Single(id);
            dbItem.Completed = item.Completed;
            dbItem.TaskName = item.TaskName;
            if (dbItem.Completed)
                dbItem.CompletedAt = DateTime.Now;
            else 
                dbItem.CompletedAt = null;
            _repo.Save();
            return Json(dbItem);
        }
    }
}
<file_sep>Basic Todo Application for CoffeeScript and Backbone demo

It's basically a crummy ASP.NET and Entity Framework (code first) backend to power an intro to CoffeeScript and Backbone demo. All the Backbone stuff happens in the app.coffee file.
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ToDerp.Data.Models;

namespace ToDerp.Data.Services
{
    public class ToDerpContext : DbContext
    {
        public DbSet<TodoItem> TodoItems { get; set; }
    }

    public class DerpRepository : IDisposable
    {
        private ToDerpContext _context;

        public DerpRepository()
        {
            _context = new ToDerpContext();
        }

        public IQueryable<TodoItem> AllItems()
        {
            return _context.TodoItems.AsQueryable();
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        public void Add(TodoItem item)
        {
            _context.TodoItems.Add(item);
            Save();
        }

        public void Dispose()
        {
            if (_context != null)
            {
                _context.Dispose();
            }
        }

        public TodoItem Single(int itemId)
        {
            return AllItems().FirstOrDefault(i => i.TodoItemId == itemId);
        }
    }
}
<file_sep>﻿(function() {
  var parseSerializedDate;

  parseSerializedDate = function(text) {
    return new Date(parseInt(text.substr(6)));
  };

  Handlebars.registerHelper('prettydate', function(text) {
    var ampm, d, hours, months;
    if (text === void 0) {
      return '';
    }
    if (text == null) {
      return '';
    }
    d = parseSerializedDate(text);
    hours = d.getHours() + 1;
    ampm = "AM";
    if (hours > 12) {
      hours -= 12;
      ampm = "PM";
    }
    months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    return "" + hours + ":" + (d.getMinutes()) + " " + ampm + "  " + months[d.getMonth()] + " " + (d.getDate()) + ", " + (d.getFullYear());
  });

}).call(this);
<file_sep>﻿using System.Web;
using System.Web.Optimization;

namespace ToDerp
{
    public class BundleConfig
    {
        // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/derp").Include(
                        "~/Scripts/lib/jquery-1.8.3.js", 
                        "~/Scripts/lib/underscore.js",
                        "~/Scripts/lib/handlebars-1.0.rc.1.js",
                        "~/Scripts/lib/bootstrap.js",
                        "~/Scripts/lib/backbone.js",
                        "~/Scripts/extensions.js",
                        "~/Scripts/app.js"));


            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/lib/modernizr-*"));

            bundles.Add(new StyleBundle("~/bundles/style").Include(
                "~/Content/bootstrap.css",
                "~/Content/app.css"
                ));

        }
    }
}<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ToDerp.Data.Models
{
    public class TodoItem
    {
        public TodoItem()
        {
            CreatedAt = DateTime.Now;
        }

        public int TodoItemId { get; set; }
        public string TaskName { get; set; }
        public bool Completed { get; set; }
        public DateTime CreatedAt { get; set; }
        public DateTime? CompletedAt { get; set; }
    }
}
<file_sep>﻿(function() {
  var BaseView, Controller, FormView, TodoItem, TodoItems, TodoView, _ref,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  TodoItem = (function(_super) {

    __extends(TodoItem, _super);

    function TodoItem() {
      return TodoItem.__super__.constructor.apply(this, arguments);
    }

    TodoItem.prototype.urlRoot = '/api/Todo/Item';

    TodoItem.prototype.idAttribute = 'TodoItemId';

    return TodoItem;

  })(Backbone.Model);

  TodoItems = (function(_super) {

    __extends(TodoItems, _super);

    function TodoItems() {
      return TodoItems.__super__.constructor.apply(this, arguments);
    }

    TodoItems.prototype.model = TodoItem;

    TodoItems.prototype.url = '/api/Todo';

    return TodoItems;

  })(Backbone.Collection);

  BaseView = (function(_super) {

    __extends(BaseView, _super);

    function BaseView() {
      return BaseView.__super__.constructor.apply(this, arguments);
    }

    BaseView.prototype.parseForm = function() {
      var inputs, parseFn,
        _this = this;
      inputs = this.$('input');
      parseFn = function(obj, input) {
        var inputName;
        input = $(input);
        inputName = input.attr('name');
        obj[inputName] = input.is('[type=checkbox]') ? input.is(':checked') : input.val();
        return obj;
      };
      return _.reduce(inputs, parseFn, {});
    };

    BaseView.prototype.createTemplate = function() {
      var _ref;
      this.template = (_ref = this.template) != null ? _ref : Handlebars.compile($(this.templateId).html());
      return this.template;
    };

    BaseView.prototype.render = function() {
      var tmpl;
      tmpl = this.createTemplate();
      this.$el.html(tmpl(this.model.toJSON()));
      return this;
    };

    return BaseView;

  })(Backbone.View);

  FormView = (function(_super) {

    __extends(FormView, _super);

    function FormView() {
      return FormView.__super__.constructor.apply(this, arguments);
    }

    FormView.prototype.el = '#create';

    FormView.prototype.initialize = function() {
      return this.reset();
    };

    FormView.prototype.events = {
      'submit': 'formSubmitted'
    };

    FormView.prototype.reset = function() {
      this.$('[name=TaskName]').val('');
      return this.model = new TodoItem;
    };

    FormView.prototype.formSubmitted = function(ev) {
      ev.preventDefault();
      this.model.save(this.parseForm());
      this.trigger('TodoItem:Created', this.model);
      return this.reset();
    };

    return FormView;

  })(BaseView);

  TodoView = (function(_super) {

    __extends(TodoView, _super);

    function TodoView() {
      return TodoView.__super__.constructor.apply(this, arguments);
    }

    TodoView.prototype.tagName = 'li';

    TodoView.prototype.className = 'row';

    TodoView.prototype.templateId = '#row-template';

    TodoView.prototype.initialize = function() {
      return this.model.on('change:Completed', this.remove, this);
    };

    TodoView.prototype.events = {
      'change input[type=checkbox]': 'checkChanged'
    };

    TodoView.prototype.checkChanged = function() {
      var formValues;
      formValues = this.parseForm();
      return this.model.save(formValues);
    };

    return TodoView;

  })(BaseView);

  Controller = (function() {

    function Controller() {}

    Controller.prototype.inProgressId = '#inprogress';

    Controller.prototype.completeId = '#completed';

    Controller.prototype.index = function() {
      var coll, formView;
      coll = new TodoItems;
      coll.on('reset', this._renderItems, this);
      formView = new FormView;
      formView.on('TodoItem:Created', this._renderItem, this);
      return coll.fetch();
    };

    Controller.prototype._renderItem = function(item) {
      var inList, view;
      view = new TodoView({
        model: item
      });
      inList = item.get('Completed') ? this.completeId : this.inProgressId;
      $(inList).append(view.render().el);
      return item.once('sync', this._renderItem, this);
    };

    Controller.prototype._renderItems = function(coll) {
      var item, _i, _len, _ref, _results;
      _ref = coll.models;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        item = _ref[_i];
        _results.push(this._renderItem(item));
      }
      return _results;
    };

    return Controller;

  })();

  jQuery(function() {
    var c;
    c = new Controller;
    return c.index();
  });

  this.derp = (_ref = window.derp) != null ? _ref : {};

  this.derp.TodoItem = TodoItem;

  this.derp.TodoItems = TodoItems;

}).call(this);
