所以我解决了上一个问题我问here的问题,现在我得到了我想要的东西,但是当我点击保存它什么也没做?没有错误或回发,没有保存到数据库?该按钮在我的视图中没有做任何事情?
我在EF模型中与Post和Tag有很多关系。我正在尝试将帖子分配给标签。我正在关注这个tutorial。但是,单击“保存”时按钮不起作用。
PostController中:
public ActionResult EditPostTag(int id = 12) // hardcoded the post for now
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var postsViewModel = new PostsViewModel
{
posts = db.Posts.Include(i => i.Tags).First(i => i.Id == id),
};
if (postsViewModel.posts == null)
return HttpNotFound();
var tagsList = db.Tags.ToList();
postsViewModel.Tags = tagsList.Select(o => new SelectListItem
{
Text = o.Name,
Value = o.Id.ToString()
});
ViewBag.UserID =
new SelectList(db.BlogUsers, "UserID", "Email", postsViewModel.posts.Id);
return View(postsViewModel);
}
答案 0 :(得分:4)
您的观点没有form
代码
@model MyBlogger.ViewModel.PostsViewModel
@{
ViewBag.Title = "EditPostTag";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>EditPostTag</h2>
@using (Html.BeginForm()) // add this
{
....
}
编辑(进一步评论和OP的一些误解)
使用视图模型总是很好的做法,但是你没有利用它,继续使用ViewBag
并使用它来保存数据模型而不是只包含你需要的属性视图。我推荐它是
public class PostViewModel // its for a single post - not plural?
{
public int ID { get; set; }
[Required(ErrorMessage = "Please enter a title")]
public string Title { get; set; }
[Display(Name = "Tags")] // plus [Required] is at least one tag must be selected
public List<int> SelectedTags { get; set; }
public SelectList TagsList { get; set; }
// Its unclear if you really need the following 2 properties (see notes)
[Display(Name = "User")]
[Required(ErrorMessage = "Please select a user")]
public int UserID { get; set; }
public SelectList UserList { get; set; }
}
附注:有点不清楚为什么允许用户选择与Post
对象关联的其他用户。我怀疑当你保存Post
时,你应该只是在控制器POST方法中分配当前用户
您的控制器方法将是(假设这是PostController
)
public ActionResult Edit(int id)
{
Post post = db.Posts.Include(i => i.Tags).FirstOrDefault(i => i.Id == id); // First() will throw an exception is the item is not found
if (post == null) { return HttpNotFound(); }
PostViewModel model = new PostViewModel()
{
ID = post.ID,
Title = post.Title,
SelectedTags = post.Tags.Select(t => t.Id)
}; // include UserId property?
ConfigureEditModel(model);
return View(model);
}
[HttpPost]
public ActionResult Edit(PostViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureEditModel(model);
return View(model);
}
// map your view model to a data model, save it and redirect
}
private void ConfigureEditModel(PostViewModel model)
{
model.TagsList = new SelectList(db.Tags, "Id", "Name");
model.UserList = new BlogUsers(db.Tags, "UserID", "Email"); // ??
}
旁注:可以接受SelectList
或IEnumerable<SelectListItem>
(我发现SelectList
更容易阅读但是它慢了一两毫秒,因为它使用反射来生成IEnumerable<SelectListItem>
)但是没有像使用new SelectList(db.BlogUsers, "UserID", "Email", postsViewModel.posts.Id);
那样使用第4个参数 - 您对属性的绑定和所选项目将是属性的值,因此尝试设置Selected
属性只是忽略)
最后是视图(简化为仅显示没有html属性的助手)
@model MyBlogger.ViewModel.PostViewModel
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
// @Html.HiddenFor(model => model.posts.Id) not required
@Html.LabelFor(m => m.Title)
@Html.TextBoxFor(m => m.Title)
@Html.ValidationMessageFor(m => m.Title)
// Is the UserId property required?
@Html.LabelFor(m => m.UserID)
@Html.DropDownListFor(m => m.UserID, Model.UserList, "Please select")
@Html.ValidationMessageFor(m => m.UserID)
@Html.LabelFor(model => model.SelectedTags)
@Html.ListBoxFor(m => m.SelectedTags, Model.TagsList)
// Add ValidationMessageFor() if at least one should be selected
<input type="submit" value="Save" class="btn btn-default" />
}
旁注:由于方法的参数名为id
,因此id
属性的值将添加到路径参数中,因此不必为视图添加隐藏的输入模型ID
属性(DefaultModelBinder
除了表单值之外还读取路由值,因此视图模型ID
属性将被正确绑定(在您的情况下为12
)