MVC.NET的新手(和C#一般......并且正在开发)并尝试围绕ViewModels。我有一个非常基本的要求。我有Actor
,UseCase
和Project
个实体。要创建新的UseCase
,我想要一个DropDownListFor
Actors
与Project
位于同一UseCase
的视图。项目id
位于URL中。我一直关注此How to bind a selectlist with viewmodel?,但我遇到了错误:
DataBinding: 'System.Web.Mvc.SelectListItem' does not contain a property with the name 'ActorId'.
此外,我并不确切知道如何使用POST
方法进行映射 - 我很高兴现在手动执行此操作而不使用AutoMapper
。
视图模型:
public class UserGoalsStepViewModel
{
public enum GoalLevel
{
Summary, UserGoal, SubGoal,
}
public int ProjectId { get; set; }
public int ActorId { get; set; }
public SelectList ActorList { get; set; }
public string Title { get; set; }
public GoalLevel Level { get; set; }
public UserGoalsStepViewModel ()
{
}
}
更新:控制器: 已更新,以反映以下评论中讨论的更改。
发生了什么:
1.在GET中创建视图时正确填充模型(ProjectId,Level和ActorList的值是正确的,actorId是' 0'并且Title是null。全部按预期方式。
2.在POST上,标题设置为" 5" (实际上是所选actor
的Id,ActorId = 0仍然,Level得到正确的值而ProjectId失去了它的值。所以,显然我需要对SelectList定义做一些事情,但是我是不确定为什么ProjectId迷路了?
// GET: UseCases/Create
public ActionResult Create(int id)
{
ViewBag.projectId = id;
//Populate the ViewModel
UserGoalsStepViewModel model = new UserGoalsStepViewModel()
{
ProjectId = id,
ActorList = new SelectList(db.Actors.Where(a => a.projectID == id), "id", "Title"),
};
return View(model);
}
// POST: UseCases/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 = "ProjectId,ActorId,Title,Level")] UserGoalsStepViewModel model, int id)
{
ViewData["Actors"] = new SelectList(db.Actors.Where(a => a.projectID == id), "id", "Title");
if (ModelState.IsValid)
{
//Create a use case object to map to, which can then be saved in the DB
UseCase uc = new UseCase();
uc.ProjectID = model.ProjectId;
uc.ActorID = model.ActorId;
uc.Level = (Level)model.Level;
db.SaveChanges();
return RedirectToAction("Index", new { id = model.ProjectId });
}
return View(model);
}
查看:
@Html.DropDownListFor(model => model.Title, new SelectList(Model.ActorList, "ActorId", "Title"), new { @class = "form-control" })
答案 0 :(得分:2)
尝试:
@Html.DropDownListFor(model => model.Title, Model.ActorList, new { @class = "form-control" })
而不是:
@Html.DropDownListFor(model => model.Title, new SelectList(Model.ActorList, "ActorId", "Title"), new { @class = "form-control" }
问题是您尝试在DropDownListFor中创建Selectlist
,但Model.ActorList
已经 一个SelectList
。
代码中可能存在其他问题,但这应该会让您超越该特定错误。
<强>更新强>
您POST的Controller方法应如下所示:
public ActionResult Create(UserGoalsStepViewModel model)
{
// what are we updating? assume it's a project
var p = from db.Projects.Where(x => x.Id == model.id;
p.SomeProperty = model.SomeProperty;
db.SaveChanges();
}
NB-为了简洁起见,我删除了一些额外的检查 - 显然你想要添加绑定限制,模型状态检查,空检查等。
更新2
当您发布数据时Title=5
,因为标题控件是您的选择列表,而5是所选值。
ActorId = 0
因为您可能没有包含此值的表单控件,ProjectId也是如此?如果没有看到View代码,就无法确定。
答案 1 :(得分:0)
这是我在帖子上做的... ....向VM添加Post方法。
public class UserGoalsStepViewModel{
// in the ctor initiailze properites...
public string SelectedValue {get;set;}
public IEnumerable<SelectListItem> DDL {get;set;}
public void Post(){
DoSomethingWith(SelectedValue)
}
这需要在View ...
中使用强类型绑定进行正确绑定@model UserGoalStepViewModel
@Html.DropDownListFor(x=>model.SelectedValue, model.DDL)
控制器(帖子的动作方法)
[HttpPost]
public ActionResult(UserGoalsStepViewMdoel vm){
if(ModelState.IsValid){
vm.Post();
ModelState.Clear(); // if you want to show changed properties in view.
}
return View(vm);
}
最后一件事,确保你想要发回控制器的所有内容都在BeginForm内...... MVC有这样的习惯,就是你只需要给你发回你强烈的控制器动作方法的内容,如果你没有&#39 ; t得到BeginForm内部的所有内容,它将看起来像#34;丢失数据&#34; ......