Created
November 27, 2012 18:29
-
-
Save McNull/4156068 to your computer and use it in GitHub Desktop.
Json Model Binding with Knockout and ASP.NET MVC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace System.Web.Mvc { | |
public class JsonModelBinder : IModelBinder { | |
private readonly static System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); | |
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { | |
var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName]; | |
if (string.IsNullOrEmpty(stringified)) | |
return null; | |
return serializer.Deserialize(stringified, bindingContext.ModelType); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Web.Mvc; | |
using System.Collections.Generic; | |
namespace Controllers { | |
public class CustomersController: Controller { | |
/// <summary> | |
/// Edit an aspect. | |
/// </summary> | |
/// <param name="id">The unique identity of the customer to edit.</param> | |
/// <returns></returns> | |
public ActionResult Edit(Guid? id) { | |
// if the given id is empty, then we will simply edit a new model | |
if (id == Guid.Empty || !id.HasValue) | |
return View(new ViewModels.CustomerViewModel{}); | |
return View(); // here we would have some kind of data lookup if a valid id was given | |
} | |
/// <summary> | |
/// Edit a Customer. | |
/// </summary> | |
/// <param name="model"> | |
/// The customer to edit, expressed as a view model. | |
/// </param> | |
/// <returns> | |
/// Returns the user to the customers home page if successful, otherwise displays form | |
/// errors and requests for them to be fixed. | |
/// </returns> | |
[HttpPost] | |
public ActionResult Edit(ViewModels.CustomerViewModel model) { | |
if (ModelState.IsValid) { | |
// success | |
} | |
return View(model); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel.DataAnnotations; | |
using Lightcast.Infrastructure; | |
namespace ViewModels { | |
public class CustomerViewModel { | |
/// <summary> | |
/// The customer id. | |
/// </summary> | |
[Required] | |
public Guid Id { get; set; } | |
/// <summary> | |
/// The customer name. | |
/// </summary> | |
[Required] | |
[DataType(DataType.Text)] | |
[RegularExpression(@"^(?!.*[ ]{2})(?!.*[']{2})(?!.*[-]{2})(?:[a-zA-Z0-9 \p{L}'-]{3,64}$)$", ErrorMessage = "Invalid name. Names must be between 3 and 64 characters in length, may contain any alphanumeric character and the symbols -', and whitespace only.")] | |
[Display(Name = "Name")] | |
public string Name { get; set; } | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@model ViewModels.CustomerViewModel | |
@{ Html.BeginForm(); } | |
@Html.LabelFor(model => model.Name) | |
@Html.TextBoxFor( model => model.Name, new { @data_bind = "value: Name" }) | |
@Html.ValidationMessageFor( model => model.Name ) | |
<br class="space" /> | |
<div class="clearfix right"> | |
<button type="submit">Submit</button> | |
</div> | |
@{ Html.EndForm(); } | |
<script type="text/javascript"> | |
// ----------------------------------------------------------------------- // | |
// **************************** MODEL BINDING **************************** // | |
// ----------------------------------------------------------------------- // | |
// attempt to bind any data we received from the server | |
var serverData = @(new MvcHtmlString(Model.ToJson())); | |
// pass any data we received into a new viewModel | |
var viewModel = new ViewModels.CustomerViewModel( ko.toJS(serverData) ); | |
// apply the knockout binding to the viewModel | |
ko.applyBindings(viewModel, $("form")[0]); | |
// attach the jquery unobtrusive validator | |
$.validator.unobtrusive.parse("form"); | |
// bind the submit handler to unobtrusive validation. | |
$("form").data("validator").settings.submitHandler = function() { | |
viewModel.Save( $("form" ) ); | |
}; | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using System.Collections.Generic; | |
using System.Linq.Expressions; | |
using System.Web.Mvc.Html; | |
namespace System.Web.Mvc { | |
public static class HtmlHelperExtensions { | |
/// <summary> | |
/// Serializes an object to Javascript Object Notation. | |
/// </summary> | |
/// <param name="item">The item to serialize.</param> | |
/// <returns> | |
/// The item serialized as Json. | |
/// </returns> | |
public static string ToJson ( this object item ) { | |
return new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(item); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protected void Application_Start() { | |
AreaRegistration.RegisterAllAreas(); | |
RegisterGlobalFilters(GlobalFilters.Filters); | |
RegisterRoutes(RouteTable.Routes); | |
ModelBinders.Binders.Add(typeof(ViewModels.CustomerViewModel), new JsonModelBinder()); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ViewModels = ViewModels || {}; | |
ViewModels.CustomerViewModel = function (model) { | |
return { | |
Id: ko.observable(model.Id), | |
/// <summary> | |
/// The entity identification expressed as a GUID. | |
/// </summary> | |
/// <returns type="System.Guid" /> | |
Name: ko.observable(model.Name), | |
/// <summary> | |
/// The name of the Customer. | |
/// </summary> | |
/// <returns type="System.String" /> | |
Save: function ($form) { | |
ko.utils.postJson($form.attr('action'), { model: ko.toJS(this) }); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment