My application needs to CRUD contracts, and I can attach documents to each contract. So, in my Edit/Update page, I have three forms:
- one to update the contract properties (Edit.cshtml)
- one to add document(s) to the contract (AddDocument.cshtml)
- one to remove a document from the contract (not necessary to show)
and it looks like this:
Edit.cshtml
@model ContractViewModel
@Html.Action("AddDocument", "Contracts", new { id = Model.IdContract })
@Html.Action("RemoveDocument", "Contracts", new { id = Model.IdContract })
@using (Html.BeginForm("Edit", "Contracts", FormMethod.Post, new { @class = "form-horizontal", enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.IdContract)
<div class="form-group">
@Html.LabelFor(model => model.ContractNumber, htmlAttributes: new { @class = "control-label col-md-4" })
<div class="col-md-8">
@Html.EditorFor(model => model.ContractNumber, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.ContractNumber)
</div>
</div> [...]
<input type="submit" value="Update"/>
}
AddDocument.cshtml
@model DocumentViewModel
@using (Html.BeginForm("AddDocument","Contracts", FormMethod.Post, new { @class = "form-horizontal", enctype="multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.IdContract)
<div class="form-group">
@Html.LabelFor(model => model.DocHttp, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(x => x.DocHttp, htmlAttributes: new { @class = "form-control", data_style = "btn-primary", type = "file", multiple = "multiple" })
@Html.ValidationMessageFor(model => model.DocHttp)
</div>
</div>
<input type="submit" value="Add"/>
}
ContractController.cs
public ActionResult Edit(int? id)
{
if (id == null)
{
throw new HttpException(400, "Bad request");
}
Contract contract = business.Get<Contract>(x => x.IdContract == id);
ContractViewModel vm = new ContractViewModel(contract);
if (contract == null)
{
throw new HttpException(404, "Not found");
}
return View(vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ContractViewModel vm)
{
Contract contract = business.Get<Contract>(x => x.IdContract == id);
if (ModelState.IsValid)
{
[...]
}
return View(vm);
}
public ActionResult AddDocument(int id)
{
DocumentViewModel vm = new DocumentViewModel();
vm.IdContract = id;
return PartialView(vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddDocument(DocumentViewModel vm)
{
Contract contract = business.Get<Contract>(x => x.IdContract == vm.IdContract);
if (ModelState.IsValid)
{
[...]
}
return RedirectToAction("Edit", "Contracts", new { id = vm.IdContract });
//return View(vm);
}
Firstly, the issue is, when I submit the Edit form, the [HttpPost]Edit method is naturally called, but also the [HttpPost]AddDocument. Is that due to the Html.Action used instead of Html.RenderPartial?
If I'm right, the Html.Action is called when you have to do a treatment before generating the partial view, while Html.RenderPartial passes just parameters.
Why is the [HttpPost]AddDocument method called? and who called it?
Secondly, to bypass the problem, I have to Redirect to the Edit page instead of calling the View method. But, I'm losing the data entered. How can I manage this problem?
Thanks.