I'm having a problem with posting a view that has multiple partial views within it using one submit button
This is my A model,
:UPDATED:
public class AModel
{
public int AID { get; set; }
public int BID { get; set; }
public int CID { get; set; }
public int ANumber { get; set; }
public BModel BModel { get; set; }
public CModel CModel { get; set; }
}
this is my B model
public class BModel
{
public int BID { get; set; }
public int BName { get; set; }
public IList<DModel> DModel { get; set; }
}
this is the D model
public class DModel
{
public int DID { get; set; }
public int? Number { get; set; }
}
this is the c Model
public class CModel
{
public int CID { get; private set; }
public IList<HModel> HModels { get; set; }
}
and so on this is the main view
@model Project.Web.Models.AModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.Partial("CreateB",Model.BModel);
@Html.Partial("CreateC",Model.CModel);
<input style="border-radius:4px;width:100px;" type="button" value="next" id="next" class="btn btn-default" />
}
this is the Get action
public ActionResult Create(){
Models.AModel model = new Models.AModel(){
BModel = new BModel(){
DModel = new List<Models.DModel>(){ new Models.DModel() },
CModel = new CModel(){
HModel = new List<HModel>(){ new Models.HModel() },
};
return View(model);
}
this is the Post action
[HttpPost]
public ActionResult Create(Models.AModel model)
{
//doing things with data
//when I reach this point all object are null
return RedirectToAction("index", model);
}
public void SetNumber(Models.BModel model){
model.DModel.Add(new Models.DModel());
}
Partial View For BModel, and CModel is similar to BModel Partial view Note: the SetNumber method only create a new Object and add it to the list
@model Project.Web.Models.BModel
@Html.TextBoxItemFor(x => x.BName)
@for ( int i=0; i< Model.DModel.Count; i++){
@Html.TextBoxItemFor( x => x.DModel[i].Number)
<a id="addNumber" href="/AController/SetNumber/" data-ajax="true" data-
ajax-method="GET" >Add Another Number</a>
}
What can I do? What Am I missing?
Would be nice to see your partials as well. You should remember to put those partials names (as properties from main model) to "name" attribute of input as well. So for your case your PartialView should contain inputs like these: <input name="AModel.BModel.BID" ... />
UPDATE:
Try to replace your
@Html.Partial("Name", Model.PartialModel)
to
@{ Html.RenderPartial("Name", Model.PartialModel, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = prefix } }); }
where prefix
is Model property name (holding that partial model, ex "BModel"). So your view for AModel would look like this:
@model Project.Web.Models.AModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@{ Html.RenderPartial("CreateB",Model.BModel, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "BModel" } }) }
@{ Html.RenderPartial("CreateC",Model.CModel, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "CModel" } })
<input style="border-radius:4px;width:100px;" type="button" value="next" id="next" class="btn btn-default" />
}
UPDATE 2:
In order to work with arrays (which you have in your BModel) you will need to modify this prefix a bit, so view for your BModel would contain:
@{
for (var i = 0; i < Model.DModel.Count(); i++)
{
Html.RenderPartial("Name", Model.DModel[i], new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "DModel["+i+"]" } });
}
}
UPDATE 3:
Here's a complete example for your case (or pretty similar to your) without JavaScript. Controller:
public ActionResult Test()
{
return View("Test1", new AModel());
}
[HttpPost]
public ActionResult Save(AModel model)
{
if (model.PostType == "Add")
{
model.BModel.DModels.Add(new DModel());
return View("Test1", model);
}
// Do something with this final model
return View("Test1");
}
Models:
public class DModel
{
public string Name { get; set; }
}
public class CModel
{
public string SomeName { get; set; }
}
public class BModel
{
public List<DModel> DModels { get; set; }
public BModel()
{
DModels = new List<DModel>();
}
}
public class AModel
{
public BModel BModel { get; set; }
public CModel CModel { get; set; }
public string PostType { get; set; }
public AModel()
{
BModel = new BModel();
CModel = new CModel();
}
}
AModel View:
@model MVC.Models.AModel
@if (Model == null)
{
<span>Model saved</span>
}
else
{
using (Html.BeginForm("Save", "Home", FormMethod.Post))
{
Html.RenderPartial("Partials/CModel", Model.CModel, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "CModel" } });
<hr />
Html.RenderPartial("Partials/BModel", Model.BModel, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "BModel" } });
<input type="submit" name="PostType" value="Add"/><br />
<input type="submit" name="PostType" value="Save"/>
}
}
BModel Partial View:
@model MVC.Models.BModel
@{
for (var i = 0; i < Model.DModels.Count(); i++)
{
Html.RenderPartial("Partials/DModel", Model.DModels[i], new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = $"{ViewData.TemplateInfo.HtmlFieldPrefix}.DModels[{i}]" } });
}
}
DModel Partial View:
@model MVC.Models.DModel
Name: @Html.EditorFor(x => x.Name) <br/>
CModel Partial View:
@model MVC.Models.CModel
SomeName: @Html.EditorFor(x => x.SomeName) <br/>
If you can use jQuery then those 2 submit inputs could be replaced with some buttons and onclick
event handlers which will take current form and post to different actions on controller.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.