Create a gist now

Instantly share code, notes, and snippets.

Embed
@model EditUserModel
@using (Html.BeginForm())
{
<div>
@Html.HiddenFor(m => m.Id)
@Html.TextBoxFor(m => m.FirstName)
@Html.TextBoxFor(m => m.LastName)
@Html.DropDownListFor(m => m.CountryId, Model.Countries)
<input type="submit" />
</div>
}
class EditUserModel
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CountryId { get; set; }
public ICollection<SelectListItem> Countries { get; set; }
}
class EditUserModelBuilder : IModelBuilder<EditUserModel, User>
{
readonly ISession session;
public EditUserModelBuilder(ISession session)
{
this.session = session;
}
public EditUserModel CreateFrom(User user)
{
var model = new EditUserModel();
model.Id = user.FirstName;
model.FirstName = user.FirstName;
model.LastName = user.LastName;
model.Country = user.Country.Id;
model.Countries = GetCountries();
return model;
}
public EditUserModel Rebuild(EditUserModel model)
{
model.Countries = GetCountries();
return model;
}
public User ApplyChanges(EditUserModel model)
{
var user = string.IsNullOrEmpty(model.Id) ? new User() : session.Find<User>(model.Id);
session.Store(user);
user.FirstName = model.FirstName;
user.LastName = model.LastName;
user.Country = session.Find<Country>(model.CountryId);
return user;
}
ICollection<SelectListItem> GetCountries()
{
var countries = session.FindAll<Country>();
return countries.Select(c => new SelectListItem { Value = c.Id, Text = c.Name }).ToList();
}
}
interface IModelBuilder<TViewModel, TEntity>
{
TViewModel CreateFrom(TEntity entity);
TViewModel Rebuild(TViewModel model);
TEntity ApplyChanges(TViewModel viewModel);
}
class UserController : Controller
{
IModelBuilder<EditUserModel, User> builder = new EditUserModelBuilder();
public ActionResult Edit(string id)
{
var user = session.Find<User>(id) ?? new User();
return View(model, builder.CreateFrom(user));
}
[HttpPost]
public ActionResult Edit(EditUserModel model)
{
if (!ModelState.IsValid)
{
return View(builder.Rebuild(model);
}
builder.ApplyChanges(model);
session.SaveChanges();
return RedirectToAction("Index");
}
}
@PaulStovell

This comment has been minimized.

Show comment
Hide comment
@PaulStovell

PaulStovell Apr 13, 2012

This approach is based on this StackOverflow answer: http://stackoverflow.com/a/2775656/57132

I like it because the controller is much simpler, and the save code is more easily reused. In the real world I'd inject the model builder so testing would be easier too. I like that the messiness of re-filling the countries list for example is hidden inside the builder.

Owner

PaulStovell commented Apr 13, 2012

This approach is based on this StackOverflow answer: http://stackoverflow.com/a/2775656/57132

I like it because the controller is much simpler, and the save code is more easily reused. In the real world I'd inject the model builder so testing would be easier too. I like that the messiness of re-filling the countries list for example is hidden inside the builder.

@plillevold

This comment has been minimized.

Show comment
Hide comment
@plillevold

plillevold Apr 13, 2012

Agree that this was a tidier approach. Just wanted to mention, there's a copy/paste bug in Edit.cshtml line 8.

Agree that this was a tidier approach. Just wanted to mention, there's a copy/paste bug in Edit.cshtml line 8.

@PaulStovell

This comment has been minimized.

Show comment
Hide comment
@PaulStovell

PaulStovell Apr 13, 2012

Thanks Peter, I've fixed the bug

Owner

PaulStovell commented Apr 13, 2012

Thanks Peter, I've fixed the bug

@nblumhardt

This comment has been minimized.

Show comment
Hide comment
@nblumhardt

nblumhardt Apr 14, 2012

Looks great :)

Looks great :)

@dougrchamberlain

This comment has been minimized.

Show comment
Hide comment
@dougrchamberlain

dougrchamberlain Oct 3, 2013

There is another mistake in your IModelBuilder.cs line 4. It should be TEditUserModel

There is another mistake in your IModelBuilder.cs line 4. It should be TEditUserModel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment