【发布时间】:2017-05-25 17:51:34
【问题描述】:
我有一个用户类,它有一个名称(唯一且必需)、密码(必需)和配置文件(必需)。 Profile 类有一个唯一且必需的名称。这两个类都有一个 Id 作为主键,同时首先使用代码生成数据库。
我想允许在我的页面中创建新用户,这里有一些代码可以做到这一点:
控制器
// GET: Users/Create
public ActionResult Create()
{
populateViewBagWithProfilesAsSelectListItem();
return View();
}
private void populateViewBagWithProfilesAsSelectListItem()
{
IEnumerable<SelectListItem> profiles = db.Profiles.ToList().
Select(x => new SelectListItem
{
Value = x.Id.ToString(),
Text = x.Name
});
ViewBag.Profiles = profiles;
}
// POST: Users/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Name,Password,Profile")] User user)
{
user.Profile = db.Profiles.Find(user.Profile.Id);
ModelState.Clear();
TryValidateModel(user);
lock (UsersLocker)
{
if (ModelState.IsValid)
{
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
}
populateViewBagWithProfilesAsSelectListItem();
return View(user);
}
创建视图
@model ProceduresRecord.Web.MVC.Models.User
@{
ViewBag.Title = "Crear";
}
<h2>@ViewBag.Title</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Usuario</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Profile, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.Profile.Id, (IEnumerable<SelectListItem>)ViewBag.Profiles, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Profile.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Crear" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Volver a la Lista", "Index")
</div>
这会导致这个页面:
如您所见,我从数据库填充配置文件,我向用户显示配置文件名称,一旦他选择一个并单击创建,该配置文件的 Id 将发送到控制器中的 POST 方法创建。然后我努力使用提供的 ID 从数据库中获取完整的配置文件,我将完整的配置文件分配给用户并重新验证 ModelState(以便它更改为 true ......这是错误的,因为配置文件没有名称到目前为止)。 这一切似乎都有效,但我想知道......
难道没有更好的方法吗?我的意思是,在填充 html 选择时,我已经从数据库中获取了配置文件,能够一次性将完整的配置文件发送到 POST 并避免此代码,这不是很棒吗:
user.Profile = db.Profiles.Find(user.Profile.Id);
ModelState.Clear();
TryValidateModel(user);
如果有什么办法,请告诉我!
P.D:我正在尝试自学 MVC 和 Code First,任何建议都将不胜感激。
【问题讨论】:
-
不要在视图中使用数据模型,尤其是在编辑时。为
Name、Password` 和SelectedProfile创建一个视图模型 - 请参阅 CodingYoshi 的回答(并且您问题中的最后 3 行代码都不需要)
标签: c# asp.net-mvc entity-framework