带有外键的 ViewModel 和创建操作
ViewModel with foreign key and Create action
我有一个页面显示 post 的详细信息,并且已识别的用户可以在 post 上添加评论。
我的问题:
PostID 和 UserID 在 Comment 模型中是 FK,不会从视图传递到控制器
CommnetMessage 为空!!
怎么了?
评论模型:
public class Comment : System.Object
{
public Comment()
{
this.CommnetDate = General.tzIran();
}
[Key]
public int CommentID { get; set; }
[Required]
public string CommnetMessage { get; set; }
[Required]
public DateTime CommnetDate { get; set; }
public string UserId { get; set; }
[Key, ForeignKey("UserId")]
public virtual ApplicationUser ApplicationUser { get; set; }
public int PostID { get; set; }
[Key, ForeignKey("PostID")]
public virtual Post posts { get; set; }
}
Post 型号:
public class Post : System.Object
{
public Post()
{
this.PostDate = General.tzIran();
this.PostViews = 0;
}
[Key]
public int PostID { get; set; }
public string PostName { get; set; }
public string PostSummery { get; set; }
public string PostDesc { get; set; }
public string PostPic { get; set; }
public DateTime PostDate { get; set; }
public int PostViews { get; set; }
public string postMetaKeys { get; set; }
public string PostMetaDesc { get; set; }
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser ApplicationUser { get; set; }
public int CategoryID { get; set; }
[ForeignKey("CategoryID")]
public virtual Category Category { get; set; }
public virtual ICollection<Comment> commnets {get; set;}
}
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
/*Realations*/
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
查看模型:
public class PostViewModel
{
public ApplicationUser Users { get; set; }
public Post posts { get; set; }
public Category Categories { get; set; }
public IEnumerable<Comment> ListCommnets { get; set; }
public Comment Commnets { get; set; }
}
控制器:
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var post = db.Posts.Find(id);
post.PostViews += 1;
db.SaveChanges();
if (post == null)
{
return HttpNotFound();
}
return View(new PostViewModel() { posts = post });
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details([Bind(Include = "CommentID,CommnetMessage,CommnetDate,UserId,PostID")] Comment comment , int? id)
{
int pid = comment.PostID;
if (ModelState.IsValid)
{
db.CommentS.Add(comment);
db.SaveChanges();
TempData["notice"] = "پیغام شما با موفقیت ثبت شد.";
return RedirectToAction("success");
}
ViewBag.UserId = new SelectList(db.Users, "Id", "FirstName", comment.UserId);
ViewBag.PostID = id;
return View( new PostViewModel() { posts = db.Posts.Find(id)});
}
public ActionResult success()
{
ViewBag.Message = "از طریق فرم زیر می توانید برایمان پیغام بگذارید.";
return View("Details", new PostViewModel() { ListCommnets = db.CommentS });
}
评论部分视图:
@using Microsoft.AspNet.Identity
@using FinalKaminet.Models
@using Microsoft.AspNet.Identity.EntityFramework
@model FinalKaminet.ViewModel.PostViewModel
@if (TempData["notice"] != null)
{
<p>@TempData["notice"]</p>
}
@if (Request.IsAuthenticated)
{
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var user = manager.FindById(User.Identity.GetUserId());
using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.posts.PostID)
@Html.HiddenFor(model => model.Users.Id)
<div class="form-group">
@Html.LabelFor(model => model.Users.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@{
var name = user.FirstName + " " + user.LastName;
}
<input type="text" id="Id" value="@name" disabled="disabled" class="form-control" />
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Commnets.CommnetMessage, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Commnets.CommnetMessage, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Commnets.CommnetMessage, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Send" class="btn btn-default" />
</div>
</div>
</div>
}
}
else
{
<p>@Html.ActionLink("Log in", "Login", "Account", new { returnUrl = Request.Url }, null)</p>
}
如@StephenMuecke 所述,您的视图模型是 PostViewModel
,并且所有 编辑器、隐藏字段 都是基于您的视图模型创建的。例如,当您使用 @Html.HiddenFor(model => model.posts.PostID)
生成隐藏字段并尝试 post 您的数据 MVC 模型绑定器尝试将此字段的值绑定到您的 Action 方法[=中指定的模型26=]。在你的情况下它是 Comment
所以,MVC 模型绑定器将尝试将生成的隐藏字段的值绑定到 Comment.posts.PostID
不存在。为了使一切完美运行,您必须使用相同的视图模型作为操作方法的参数:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details(PostViewModel viewModel)
{
......
}
另外,正如@StephenMuecke 所说,您的视图模型应该只包含您需要的那些属性。例如,您的 PostViewModel
应该如下所示:
public class PostViewModel
{
// Actually, you do not need UserId property
// as it should be retrieved inside controller
// from current user data
public string UserId { get; set; }
public string UserName { get; set; }
public int PostID { get; set; }
public string CommentMessage { get; set; }
}
回到您的操作方法,您必须将视图模型映射到您的模型:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details(PostViewModel viewModel)
{
Comment comment = new Comment
{
CommnetMessage = viewModel.CommentMessage,
// and other properties
}
// Save your model and etc.
}
我有一个页面显示 post 的详细信息,并且已识别的用户可以在 post 上添加评论。
我的问题:
PostID 和 UserID 在 Comment 模型中是 FK,不会从视图传递到控制器
CommnetMessage 为空!!
怎么了?
评论模型:
public class Comment : System.Object
{
public Comment()
{
this.CommnetDate = General.tzIran();
}
[Key]
public int CommentID { get; set; }
[Required]
public string CommnetMessage { get; set; }
[Required]
public DateTime CommnetDate { get; set; }
public string UserId { get; set; }
[Key, ForeignKey("UserId")]
public virtual ApplicationUser ApplicationUser { get; set; }
public int PostID { get; set; }
[Key, ForeignKey("PostID")]
public virtual Post posts { get; set; }
}
Post 型号:
public class Post : System.Object
{
public Post()
{
this.PostDate = General.tzIran();
this.PostViews = 0;
}
[Key]
public int PostID { get; set; }
public string PostName { get; set; }
public string PostSummery { get; set; }
public string PostDesc { get; set; }
public string PostPic { get; set; }
public DateTime PostDate { get; set; }
public int PostViews { get; set; }
public string postMetaKeys { get; set; }
public string PostMetaDesc { get; set; }
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser ApplicationUser { get; set; }
public int CategoryID { get; set; }
[ForeignKey("CategoryID")]
public virtual Category Category { get; set; }
public virtual ICollection<Comment> commnets {get; set;}
}
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
/*Realations*/
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
查看模型:
public class PostViewModel
{
public ApplicationUser Users { get; set; }
public Post posts { get; set; }
public Category Categories { get; set; }
public IEnumerable<Comment> ListCommnets { get; set; }
public Comment Commnets { get; set; }
}
控制器:
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var post = db.Posts.Find(id);
post.PostViews += 1;
db.SaveChanges();
if (post == null)
{
return HttpNotFound();
}
return View(new PostViewModel() { posts = post });
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details([Bind(Include = "CommentID,CommnetMessage,CommnetDate,UserId,PostID")] Comment comment , int? id)
{
int pid = comment.PostID;
if (ModelState.IsValid)
{
db.CommentS.Add(comment);
db.SaveChanges();
TempData["notice"] = "پیغام شما با موفقیت ثبت شد.";
return RedirectToAction("success");
}
ViewBag.UserId = new SelectList(db.Users, "Id", "FirstName", comment.UserId);
ViewBag.PostID = id;
return View( new PostViewModel() { posts = db.Posts.Find(id)});
}
public ActionResult success()
{
ViewBag.Message = "از طریق فرم زیر می توانید برایمان پیغام بگذارید.";
return View("Details", new PostViewModel() { ListCommnets = db.CommentS });
}
评论部分视图:
@using Microsoft.AspNet.Identity
@using FinalKaminet.Models
@using Microsoft.AspNet.Identity.EntityFramework
@model FinalKaminet.ViewModel.PostViewModel
@if (TempData["notice"] != null)
{
<p>@TempData["notice"]</p>
}
@if (Request.IsAuthenticated)
{
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var user = manager.FindById(User.Identity.GetUserId());
using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.posts.PostID)
@Html.HiddenFor(model => model.Users.Id)
<div class="form-group">
@Html.LabelFor(model => model.Users.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@{
var name = user.FirstName + " " + user.LastName;
}
<input type="text" id="Id" value="@name" disabled="disabled" class="form-control" />
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Commnets.CommnetMessage, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Commnets.CommnetMessage, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Commnets.CommnetMessage, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Send" class="btn btn-default" />
</div>
</div>
</div>
}
}
else
{
<p>@Html.ActionLink("Log in", "Login", "Account", new { returnUrl = Request.Url }, null)</p>
}
如@StephenMuecke 所述,您的视图模型是 PostViewModel
,并且所有 编辑器、隐藏字段 都是基于您的视图模型创建的。例如,当您使用 @Html.HiddenFor(model => model.posts.PostID)
生成隐藏字段并尝试 post 您的数据 MVC 模型绑定器尝试将此字段的值绑定到您的 Action 方法[=中指定的模型26=]。在你的情况下它是 Comment
所以,MVC 模型绑定器将尝试将生成的隐藏字段的值绑定到 Comment.posts.PostID
不存在。为了使一切完美运行,您必须使用相同的视图模型作为操作方法的参数:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details(PostViewModel viewModel)
{
......
}
另外,正如@StephenMuecke 所说,您的视图模型应该只包含您需要的那些属性。例如,您的 PostViewModel
应该如下所示:
public class PostViewModel
{
// Actually, you do not need UserId property
// as it should be retrieved inside controller
// from current user data
public string UserId { get; set; }
public string UserName { get; set; }
public int PostID { get; set; }
public string CommentMessage { get; set; }
}
回到您的操作方法,您必须将视图模型映射到您的模型:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details(PostViewModel viewModel)
{
Comment comment = new Comment
{
CommnetMessage = viewModel.CommentMessage,
// and other properties
}
// Save your model and etc.
}