I am using EF4 (Db First) and I have an entity with a number of non-nullable properties.
In an Edit form (Razor/MVC3), I want to allow the editing of only one of the properties, but not the others.
To get this to work, I am having to put @Html.HiddenFor(...)
statements for each of my other properties that can't be nullable, otherwise I get an error on SaveChanges().
Is there a simple way to just have the ID hidden on the view, the property that can be edited, and then update ONLY that property?
All you need to do in this case is to include the ID of the entity you are editing as a hidden field as well as a text field for the property that you actually wanna edit:
@using (Html.BeginForm())
{
@Html.HiddenFor(x => x.ID)
@Html.EditorFor(x => x.PropertyYouWannaEdit)
<button type="submit">Update</button>
}
and then in the corresponding controller action you could retrieve the entity that needs to be edited from your database, update the value of the property that needs editing and save back the changes.
[HttpPost]
public ActionResult Update(SomeEntity model)
{
SomeEntity entityToEdit = db.GetEntity(model.ID);
entityToEdit.PropertyYouWannaEdit = model.PropertyYouWannaEdit;
db.Update(entityToEdit);
return RedirectToAction("Success");
}
But personally I would use a view model and AutoMapper to handle this situation. So I would start by designing a view model representing the requirements of my view and including the properties that needs to be edited only:
public class MyEntityViewModel
{
public int ID { get; set; }
public string Property1ToBeEdited { get; set; }
public string Property2ToBeEdited { get; set; }
...
}
and then have the corresponding view:
@model MyEntityViewModel
@using (Html.BeginForm())
{
@Html.HiddenFor(x => x.ID)
@Html.EditorFor(x => x.Property1ToBeEdited)
@Html.EditorFor(x => x.Property2ToBeEdited)
...
<button type="submit">Update</button>
}
and finally the 2 controller actions (GET and POST):
public ActionResult Update(int id)
{
// Fetch the domain model that we want to be edited from db
SomeEntity domainModel = db.GetEntity(id);
// map the domain model to a view model
MyEntityViewModel viewModel = Mapper.Map<SomeEntity, MyEntityViewModel>(domainModel);
// pass the view model to the view
return View(viewModel);
}
[HttpPost]
public ActionResult Update(MyEntityViewModel model)
{
if (!ModelState.IsValid)
{
// validation failed => redisplay view so that the user can fix the errors
return View(model);
}
// fetch the domain entity that needs to be edited:
SomeEntity entityToEdit = db.GetEntity(model.ID);
// update only the properties that were part of the view model,
// leaving the others intact
Mapper.Map<MyEntityViewModel, SomeEntity>(model, entityToEdit);
// persist the domain model
db.Update(entityToEdit);
// we are done
return RedirectToAction("Success");
}