好的,这让我疯了。有时候我发现MVC让我在树林里迷失方向,开始向错误的道路前进,一切都变得地狱。所以我伸出手来看看是否有一双新眼睛指向正确的方向。
基本上,该结构允许管理员创建自己的问题,这本身就很简单,但在这种情况下,它不仅仅是一个“单一”答案框。例如:
您的营业地点的名称和地址是什么?
名称: _ __ _ __ _ 地址: _ __ _ 城市: _ __ 状态:__ Zip: _
因此,如果客户只有一个位置,它将是一个带有5个文本框(名称,地址,城市,州,邮政编码)的答案......但由于问题是动态创建的,因此它可以是3个文本框,1, 2,等等。
所以我遇到的问题是当模型被发布回控制器时,视图模型的问题部分很好,但答案/选择部分总是返回null。请看看是否有巨型开/关开关我显然忽略了包括。
这是模型和视图模型:
public class Questions
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public int FormID { get; set; }
[Display(Name = "Question Order")]
[Range(0, Int32.MaxValue, ErrorMessage = "Must Use an Integer")]
public int QuestionOrder { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string Question { get; set; }
[Display(Name = "Help Text")]
public string HelpText { get; set; }
public bool IsActive { get; set; }
[Display(Name = "Question May Have More Than One Entry")]
public bool CanHaveMoreThanOne { get; set; }
public int QuestionTypeID { get; set; }
}
public class Choices
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public int QuestionID { get; set; }
public string FieldName { get; set; }
public string QuestionLabel { get; set; }
public bool IsRequired { get; set; }
public string RegEx { get; set; }
public string TextIfSelected { get; set; }
public string QuestionToSkipToIfSelected { get; set; }
public bool IsActive { get; set; }
[NotMapped]
public string AnswerText { get; set; }
[NotMapped]
public bool AnswerBool { get; set; }
[NotMapped]
public int AnswerNumeric { get; set; }
[NotMapped]
public DateTime AnswerDate { get; set; }
}
public class ViewQuestion
{
public Questions Question { get; set; }
public IEnumerable<Choices> Answers { get; set; }
}
以下是观点:
@using InterviewMaster.Models
@model ViewQuestion
@using (Html.BeginForm("AnswerQuestion","Interview", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.HiddenFor(m => m.Question.CanHaveMoreThanOne)
@Html.HiddenFor(m => m.Question.FormID)
@Html.HiddenFor(m => m.Question.HelpText)
@Html.HiddenFor(m => m.Question.ID)
@Html.HiddenFor(m => m.Question.Question)
@Html.HiddenFor(m => m.Question.QuestionOrder)
@Html.HiddenFor(m => m.Question.QuestionTypeID)
<h3>@Model.Question.Question</h3>
<hr />
@if (Model.Question.QuestionTypeID == 1)
{
foreach(var o in Model.Answers)
{
Html.RenderPartial("Partial1", o);
}
}
else if (Model.Question.QuestionTypeID == 2)
{
//TO-DO: Make other types of answers such as radio buttons, checkboxes, etc.
}
<input type="submit" value="Create" class="btn btn-default" />
</div>
}
这是我正在使用的部分
@model InterviewMaster.Models.Choices
@using(Html.BeginCollectionItem("Choices"))
{
@Html.HiddenFor(model => model.ID)
@Html.HiddenFor(model => model.QuestionID)
@Html.HiddenFor(model => model.FieldName)
@Html.HiddenFor(model => model.QuestionLabel)
@Html.HiddenFor(model => model.IsRequired)
@Html.HiddenFor(model => model.RegEx)
@Html.HiddenFor(model => model.TextIfSelected)
@Html.HiddenFor(model => model.QuestionToSkipToIfSelected)
@Html.HiddenFor(model => model.IsActive)
@Html.HiddenFor(model => model.AnswerBool)
@Html.HiddenFor(model => model.AnswerDate)
@Html.HiddenFor(model => model.AnswerNumeric)
<div class="form-group">
<label>@Html.ValueFor(model => model.QuestionLabel)</label>
@Html.TextBoxFor(model => model.AnswerText)
</div>
}
最后但并非最不重要的是,接收此帖子的控制器:
// POST: /Interview/AnswerQuestion
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AnswerQuestion(ViewQuestion dto)
{
foreach(var answer in dto.Answers)
{
Console.Write("Answer:" + answer.AnswerText);
}
return RedirectToAction("ContinueInterview", new { OrderID = 1, OrderDetailID = 1, FormID = 1, QuestionID = 1 });
}
答案 0 :(得分:4)
对于那些有一天可能需要这个的人来说,这就是问题所在。
此...
@using(Html.BeginCollectionItem("Choices"))
应该是这个......
@using(Html.BeginCollectionItem("dto.Answers"))
在Steven Sandersons网站(http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/)的例子中,它并没有真正进入一个复杂的例子,比如我的(不是他的错...我的)
我认为这就是你编辑/观看的模型。相反,它是你发送回控制器的东西。我很高兴。
希望这可以帮助将来的某个人。这花了我大约8个小时让自己疯狂...... arrrrgggghhh!