Skip to content

Instantly share code, notes, and snippets.

@jsonw23
Created April 15, 2011 04:24
Show Gist options
  • Save jsonw23/921135 to your computer and use it in GitHub Desktop.
Save jsonw23/921135 to your computer and use it in GitHub Desktop.
Example Contact Form to illustrate tricky model binding situations in ASP.NET MVC 3
using System.Collections.Generic;
namespace GeekJ.Examples.ContactForm.Models
{
public class Contact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
private IList<Phone> _phoneNumbers;
public IList<Phone> PhoneNumbers
{
get
{
if (_phoneNumbers == null)
_phoneNumbers = new List<Phone>();
return _phoneNumbers;
}
}
}
}
using System.Web.Mvc;
using GeekJ.Examples.ContactForm.Models;
namespace GeekJ.Examples.ContactForm.Controllers
{
public class ContactController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult New(Contact newContact)
{
if (Request.HttpMethod == "POST")
{
}
return View(new Contact());
}
}
}
@using GeekJ.Examples.ContactForm.Models
@model GeekJ.Examples.ContactForm.Models.Contact
@{
ViewBag.Title = "New Contact";
for (int i = 0; i < 5; i++)
{
Model.PhoneNumbers.Add(new Phone());
}
}
<h2>New</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Contact</legend>
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.PhoneNumbers)
</div>
<div class="editor-field">
@for (int i = 0; i < Model.PhoneNumbers.Count(); i++) {
@Html.DropDownListFor(model => model.PhoneNumbers[i].Type, new SelectList(new string[] {
"Home", "Work", "Mobile", "Fax"
}))
@Html.TextBoxFor(model => model.PhoneNumbers[i].Number)
<br />
}
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@using GeekJ.Examples.ContactForm.Models
@model GeekJ.Examples.ContactForm.Models.Contact
@{
ViewBag.Title = "New Contact";
}
<h2>New</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jQuery.tmpl.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.datalink.js")" type="text/javascript"></script>
<script type="text/javascript">
var contact = {
PhoneNumbers: [
{ Type: "", Number: "" }
]
}
$(function () {
$("#phoneNumberTemplate").tmpl(contact).appendTo("#phoneNumbersContainer")
link();
$("#phoneNumbersContainer input").live("change", function () {
var used = 0;
for (var i = 0; i < contact.PhoneNumbers.length; i++) {
if (contact.PhoneNumbers[i].Number != "") {
used++;
}
}
if (used == $("#phoneNumbersContainer :text").length) {
contact.PhoneNumbers.push({ Type: "", Number: "" });
$("#phoneNumbersContainer").empty();
$("#phoneNumberTemplate").tmpl(contact).appendTo("#phoneNumbersContainer")
link();
}
});
$("form").submit(function () {
for (var i = 0; i < contact.PhoneNumbers.length; i++) {
if (contact.PhoneNumbers[i].Number == "") {
$(".phoneNumber:eq(" + i + ")").remove();
}
}
});
});
function link() {
$("div.phoneNumber").each(function (i) {
$(this).link(contact.PhoneNumbers[i], {
Type: {
name: "_Type",
convert: function (value, source, target) {
$(":hidden[name$=Type]", $(source).parent()).val(value);
return value;
}
},
Number: {
name: "_Number",
convert: function (value, source, target) {
$(":hidden[name$=Number]", $(source).parent()).val(value);
return value;
}
}
});
});
}
</script>
<script id="phoneNumberTemplate" type="text/x-jquery-tmpl">
{{each PhoneNumbers}}
<div class="phoneNumber">
@Html.Hidden("PhoneNumbers[${$index}].Type", "${$value.Type}")
@Html.DropDownList("_Type", new SelectList(new string[] {
"Home", "Work", "Mobile", "Fax"
}), "${$value.Type}")
@Html.Hidden("PhoneNumbers[${$index}].Number", "${$value.Number}")
@Html.TextBox("_Number", "${$value.Number}")
</div>
{{/each}}
</script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Contact</legend>
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.PhoneNumbers)
</div>
<div class="editor-field">
<div id="phoneNumbersContainer"></div>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@using GeekJ.Examples.ContactForm.Models
@model GeekJ.Examples.ContactForm.Models.Contact
@{
ViewBag.Title = "New Contact";
for (int i = 0; i < 5; i++)
{
Model.PhoneNumbers.Add(new Phone());
}
}
<h2>New</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Contact</legend>
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
namespace GeekJ.Examples.ContactForm.Models
{
public class Phone
{
public string Type { get; set; }
public string Number { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment