This view is based on a pretty complex model object that contains other objects as properties. At the bottom of the view I have a simple input element of type "submit" which eventually
calls the Confirm action on my controller.
Here is what my controller looks like:
public PartialViewResult
Confirm(String
button, StoreRequestValidationViewModel
Item)
...
The
StoreRequestValidationViewModel
is a subclass of
StoreRequestViewModel in the partial view.
When I place a breakpoint in my controller to view the Item parameter, I see all of my parameters being sent, including the child objects. The Confirm view is generated properly.
Actually, the Confirm view is the same as this first view except that everything is in read only. Basically, the user uses this view to check his information before clicking a Save button that will update the database.
The problem is with this second read-only view. I used the same logic as the first view but the model that is sent to the controller has the child object always null. The only difference
in the view is that I use LabelFor helpers.
information that are not rendered in input fields are not returned back to the controller when form is submitted, so your model in the controller is not updated. The solution is that you put the property that are in label fields also int an hidden
field, so they can be returned to the server
The view contains a bunch of fields that render as read only labels. Actually, I use a Html helper :
public static MvcHtmlString DisplayFormatedDetails<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
string text = "N/A";
if (metadata.Model != null)
{
text = metadata.Model.ToString();
}
if (string.IsNullOrEmpty(text))
{
return MvcHtmlString.Empty;
}
else
{
if (text.Contains(Environment.NewLine))
{
text = text.Replace(Environment.NewLine, "<br />");
}
else
{
for (int i = 0; i < text.Length; i = i + 80)
{
text = text.Insert(i, Environment.NewLine);
}
}
return new MvcHtmlString(text);
}
}
Here is part of the view:
@model StoreRequestValidationViewModel
@{
String Active = "";
if (Model != null)
{
if (Model.StoreSIRequestTypeId == StoreRequestTypes.PeriodicDistributionReport)
{
Active = "PDR";
}
else if (Model.StoreSIRequestTypeId == StoreRequestTypes.StoreStatement)
{
Active = "SS";
}
else if (Model.StoreSIRequestTypeId == StoreRequestTypes.WarehouseInvoice)
{
Active = "WI";
}
}
}
the browser will not post labels or html, only input, select & textarea elements in the form that is doing the submit. they arrive as name / value pairs (with mvc the name should be the property name). the binder creates a new instance of the model, and
applies post values to it then calls the controller.
One of our programmers found a solution to this problem. He placed the model inside the Cache. But before saving it to cache he explicitly added the child objects and used the "as" keyword to convert from the parent viewmodel class to the validationviewmodel
class. When doing that, we at least did not lose the child objects. Then the controller was able to pick up the entire model.
I don't think this approach will be ideal long term. You should spend some time reading up on model binding so you really understand how it works. I suggest Sanderson's MVC 3 book -- it will be worth your time.
I don't think this approach will be ideal long term. You should spend some time reading up on model binding so you really understand how it works. I suggest Sanderson's MVC 3 book -- it will be worth your time.
I agree, You have to understand how model binding works and organize the names of the htll inputs in your views in succh a way they can be submitted properly to the receiving controllew.
On mvc there is no State that is moved between sever and client, but the "state" is stored in the input fileds you manipulate explicitely, and model binding occurs on a name convention basis....so be sure to understand wee how does this work...
So is it safe to assume that there is no elegant solution for this type of requirement? What we're trying to do is have users enter the information in a form using the usual input tags, this posts correctly.
But then the user is presented with a Confirmation screen where the data she entered is in read-only form. The Save button is on this page, which has no input tags. I really don't want to use hidden fields.
rayc
Member
329 Points
127 Posts
Controller not receving entire model
Apr 11, 2012 06:32 PM|LINK
I have a view that contains the following Ajax.BeginForm:
@model StoreRequestViewModel
@using (Ajax.BeginForm("Confirm", new AjaxOptions() { HttpMethod = "Post", UpdateTargetId = "formContainer", LoadingElementId = "StoreRequestForm"}))
This view is based on a pretty complex model object that contains other objects as properties. At the bottom of the view I have a simple input element of type "submit" which eventually calls the Confirm action on my controller.
Here is what my controller looks like:
public PartialViewResult Confirm(String button, StoreRequestValidationViewModel Item)
...
The StoreRequestValidationViewModel is a subclass of StoreRequestViewModel in the partial view.
When I place a breakpoint in my controller to view the Item parameter, I see all of my parameters being sent, including the child objects. The Confirm view is generated properly. Actually, the Confirm view is the same as this first view except that everything is in read only. Basically, the user uses this view to check his information before clicking a Save button that will update the database.
The problem is with this second read-only view. I used the same logic as the first view but the model that is sent to the controller has the child object always null. The only difference in the view is that I use LabelFor helpers.
Help?
BrockAllen
All-Star
28072 Points
4996 Posts
MVP
Re: Controller not receving entire model
Apr 11, 2012 06:35 PM|LINK
Can you show (some of) the view that's emitting the HTML for the model.
DevelopMentor | http://www.develop.com
thinktecture | http://www.thinktecture.com/
giop
Member
378 Points
81 Posts
Re: Controller not receving entire model
Apr 11, 2012 07:10 PM|LINK
Please post your view, and model :)
Seems to be a binding problem.
Please Mark as Answer if it helps :)
francesco ab...
All-Star
20954 Points
3286 Posts
Re: Controller not receving entire model
Apr 11, 2012 08:11 PM|LINK
information that are not rendered in input fields are not returned back to the controller when form is submitted, so your model in the controller is not updated. The solution is that you put the property that are in label fields also int an hidden field, so they can be returned to the server
Mvc Controls Toolkit | Data Moving Plug-in Videos
rayc
Member
329 Points
127 Posts
Re: Controller not receving entire model
Apr 13, 2012 01:15 PM|LINK
The view contains a bunch of fields that render as read only labels. Actually, I use a Html helper :
public static MvcHtmlString DisplayFormatedDetails<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
string text = "N/A";
if (metadata.Model != null)
{
text = metadata.Model.ToString();
}
if (string.IsNullOrEmpty(text))
{
return MvcHtmlString.Empty;
}
else
{
if (text.Contains(Environment.NewLine))
{
text = text.Replace(Environment.NewLine, "<br />");
}
else
{
for (int i = 0; i < text.Length; i = i + 80)
{
text = text.Insert(i, Environment.NewLine);
}
}
return new MvcHtmlString(text);
}
}
Here is part of the view:
@model StoreRequestValidationViewModel
@{
String Active = "";
if (Model != null)
{
if (Model.StoreSIRequestTypeId == StoreRequestTypes.PeriodicDistributionReport)
{
Active = "PDR";
}
else if (Model.StoreSIRequestTypeId == StoreRequestTypes.StoreStatement)
{
Active = "SS";
}
else if (Model.StoreSIRequestTypeId == StoreRequestTypes.WarehouseInvoice)
{
Active = "WI";
}
}
}
<div id="SI" style="display:block;">
<table width="75%" border="0" cellpadding="5">
<tr>
<td width="75%" height="1" >@Html.Image("~/Content/Images/spacer.gif", "", "")</td>
</tr>
<tr>
<td class="projectsSearchResultsHeader" ><u>Store Information</u></td>
</tr>
</table>
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr>
<td width="5">@Html.Image("~/Content/Images/spacer.gif", "", "")</td>
<td width="170" class="contentLabelBold">
@AppStrings.StoreRequestFormCompany<font class="contentLabelRequired">*</font>
</td>
<td class="DisplayContent">
@Html.DisplayFormatedData(item => item.CompanyVendorName)
</td>
</tr>
<tr>
<td width="5">@Html.Image("~/Content/Images/spacer.gif", "", "")</td>
<td width="170" class="contentLabelBold">
@AppStrings.StoreRequestFormRequestType <font class="contentLabelRequired">*</font>
</td>
<td class="DisplayContent">
@Html.DisplayFormatedData(item => item.StoreSIRequestTypeName)
</td>
</tr>
<tr>
Is it the Html helper that is not allowing it to generate the proper request?
bruce (sqlwo...
All-Star
37614 Points
5573 Posts
Re: Controller not receving entire model
Apr 13, 2012 01:20 PM|LINK
the browser will not post labels or html, only input, select & textarea elements in the form that is doing the submit. they arrive as name / value pairs (with mvc the name should be the property name). the binder creates a new instance of the model, and applies post values to it then calls the controller.
rayc
Member
329 Points
127 Posts
Re: Controller not receving entire model
Apr 13, 2012 01:28 PM|LINK
One of our programmers found a solution to this problem. He placed the model inside the Cache. But before saving it to cache he explicitly added the child objects and used the "as" keyword to convert from the parent viewmodel class to the validationviewmodel class. When doing that, we at least did not lose the child objects. Then the controller was able to pick up the entire model.
BrockAllen
All-Star
28072 Points
4996 Posts
MVP
Re: Controller not receving entire model
Apr 13, 2012 02:20 PM|LINK
I don't think this approach will be ideal long term. You should spend some time reading up on model binding so you really understand how it works. I suggest Sanderson's MVC 3 book -- it will be worth your time.
DevelopMentor | http://www.develop.com
thinktecture | http://www.thinktecture.com/
francesco ab...
All-Star
20954 Points
3286 Posts
Re: Controller not receving entire model
Apr 13, 2012 02:30 PM|LINK
I agree, You have to understand how model binding works and organize the names of the htll inputs in your views in succh a way they can be submitted properly to the receiving controllew.
On mvc there is no State that is moved between sever and client, but the "state" is stored in the input fileds you manipulate explicitely, and model binding occurs on a name convention basis....so be sure to understand wee how does this work...
Mvc Controls Toolkit | Data Moving Plug-in Videos
rayc
Member
329 Points
127 Posts
Re: Controller not receving entire model
Apr 14, 2012 12:43 AM|LINK
So is it safe to assume that there is no elegant solution for this type of requirement? What we're trying to do is have users enter the information in a form using the usual input tags, this posts correctly.
But then the user is presented with a Confirmation screen where the data she entered is in read-only form. The Save button is on this page, which has no input tags. I really don't want to use hidden fields.