Ok, after some research I was unable to understand the “viewmodel thing”.
I didn’t find any article that explains me what are the steps to work with ViewModels compared to simply passing the Entity as a Model to the View.
When using the pure Entity it is pretty straight-forward:
If creating a new entry, just show the view. If is post, validate, do Add(x) and voilá! When editting, populate an object and send it to the View. When posting, validate, change the state and save. No secret here.
But I am unable to create and edit ViewModels. Can someone help me on this?
To be short, I have this POCOs :
public class Vessel
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int ShipownerId { get; set; }
public virtual Shipowner Shipowner { get; set; }
}
public class Shipowner
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Vessel> Vessels { get; set; }
}
And this View:
@model INTREPWEB.Models.VesselCreateViewModel
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Vessel</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Vessel.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Vessel.Name)
@Html.ValidationMessageFor(model => model.Vessel.Name)
</div>
<div class="editor-field">
@Html.DropDownListFor(model => model.Vessel.ShipownerId, Model.Shipowners, String.Empty)
@Html.ValidationMessageFor(model => model.Vessel.Name)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
I’ve created this ViewModel:
public class VesselCreateViewModel
{
public Vessel Vessel { get; set; }
public SelectList Shipowners { get; set; }
public VesselCreateViewModel()
{
using (INTREPDB db = new INTREPDB())
{
var list = db.Shipowners.ToList()
.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString()
});
Shipowners = new SelectList(list, "Value", "Text");
}
}
public VesselCreateViewModel(int id)
{
using (INTREPDB db = new INTREPDB())
{
Vessel = db.Vessels.Find(id);
var list = db.Shipowners.ToList()
.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString()
});
Shipowners = new SelectList(list, "Value", "Text");
}
}
}
As you can see, it auto populates a collection for the View to show a DropDown menu. I was able to create new Vessels by doing the same way I do with only Models. But can’t figure out what I’m doing wrong when editting this thing.
This is the wrong POST Edit method:
[HttpPost]
public ActionResult Edit(VesselCreateViewModel vm)
{
if (ModelState.IsValid)
{
db.Entry(vm.Vessel).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
What should I do to save this little monster?
as you can see you are only using the Model-part of your ViewModel in this code. This is IMHO typical so you pass the ViewModel to the View but only bind the Model in your Edit-Postback.
Then you can easily recreate the viewmodel based on the changed model if you have to.
BTW: IMO ViewModel is a bad name in this case. If I hear ViewModel I think of MVVM but this case the viewmodel is only some kind of static-typed View-Helper and should have no behavior.