我已经阅读了很多类似的帖子。我试图运用我所见过的无济于事的方式。为了你的怜悯和帮助,我把自己扔在键盘的脚下。
我有一个类似调查的网站,所以为了简单起见,我编写了一个示例项目来复制问题。我也可以上传。
我有一个带有地址的子对象的模型 - 没有问题 - 它会绑定。
该模型还有一个问题集。它永远不会在帖子上绑定,这就是问题所在。
让我们从模特开始:
调查本身:
public class Survey
{
[ScaffoldColumn(false)]
public int Id { get; set; }
public string Name { get; set; }
[DisplayName("Phone #")]
[StringLength(15)]
[DataType(DataType.PhoneNumber)]
public string ContactMethodPhone { get; set; }
[DisplayName("Email")]
[StringLength(120)]
[EmailAddress]
public string ContactMethodEmail { get; set; }
public virtual Address Address { get; set; }
public virtual List<Question> Questions { get; set; }
}
和地址:
public class Address
{
[ScaffoldColumn(false)]
public int AddressId { get; set; }
[DisplayName("Address line 1")]
[Required]
[StringLength(200)]
public string Street { get; set; }
[DisplayName("Address line 2")]
[StringLength(200)]
public string Street2 { get; set; }
[DisplayName(" ")]
[StringLength(50)]
public string ApartmentNum { get; set; }
[DisplayName("Type")]
[StringLength(50)]
public string Tenement { get; set; }
[DisplayName("City")]
[Required]
[StringLength(200)]
public string City { get; set; }
[DisplayName("Province/State")]
[StringLength(20)]
public string State { get; set; }
[Required]
[DisplayName("Postal/Zip Code")]
[StringLength(10)]
public string MailCode { get; set; }
[DisplayName("Country")]
[StringLength(30)]
public string Country { get; set; }
[NotMapped]
public List<SelectListItem> Cities { get; set; }
[NotMapped]
public List<SelectListItem> Provinces { get; set; }
[NotMapped]
public List<SelectListItem> Countries { get; set; }
[NotMapped]
public List<SelectListItem> MailCodes { get; set; }
[NotMapped]
public List<SelectListItem> Tenements { get; set; }
}
和问题:
public class Question
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[ScaffoldColumn(false)]
public int ImageID { get; set; } // Question Image
[DisplayName("Question: ")]
public string InformationIntakeGroupValue { get; set; } // Question: ie Did you graguate high school
public int ImageID_Topic { get; set; } // Topic Image
[DisplayName("Topic: ")]
public string InformationIntakeTopicValue { get; set; } // Topic: ie Education
[ScaffoldColumn(false)]
public string InformationIntakeTypeCode { get; set; } // Type of question (date, bool, text)
// below not filled by select;
// the key from the EntityAffilliateIntake record insert
public int PersonId { get; set; } // Person anwering question
// this is the user response area
[DisplayName("Answer: ")]
public string InformationIntakeValue { get; set; }
[DisplayName("Choice: ")]
public string InformationIntakeValueBool { get; set; }
[DisplayName("Date: ")]
public DateTime InformationIntakeValueDate { get; set; }
[ForeignKey("Survey")]
public int SurveyId { get; set; }
public virtual Survey Survey { get; set; }
}
(注意:我还试过没有外键的模型 - 但可能没有正确定义)
控制器:
// GET: /Inquiry/Create
public ActionResult Create()
{
var geoIpData = Strings._download_serialized_json_data<GeoData>(StringConstants.UrlForGeoService);
SurveyModel = new Survey
{
Id=1,
Address = new AddressController().GetAddressModel(geoIpData.country, geoIpData.regionName, geoIpData.city, ""),
Questions = new QuestionController().GetQuestions(1).ToList()
};
return View(SurveyModel);
}
// POST: /Inquiry/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]
public ActionResult Create([Bind(Include = "Id, Name, ContactMethodPhone, ContactMethodEmail, Address, Questions")] Survey survey)
{
if (ModelState.IsValid)
{
int i = 0;
}
if (survey.Address.Cities == null)
{
survey.Address.Cities = SurveyModel.Address.Cities;
survey.Address.Countries = SurveyModel.Address.Countries;
survey.Address.MailCodes = SurveyModel.Address.MailCodes;
survey.Address.Provinces = SurveyModel.Address.Provinces;
survey.Address.Tenements = SurveyModel.Address.Tenements;
}
if (survey.Questions == null)
{
survey.Questions = SurveyModel.Questions;
}
return View(survey);
}
观点:
@model BindCollection.Models.Survey
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
// I use <div class="container">, <fieldset> and <div class="row">
// instead of <div class="form-horizontal"> and <div class="form-group">
<div class="container">
<fieldset>
<legend></legend>
<h4>Survey</h4>
<hr />
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.Id)
<div class="row">
@Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2 col-md-2 col-lg-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
Your address information:<br />
<br />
</div>
</div>
@* no problem here with address *@
@{ var vddAddress = new ViewDataDictionary(ViewData) { TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = "Address" } };}
@Html.Partial("_AddressPartial", Model.Address, @vddAddress)
<hr />
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
How we can contact you? :<br />
<br />
</div>
</div>
<div class="row">
@Html.LabelFor(model => model.ContactMethodPhone, new { @class = "control-label col-sm-2 col-md-2 col-lg-2" })
<div class="col-sm-10 col-md-10 col-lg-10">
@Html.EditorFor(model => model.ContactMethodPhone)
@Html.ValidationMessageFor(model => model.ContactMethodPhone)
</div>
</div>
<div class="row">
@Html.LabelFor(model => model.ContactMethodEmail, new { @class = "control-label col-sm-2 col-md-2 col-lg-2" })
<div class="col-sm-10 col-md-10 col-lg-10">
@Html.EditorFor(model => model.ContactMethodEmail)
@Html.ValidationMessageFor(model => model.ContactMethodEmail)
</div>
</div>
<hr />
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
Some Questions<br />
<br />
</div>
</div>
@*Here is the evil one! Beware!*@
@{ var vddQuestions = new ViewDataDictionary(ViewData) { TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = "Questions" } };}
@Html.Partial("_QuestionsPartial", Model.Questions, @vddQuestions)
<hr />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</fieldset>
</div>
}
地址部分视图无关紧要,因为那里没有问题。
以下是问题的部分视图:
@model IEnumerable<BindCollection.Models.Question>
@using BindCollection
@using Kendo.Mvc.UI
@{
string CurrentTopic = string.Empty;
bool FirstTime = true;
}
@foreach (var item in Model)
{
if (CurrentTopic != item.InformationIntakeTopicValue)
{
CurrentTopic = item.InformationIntakeTopicValue;
if (!FirstTime)
{
FirstTime = false;
item.InformationIntakeTopicValue = string.Empty;
}
}
else
{
item.InformationIntakeTopicValue = string.Empty;
}
@Html.EditorFor(m=>item, "Question")
<br />
<br />
}
当然,我为一个问题做了一个EditorTemplate,你可以在上面看到几行......
@model BindCollection.Models.Question
@Html.HiddenFor(m=>m.Id)
@{if (!string.IsNullOrWhiteSpace(Model.InformationIntakeTopicValue))
{
<hr />
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
<br />
<br />
<h4>
@Html.DisplayFor(m => m.InformationIntakeTopicValue, new { @class = "control-label col-sm-10 col-md-10 col-lg-10" })
</h4>
<br />
</div>
</div>
}}
@*type of value to ask for is denoted by item.InformationIntakeTypeCode*@
<div class="row">
<div class="control-label col-sm-9 col-md-9 col-lg-9">
@Html.DisplayFor(m => m.InformationIntakeGroupValue, null)
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
@{
var outputBool = false;
var outputDate = false;
var outputText = false;
if(Model.InformationIntakeTypeCode.ToLower().Contains("date") )
{
outputDate = true;
}
else if (Model.InformationIntakeTypeCode.ToLower().Contains("bool"))
{
outputBool = true;
}
else if (Model.InformationIntakeTypeCode.ToLower().Contains("string"))
{
outputText = true;
}
}
@if(outputBool)
{
@(Html.Kendo().DropDownListFor(m => m.InformationIntakeValueBool)
.HtmlAttributes(new { style ="width: 100px;", id="InformationIntakeValueBool"+Model.Id.ToString() })
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new List<SelectListItem>() {
new SelectListItem() {
Text = "Please Select...",
Value = "0"
},
new SelectListItem() {
Text = "Yes",
Value = "true"
},
new SelectListItem() {
Text = "No",
Value = "false"
}
}).Value("0")
)
}
@if(outputDate)
{
@(Html.Kendo().DatePickerFor(m => m.InformationIntakeValueDate)
.HtmlAttributes(new { style = "width: 100px;", id="InformationIntakeValueDate"+Model.Id.ToString() })
)
}
@if (outputText)
{
@Html.Kendo().AutoCompleteFor(m => m.InformationIntakeValue).HtmlAttributes(new { style = "width: 80%;", id="InformationIntakeValue"+Model.Id.ToString()})
}
</div>
</div>
所以......当我发布POST时,会发生奇怪的事情。传递所有表单值,但问题看起来很奇怪:
Id 1
Name sally
Address.Street 123 Avenue Steet
Address.Street2 Building C
Address.Tenement Suite
Address.ApartmentNum 111
Address.City_input Sarnia
Address.City Sarnia
Address.State_input Ontario
Address.State Ontario
Address.Country_input Canada
Address.Country Canada
Address.MailCode_input N6B 2K0
Address.MailCode N6B 2K0
ContactMethodPhone 555-555-5555
ContactMethodEmail r@r.com
Questions.item.Id 1
Questions.item.InformationIntakeValueBool true
Questions.item.Id 2
Questions.item.InformationIntakeValueDate 2/4/2014
Questions.item.Id 3
Questions.item.InformationIntakeValue Speckled
Questions.item.Id 4
Questions.item.InformationIntakeValueBool true
Questions.item.Id 5
Questions.item.InformationIntakeValue Lightly Toasted
Questions.item.Id 7
Questions.item.InformationIntakeValueBool true
Questions.item.Id 8
Questions.item.InformationIntakeValue Nothing!
Questions.item.Id 6
Questions.item.InformationIntakeValueBool true
Questions.item.Id 9
Questions.item.InformationIntakeValueDate 6/29/2014
我认为,正如我在其他帖子中看到的那样,问题项应如下所示:
Questions[0].Id 1
Questions[0].InformationIntakeValueBool true
Questions[1].Id 2
Questions[1].InformationIntakeValueDate 2/4/2014
Questions[2].Id 3
Questions[2].InformationIntakeValue Speckled
所以我不确定为什么我看起来像这样。
在服务器端,请求仅显示每个变量:
Request.Form.Results View Expanding the Results View will enumerate the IEnumerable
[0] "__RequestVerificationToken" object {string}
[1] "Id" object {string}
[2] "Name" object {string}
[3] "Address.Street" object {string}
[4] "Address.Street2" object {string}
[5] "Address.Tenement" object {string}
[6] "Address.ApartmentNum" object {string}
[7] "Address.City_input" object {string}
[8] "Address.City" object {string}
[9] "Address.State_input" object {string}
[10] "Address.State" object {string}
[11] "Address.Country_input" object {string}
[12] "Address.Country" object {string}
[13] "Address.MailCode_input" object {string}
[14] "Address.MailCode" object {string}
[15] "ContactMethodPhone" object {string}
[16] "ContactMethodEmail" object {string}
[17] "Questions.item.Id" object {string}
[18] "Questions.item.InformationIntakeValueBool" object {string}
[19] "Questions.item.InformationIntakeValueDate" object {string}
[20] "Questions.item.InformationIntakeValue" object {string}
查看最近4项?其他记录怎么样?
我猜测我发送到问题部分视图的ViewDataDictionary有些奇怪。
任何帮助将不胜感激。这应该简单......
答案 0 :(得分:1)
部分视图或foreach语句都不包含正确绑定集合所需的信息。我总是使用EditorTemplates来做所有事情。特别是因为EditorTemplates会自动遍历集合。
但是,如果您已经绑定并决定使用循环,则使用for循环,然后索引模型。在你的情况下:
@for(int i = 0; i < Model.Count; i++)
{
if (CurrentTopic != Model[i].InformationIntakeTopicValue)
...
@Html.EditorFor(m => Model[i]) // don't have to specify the template name
// since it's the same name as the type
}
但是,我只是这样做:
在您看来,请执行以下操作:
@*Here is the evil one! Beware!*@
@Html.EditorFor(m => m.Questions)
然后像往常一样使用Question.cshtml,它将自动由EditorFor
迭代但是,在Question.cshtml的顶部(在模型声明之后)添加以下代码,这就是实现您正在尝试的所有必要条件。您根本不需要局部视图。
@{
if (ViewBag.CurrentTopic != Model.InformationIntakeTopicValue)
{
ViewBag.CurrentTopic = Model.InformationIntakeTopicValue;
}
else
{
Model.InformationIntakeTopicValue = string.Empty;
}
}