【问题标题】:mvc button does not do anything when clicked单击时 mvc 按钮不执行任何操作
【发布时间】:2015-04-20 23:27:25
【问题描述】:

所以我解决了我之前问过here 的问题,现在我得到了我想要的东西,但是当我点击保存时它什么也没做?没有错误或回发,也没有保存到数据库中?在我看来,该按钮没有任何作用?

我在我的 EF 模型中与 Post 和 Tag 有多对多的关系。我正在尝试将帖子分配给标签。我正在关注这个tutorial。但是,当我单击保存时,该按钮什么也不做。

后控制器:

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);
} 

【问题讨论】:

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


【解决方案1】:

您的视图没有form 标签

@model MyBlogger.ViewModel.PostsViewModel
@{
    ViewBag.Title = "EditPostTag";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>EditPostTag</h2>
@using (Html.BeginForm()) // add this
{
    ....
}

编辑(进一步说明 cmets 和 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&lt;SelectListItem&gt; 都可以接受(我发现 SelectList 更容易阅读,但它会慢一到两毫秒,因为它使用反射来生成 IEnumerable&lt;SelectListItem&gt;),但使用第 4 个参数,就像您对 new SelectList(db.BlogUsers, "UserID", "Email", postsViewModel.posts.Id); 所做的那样 - 您与属性的绑定和所选项目将是该属性的值,因此尝试设置 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" />
}

旁注:由于您的方法的参数名为idid 属性的值将添加到路由参数中,因此无需为视图模型添加隐藏输入ID属性(DefaultModelBinder 读取除了表单值之外的路由值,因此视图模型ID 属性将被正确绑定(在您的情况下为12

【讨论】:

  • 感谢斯蒂芬,所有的工作,它仍然没有工作。数据库没有在 PostTagMap 中显示 id ......
  • 您需要在问题中包含 [HttpPost] 方法 - 您所显示的只是 GET 方法。它需要像[HttpPost] public ActionResult EditPostTag(PostsViewModel model)这样的签名
  • 您当前的签名public ActionResult EditPostTag(int id = 12) 没有收到带有用户输入值的视图模型
  • 恕我直言,这不是一个好的教程并且有一些实践,但它实际上在教程中 - 在“结论”标题之前的底部
  • 这是因为在返回视图之前,您没有重新分配 SelectListsTags 属性的值(就像您在 GET 方法中所做的那样)。给我一个小时左右,我会用我推荐的代码更新我的答案
猜你喜欢
  • 1970-01-01
  • 2021-09-15
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-02
  • 2016-03-14
相关资源
最近更新 更多