Tech
Forums
Jobs
Books
Events
Videos
Live
More
Interviews
Certification
Training
Career
Members
News
Blogs
Contribute
An Article
A Blog
A Video
An Ebook
An Interview Question
Register
Login
2
Answers
MVC - Related Data - Postback
Pinpoint Solutions
9y
770
1
Reply
Hi all,
I have an MVC 5 generated "Create" page. Now for the related data I have made a table, which looks like this:
When clicking on the green add button, the following modal is shown:
In this design, the user is able to add/remove sub-items to the list before submitting the form.
In this example, the row in the screenshot I add initially. All works well, except when I remove this initial row in my Create action (which shouldn't be there anyway, it should start with an empty table) no rows added are available on the server. Somehow, the Model Binder only works when there's initially 1 row rendered from the create action.
Data Model:
Controller actions:
(
OrganisatieController.cs
)
public
ActionResult
Create()
{
Organisatie
myOrganisatie =
new
Organisatie
();
//-- Test Data --
AccountType_Organisatie
myAccTypeOrg =
new
AccountType_Organisatie
();
myAccTypeOrg.Accounttype_GUID = csContext.AccountTypes.First().AccountType_GUID;
myAccTypeOrg.AccountType = csContext.AccountTypes.First();
myAccTypeOrg.Omschrijving =
"Test1234"
;
myOrganisatie.AccountType_Organisaties.Add(myAccTypeOrg);
//-- End Test Data –
//-- Load Dropdown Data --
ViewBag.slAccountTypes =
new
SelectList
(csContext.AccountTypes,
"AccountType_GUID"
,
Omschrijving"
);
return
View(myOrganisatie);
}
[
HttpPost
]
[
ValidateAntiForgeryToken
]
public
ActionResult
Create(
[
Bind
(Include =
"Organisatie_GUID,OrganisatieID,OrganisatieNaam,Startdatum,Einddatum,Afkorting,Manager_GUID,AanleverendePartij,BovenliggendeOrganisatie_GUID,AccountType_Organisaties"
)]
Organisatie
myOrg)
{
try
{
int
x = 0;
foreach
(
AccountType_Organisatie
myAccType_Org
in
myOrg.AccountType_Organisaties)
{
myAccType_Org.AccountType_Organisatie_GUID =
Guid
.NewGuid();
myAccType_Org.AccountType = csContext.AccountTypes.Find(myAccType_Org.Accounttype_GUID);
//-- Remove Related Model Validation errors --
ModelState.Remove(
String
.Format(
"AccountType_Organisaties[{0}].AccountType.Omschrijving"
, x));
ModelState.Remove(
String
.Format(
"AccountType_Organisaties[{0}].AccountType.Domein"
, x));
ModelState.Remove(
String
.Format(
"AccountType_Organisaties[{0}].AccountType.UPN_DomainTag"
, x));
ModelState.Remove(
String
.Format(
"AccountType_Organisaties[{0}].AccountType.Graceperiod"
, x));
x++;
}
if
(ModelState.IsValid)
{
myOrg.Organisatie_GUID =
Guid
.NewGuid();
//-- Update related data with new GUID --
foreach
(
AccountType_Organisatie
myAccType_Org
in
myOrg.AccountType_Organisaties)
{
myAccType_Org.Organisatie_GUID = myOrg.Organisatie_GUID;
}
csContext.Organisaties.Add(myOrg);
csContext.SaveChanges();
return
RedirectToAction(
"Index"
);
}
}
catch
(System.Data.
DataException
ex)
{
ModelState.AddModelError(
""
,
"Could not create the Organisation. [Reason: "
+ ex.Message +
"]"
);
}
//-- Load Dropdown Data --
ViewBag.slAccountTypes =
new
SelectList
(csContext.AccountTypes,
"AccountType_GUID"
,
Omschrijving"
);
return
View(myOrg);
}
ViewPage
: (
Create.shtml
)
@model
ConfiguratorWeb.Models.
Organisatie
@section Styles {
@
Styles
.Render(
"~/bundles/data-input-css"
)
}
@{
ViewBag.Title =
"Nieuwe Organisatie"
;
Layout =
"~/Views/Shared/_Layout.cshtml"
;
}
@
using
(Html.BeginForm())
{
@
Html.AntiForgeryToken()
<
div
class
="form-horizontal">
@
Html.ValidationSummary(
true
)
@
Html.HiddenFor(model => model.Organisatie_GUID)
<
div
class
="form-group">
@
Html.LabelFor(model => model.OrganisatieID,
new
{ @class =
"control-label col-md-2"
})
<
div
class
="col-md-10">
@
Html.EditorFor(model => model.OrganisatieID)
@
Html.ValidationMessageFor(model => model.OrganisatieID)
</
div
>
</
div
>
<
div
class
="form-group">
@
Html.LabelFor(model => model.OrganisatieNaam,
new
{ @class =
"control-label col-md-2"
})
<
div
class
="col-md-10">
@
Html.EditorFor(model => model.OrganisatieNaam)
@
Html.ValidationMessageFor(model => model.OrganisatieNaam)
</
div
>
</
div
>
<
hr
/>
<
div
class
="h4">
Account Types
</
div
>
<
br
/>
<
table
id
="tblAccountTypes"
data-toggle
="table"
style
="
visibility
:
visible
;
">
<
thead
>
<
tr
>
<
th
>
GUID
</
th
>
<
th
>
Item Name
</
th
>
<
th
>
Omschrijving
</
th
>
<
th
></
th
>
</
tr
>
</
thead
>
<
tbody
>
@
Html.EditorFor(model => model.AccountType_Organisaties)
</
tbody
>
</
table
>
<
button
id
="btnAddAccountType"
type
="button"
class
="btn btn-success btn-xs btn-glyph-xs"
title
="Add AccountType"
onclick
="
showModal();
"
style
="
margin-top
:
10px
;
">
<
span
class
="glyphicon glyphicon-plus"></
span
>
</
button
>
<
hr
/>
@{
Html.RenderPartial(
"_ActionButtons"
,
new
ViewDataDictionary
{ {
"SubmitClientClick"
,
"return fixIndexing();"
} });
}
</
div
>
}
<
div
id
="modalAddAccountType"
class
="modal fade">
<
div
class
="modal-dialog">
<
div
class
="modal-content">
<
div
class
="modal-header">
<
button
type
="button"
class
="close"
data-dismiss
="modal"
aria-label
="Close"><
span
aria-hidden
="true">
×
</
span
></
button
>
<
h4
class
="modal-title">
AccountType toevoegen
</
h4
>
</
div
>
<
div
class
="modal-body">
<
p
>
Kies hieronder het AccountType dat u wilt toevoegen aan de Organisatie.
</
p
>
<
br
/>
<
div
class
="form-horizontal">
<
div
class
="form-group">
<
label
class
="control-label col-md-2">
Account Type
</
label
>
<
div
class
="col-md-10">
@
Html.DropDownList(
"ddlAccountType"
, (
IEnumerable
<
SelectListItem
>)ViewData[
"slAccountTypes"
],
""
,
new
{ @class =
"form-control dropdown"
})
<
label
id
="lblAccountType_Required"
class
="h6 control-label"
style
="
visibility
:
hidden
;
">
U dient een Account type te selecteren
</
label
>
</
div
>
</
div
>
<
div
class
="form-group">
<
label
class
="control-label col-md-2">
Omschrijving
</
label
>
<
div
class
="col-md-10">
@
Html.TextBox(
"txtOmschrijving"
,
null
,
new
{ @class =
"form-control"
})
<
label
id
="lblOmschrijving_Required"
class
="h6 control-label"
style
="
visibility
:
hidden
;
">
U dient een omschrijving in te voeren
</
label
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
class
="modal-footer">
<
button
type
="button"
class
="btn btn-default"
data-dismiss
="modal">
Sluiten
</
button
>
<
button
type
="button"
class
="btn btn-primary"
onclick
="
addAccountType();
">
Toevoegen
</
button
>
</
div
>
</
div
>
<!-- /.modal-content -->
</
div
>
<!-- /.modal-dialog -->
</
div
>
<!-- /.modal -->
@section Scripts {
@
Scripts
.Render(
"~/bundles/jqueryval"
)
@
Scripts
.Render(
"~/bundles/data-input-js"
)
<
script
>
$(document).ready(
function
() {
$(
'#tblAccountTypes'
).bootstrapTable(
'hideLoading'
,
null
);
//$('.no-records-found').remove();
//-- Add onclick handler to Delete button --
$(
'[id^="btnDelete_"]'
).on(
"click"
, deleteRow);
});
function
showModal() {
$(
'#modalAddAccountType'
).modal();
}
function
addAccountType() {
var
IsValid =
true
;
var
AccountType_GUID = $(
'#ddlAccountType option:selected'
).val();
var
AccountType_Naam = $(
'#ddlAccountType option:selected'
).text();
var
Omschrijving = $(
'#txtOmschrijving'
).val();
if
(IsValid) {
//-- Determine index to be used --
var
Index = 0;
//-- Add new row to table --
var
newRow =
"<tr data-index=\""
+ Index +
"\">"
;
newRow +=
"<td><input id=\"AccountType_Organisaties_"
+ Index +
"__Accounttype_GUID\" name=\"AccountType_Organisaties["
+ Index +
"].Accounttype_GUID\" type=\"hidden\" value=\""
+ AccountType_GUID +
"\">"
+ AccountType_GUID +
"</td>"
;
newRow +=
"<td><input id=\"AccountType_Organisaties_"
+ Index +
"__AccountType_Omschrijving\" name=\"AccountType_Organisaties["
+ Index +
"].AccountType.Omschrijving\" value=\""
+ AccountType_Naam +
"\" type=\"hidden\">"
+ AccountType_Naam +
"</td>"
;
newRow +=
"<td><input id=\"AccountType_Organisaties_"
+ Index +
"__Omschrijving\" name=\"AccountType_Organisaties["
+ Index +
"].Omschrijving\" type=\"hidden\" value=\""
+ Omschrijving +
"\">"
+ Omschrijving +
"</td>"
;
newRow +=
"<td><button id=\"btnDelete_"
+ AccountType_GUID +
"\" type=\"button\" class=\"btn btn-success btn-xs btn-glyph-xs\" title=\"Verwijderen\"><span class='glyphicon glyphicon-remove'></span></button></td></tr>"
;
$(
'#tblAccountTypes tbody:last'
).append(newRow);
//-- Add onclick handler to Delete button --
$(
'#btnDelete_'
+ AccountType_GUID).on(
"click"
, deleteRow);
//-- Remove Item from Dropdownlist in Modal --
$(
'#ddlAccountType'
).find(
'option[value='
+ AccountType_GUID +
']'
).remove();
//-- Close Modal --
$(
'#modalAddAccountType'
).modal(
'toggle'
);
}
}
function
fixIndexing() {
var
tableRows = $(
'#tblAccountTypes tbody tr'
);
for
(x = 0; x < tableRows.length; x++) {
tableRows.eq(x).attr(
'data-index'
, x);
tableRows.eq(x).children(
'td:nth-child(1)'
).children(
'input:first'
).attr(
'name'
,
'AccountType_Organisaties['
+ x +
"].Accounttype_GUID"
);
tableRows.eq(x).children(
'td:nth-child(2)'
).children(
'input:first'
).attr(
'name'
,
'AccountType_Organisaties['
+ x +
"].AccountType.Omschrijving"
);
tableRows.eq(x).children(
'td:nth-child(3)'
).children(
'input:first'
).attr(
'name'
,
'AccountType_Organisaties['
+ x +
"].Omschrijving"
);
}
return
true
;
//- Submit Form -
}
function
deleteRow() {
//-- Add Item to Dropdownlist in Modal --
var
row = $(
this
).parents(
'tr'
);
var
Account_GUID = row.children(
'td:nth-child(1)'
).text();
var
Account_Naam = row.children(
'td:nth-child(2)'
).text();
$(
'#ddlAccountType'
).append(
new
Option(Account_Naam, Account_GUID));
//-- Remove row from table --
row.remove();
}
</
script
>
}
And finally the
Editor Template
for the related data (
AccountType_Organisatie.cshtml
):
@model
ConfiguratorWeb.Models.
AccountType_Organisatie
<
tr
>
<
td
>
@
Html.HiddenFor(x => Model.Accounttype_GUID)
@
Model.Accounttype_GUID
</
td
>
<
td
>
@
Html.HiddenFor(x => Model.AccountType.Omschrijving,
new
{ data_val =
false
})
@
Model.AccountType.Omschrijving
</
td
>
<
td
>
@
Html.HiddenFor(x => Model.Omschrijving,
new
{ data_val =
false
})
@
Model.Omschrijving)
</
td
>
<
td
>
<
button
id
="btnDelete_
@
Model.Accounttype_GUID
"
type
="button"
class
="btn btn-success btn-xs btn-glyph-xs"
title
="Verwijderen"
onclick
="
deleteRow()
">
<
span
class
='glyphicon glyphicon-remove'></
span
>
</
button
>
</
td
>
</
tr
>
Post
Reset
Cancel
Answers (
2
)
Next Recommended Forum
How to trigger remote validation for dropdown list
Update file and photo in gridview