JD *_*vis 4 c# asp.net-mvc entity-framework viewmodel asp.net-mvc-5
我正在开发一个网络应用程序来工作,并且我正在使用标准 CRUD 风格的交互。但是,我不希望用户更新某些字段,因此我将它们从视图中删除了。但是,如果我没有显式设置这些字段,那么当模型在数据库中更新时它们会被清除。
我关心填充 ViewModel 字段的正确方法是什么。
我想出的粗略想法是这样的:
我的视图模型:
public class EditSoftwareTrackingViewModel
{
public EditSoftwareTrackingViewModel(SoftwareTracking model)
{
Id = model.Id;
SoftwareId = model.SoftwareId;
ComputerId = model.ComputerId;
SoftwareActionId = model.SoftwareActionId;
LastModified = model.LastModified;
Computer = model.Computer;
Software = model.Software;
SoftwareAction = model.SoftwareAction;
}
public int Id { get; set; }
[DisplayName("Software")]
public int SoftwareId { get; set; }
[DisplayName("Computer")]
public int ComputerId { get; set; }
[DisplayName("Software Action")]
public int SoftwareActionId { get; set; }
[DisplayName("Last Modified")]
public DateTime? LastModified { get; set; }
public virtual Computer Computer { get; set; }
public virtual Software Software { get; set; }
public virtual SoftwareAction SoftwareAction { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的主要模型
[Table("asset.SoftwareTracking")]
public partial class SoftwareTracking
{
public int Id { get; set; }
[DisplayName("Software")]
public int SoftwareId { get; set; }
[DisplayName("Computer")]
public int ComputerId { get; set; }
[DisplayName("Date Entered")]
public DateTime? EnteredDate { get; set; }
[DisplayName("Software Action")]
public int SoftwareActionId { get; set; }
[DisplayName("Last Modified")]
public DateTime? LastModified { get; set; }
public virtual Computer Computer { get; set; }
public virtual Software Software { get; set; }
public virtual SoftwareAction SoftwareAction { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的控制器使用视图模型
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
EditSoftwareTrackingViewModel softwaretracking = new EditSoftwareTrackingViewModel(db.SoftwareTrackings.Find(id));
if (softwaretracking == null)
{
return HttpNotFound();
}
GeneratePageData(softwaretracking.Software.Id);
return View(softwaretracking);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(EditSoftwareTrackingViewModel softwaretracking)
{
if (ModelState.IsValid)
{
softwaretracking.LastModified = DateTime.Now;
var softwareTrack = db.SoftwareTrackings.Find(softwaretracking.Id);
softwareTrack = new SoftwareTracking
{
Computer = softwaretracking.Computer,
ComputerId = softwaretracking.ComputerId,
LastModified = softwaretracking.LastModified,
Software = softwaretracking.Software,
SoftwareAction = softwaretracking.SoftwareAction,
SoftwareActionId = softwaretracking.SoftwareActionId,
SoftwareId = softwaretracking.SoftwareId,
EnteredDate = softwareTrack.EnteredDate
};
db.Entry(softwareTrack).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
GeneratePageData(softwaretracking.Software.Id);
return View(softwaretracking);
}
Run Code Online (Sandbox Code Playgroud)
有更好的选择吗?或者我应该继续以这种方式创建我的视图模型?
编辑
我的业务逻辑和观点
private void GeneratePageData(int? id = null)
{
ViewBag.Computers = new SelectList(db.Computers, "Id", "ComputerName");
ViewBag.SoftwareActions = new SelectList(db.SoftwareActions, "Id", "ActionPerformed");
var usedSoft = (from softTrack in db.SoftwareTrackings
where (softTrack.SoftwareActionId != 3)
select softTrack.Software);
var softwareList = (from soft in db.Softwares
where (
((from softTrack in db.SoftwareTrackings
where (softTrack.SoftwareActionId != 3 && softTrack.SoftwareId == soft.Id)
select softTrack.Software).Count() < soft.KeyQuantity)
&& !(soft.AssetStatusId == 4 || soft.AssetStatusId == 5)
|| soft.Id == id)
select soft).ToList();
ViewBag.SoftwareList = softwareList.Select(t => new SelectListItem
{
Text = t.SoftwareIdNameFull,
Value = t.Id.ToString()
});
}
Run Code Online (Sandbox Code Playgroud)
还有我的看法
@model Lighthouse_Asset_Manager.Models.EditSoftwareTrackingViewModel
@{
ViewBag.Title = "Edit Software Install";
Layout = "";
}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
×
</button>
<h4 class="modal-title" id="myModalLabel">Edit Software Install</h4>
</div>
<div class="modal-body">
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "computerForm" }))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.Id)
<div class="form-horizontal">
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.SoftwareId, "Software", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("SoftwareId", (IEnumerable<SelectListItem>)ViewBag.SoftwareList, "-- Select --", new
{
@style = "width:100%",
@class = "select2"
})
@Html.ValidationMessageFor(model => model.SoftwareId)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ComputerId, "Computer", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("ComputerId", (IEnumerable<SelectListItem>)ViewBag.Computers, "-- Select --", new
{
@style = "width:100%",
@class = "select2"
})
@Html.ValidationMessageFor(model => model.ComputerId)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.SoftwareActionId, "Action", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("SoftwareActionId", (IEnumerable<SelectListItem>)ViewBag.SoftwareActions, "-- Select --", new
{
@style = "width:100%",
@class = "form-control"
})
@Html.ValidationMessageFor(model => model.SoftwareActionId)
</div>
</div>
<div class="form-actions no-color">
<button type="submit" class="btn btn-primary btn-sm"><i class="fa fa-floppy-o"></i> Edit Install Record</button>
<button type="button" class="btn btn-default" data-dismiss="modal">
Cancel
</button>
</div>
</div>
}
</div>
Run Code Online (Sandbox Code Playgroud)
小智 5
使用视图模型的方法是一种很好的方法。这个问题的答案解释了一些好处,包括防止过度发布攻击、使用视图特定的显示和验证属性以及包括视图特定的属性,例如SelectLists. automapper等工具可以轻松地在数据和视图模型之间进行映射,并减少控制器中的代码。我建议您对视图模型进行一些更改。、和属性不是必需的(您不需要绑定到这些属性),我会将这些属性包含LastModified在模型中而不是 ViewBag中ComputerSoftwareSoftwareActionSelectList
查看型号
public class EditSoftwareTrackingViewModel
{
public int Id { get; set; }
[Display(Name="Software")]
public int SoftwareId { get; set; }
[Display(Name="Computer")]
public int ComputerId { get; set; }
[Display(Name="Software Action")]
public int SoftwareActionId { get; set; }
public SelectList Computers { get; set; }
public SelectList SoftwareActions{ get; set; }
public SelectList SoftwareList{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后更改GeneratePageData()方法来接受视图模型
private void GeneratePageData(EditSoftwareTrackingViewModel model)
{
model.Computers = new SelectList(db.Computers, "Id", "ComputerName");
....
Run Code Online (Sandbox Code Playgroud)
并在视图中(总是最好使用强类型助手)
@Html.DropDownListFor(m => m.SoftwareId, Model.SoftwareList, "-- Select --", new { @class = "select2" })
Run Code Online (Sandbox Code Playgroud)
还有其他一些需要注意的事情。
[Display(Name="..")]属性(而不是
[DisplayName(..)])LastModified属性时,应考虑使用
UCT时间。Id视图中不需要属性的隐藏输入(假设您使用默认{controller}/{action}/{id}路由映射) - 它会添加到路由值中并且无论如何都会被绑定id表单的属性,否则您可以使用@using(Html.BeginForm()) {LabelFor()- 它可能只是
Html.LabelFor(m => m.SoftwareId, new { @class = "control-label
col-md-2" })因为您已在[Display]
属性中指定了它最后,如果您想进一步简化视图,您可以考虑使用自定义或 html 帮助程序,如此答案EditorTemplates中所示,这将允许您替换
<div class="form-group">
@Html.LabelFor(model => model.SoftwareId, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(m => m.SoftwareId, Model.SoftwareList, "-- Select --", new { @class = "select2" })
@Html.ValidationMessageFor(model => model.SoftwareId)
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
与(自定义EditorTemplate)
@Html.EditorFor(m => m.SoftwareId, "BootstrapSelect", Model.SoftwareList)
Run Code Online (Sandbox Code Playgroud)
或(自定义HtmlHelper)
@Html.BootstrapDropDownFor(m => m.SoftwareId, Model.SoftwareList)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2713 次 |
| 最近记录: |