单击时,mvc按钮不执行任何操作

时间:2015-04-20 23:27:25

标签: c# asp.net asp.net-mvc linq entity-framework

所以我解决了上一个问题我问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);
} 

1 个答案:

答案 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"); // ??
}

旁注:可以接受SelectListIEnumerable<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