So I've used EF Code First to successfully create my entities and query the database to display the items.
I now want to provide a way to edit the records.
I have a Post class which contains:
(TypeName = "varchar")]
[Required()]
public string Headline { get; set; }
public virtual PostType PostType { get; set; }
PostType is a class I wrote which has an ID and Name to categorise posts into News, Blog etc.
Now, in my Edit controller I get the post and pass this to the view in a view model. I also get a IEnumerable of the different post types.
In my view I use the below:
<div class="formFieldContainer">
@Html.LabelFor(model => model.Post.PostType)
@Html.DropDownListFor(model => model.Post.PostType, new SelectList(Model.PostTypes, "ID", "Name"))
@Html.ValidationMessageFor(model => model.Post.PostType)
</div>
<div class="formFieldContainer">
@Html.LabelFor(model => model.Post.Headline)
@Html.EditorFor(model => model.Post.Headline)
@Html.ValidationMessageFor(model => model.Post.Headline)
</div>
On my edit controller I have the below to handle the post:
[HttpPost, ValidateAn开发者_运维技巧tiForgeryToken, ValidateInput(false)]
public ActionResult Edit(int id, FormCollection collection) {
var model = new PostViewModel();
model.Post = _pr.GetPost(id); //gets the post from my post repository
model.PostTypes = _ptr.GetPostTypes();
try {
UpdateModel(model.Post, "Post");
_pr.Save();
return RedirectToRoute("Posts", new { pageNumber = 0 }); //for now go to the homepage
} catch (Exception e) {
ModelState.AddModelError("_FORM", e.Message);
return View(model);
}
}
Now without the post type list and just the headline this works. However with the post type it doesn't. I get "1 is invalid" (1 being the value of the select list) which makes sense as my Post model expects a PostType object, not int.
I thought about doing something like:
model.Post.PostType = model.PostTypes.Where(x => x.ID == Int32.Parse(collection.GetValues("Post.PostType")[0])).Select(p => p).FirstOrDefault();
But 1) it doesn't work so its obviosuly not the right way and 2) since "Post.PostType" still exists, the UpdateModel fails.
Any ideas on how to do this?
I assume your repositories _pr and _ptr are using different contexts? Entity framework must read and update from the same context. Since you are getting the post types from another context EF treats it as a new entity hence the extra row in your database.
You should share your context between repositories, session per request is a defacto best practice.
As for the update model function you can pass in a string array of properties to include in the update:
UpdateModel(model.Post, "Post", new string[] { "Headline" });
This will ignore the PostType value.
Try changing your action to take in a Post
object:
public ActionResult Edit(Post post) {
With MVC 3, EF 4, the post object should be populated from the form vars, including your PostType. Then call your update and save methods.
精彩评论