MVC View POST calls new constructor instead of passing back model - c#

I've got a view which is adding a bunch of data into a bound EditModel. However, when it is POSTed, for some reason a parameterless constructor is called before calling the POST Action, instead of just passing back the model that was bound to the view.
I thought all I had to do was to make sure I reference the model in the "Inherits" tag at the top of the view, but for some reason all of the filled in data just gets thrown away on POST and a new instance of the model is instantiated. The View certainly seems to be able to see the model, as I can use Visual Studio Intellisense to access the model fields.
I'm sure it is something simple I am missing, so any pointers as to where to look would help. I can paste in some code if it helps.
Thanks!

As Omu says it will always call the parameterless constructor with a default modelbinder. Basically the modelbinder populate public memberes from the form collection based on the element names (plus maybe a prefix if defined). You need to make sure your element names (not Ids) match the public members you want populating on the model.

This is not how MVC works. When form is posted, MVC constructs new EditModel object and populates it with values provided in form. It doesn't preserve EditModel with was used to populate view in GET action. You have to make sure that every value that you want to use in POST method is set in html inputs in GET.

The constructor it is called, because that's what it should happen, now to see why is your model not filled with data it would be very helpful if would post the code of the view and post action.

Related

How does the BindAttribute work in binding the database columns to the program?

I used an ADO.NET controller template in order to try and understand how to connect and manipulate databases through MVC. I came across this line in the Create method and I'm struggling to understand what's being bound to what.
public ActionResult Create([Bind(Include = "UserID,First_Name,Surname,Password,Phone_Number,Email,IsAdmin")] UsersTable UsersTable)
My current understanding is that the fields of UsersTable is being bound to the method so the method can manipulate the fields. Is this correct or am I entirely wrong?
This means that the values passed in your payload when you call the Create action method - typically a POST - will be bound to the properties of your POCO class, UsersTable. Include means that these properties will be included, and all the others will not, there is also an Exclude version, meaning exactly the opposite, but you can leave them all out, meaning, all values sent will be bound to properties with the same name.

Why is ASP.NET scaffolding template allowing an IEnumerable to access the property of individual items?

A bit of a confusing question here. I used the default scaffolding template for an Index View and it is strongly typed to my model. However, if my model is Employee, the view is actully strongly typed to the generic Employee type of IEnumerable , not just the Employee class._
In the default template for the table headers, the first argument of the Html helper method takes the lambda expression 'model => model.name' This doesn't make sense to me, because you would never be able to directly access the property of an individal item in a collection from the collection itself. It doesn't seem like it should even compile, is this correct? How could that be explained?

Does ASP.NET MVC form post autopopulate fields?

I have a form like ...
#using (Html.BeginForm("create", "Account", FormMethod.Post, new { id = "accountform_form" }))
{
#Html.TextBoxFor(e => e.ShipFirstName)
...
}
while testing, I was surprised to see the field retained its value on postback even without me assigning it to the view-model. Using the debugger, the value for ShipFirstName is null right at the end of the action when returning the view, so why would it show the value that was in the field? Have I been unnecessarily assigning posted values to view-model properties all this time? Or is there something else going on?
Update: the action is like so...
[HttpPost]
public ViewResult Create(AccountFormModel postModel)
{
var model = new AccountFormModel(postModel, stuff, stuff); //I use posted values and paramters to create the actual view model
return view(model);
}
So, I see the GET form, enter values, say I enter a field and leave a required field blank, submit, the resulting page has the value I entered in the other field, who's putting it there when in the model it's null?
I ran into something similar earlier today (a checkbox was always checked). Have a look at Changing ViewModel properties in POST action and see if this is similar.
Basically calling ModelState.Clear() fixed it for me.
As you're passing the model back to the view after it has been POSTed, MVC is taking the stance that you're doing so because the form contains errors. So, rather than making the user fill out the form again, it repopulates it using the ModelState collection. In this case, the values in the ModelState collection take precedence over the changes you make in the action (which does feel a bit weird).
You can get around this either by calling ModelState.Clear() or using ModelState.Remove(string key), where key is the name of the property.
If you'd like a full explanation of why this is the case, see ASP.NET MVC’s Html Helpers Render the Wrong Value!. Excerpt:
Why?
ASP.NET MVC assumes that if you’re rendering a View in response to an HTTP POST, and you’re using the Html Helpers, then you are most likely to be redisplaying a form that has failed validation. Therefore, the Html Helpers actually check in ModelState for the value to display in a field before they look in the Model. This enables them to redisplay erroneous data that was entered by the user, and a matching error message if needed.

MVC Strongly typed IQueryable<IGrouping<TKey, TElement>> model

I'm trying to create a strongly typed model for one of my Views in MVC. The model is the result of a LINQ GroupBy query so it is the type shown below (grouping employees by first letter of surname).
#model IQueryable<IGrouping<string, Employee>>
I'm unsure why but it doesn't let me have a model of this type. The error message I get is:
An opening "<" is missing the corresponding closing ">". Which is incorrect.
I know I can create a view specific model and populate that instead but I'd like to know why this model doesn't seem to work?
By default, a very limited set of namespaces are available for direct use in razor views. Try to expand it to fully qualified names and see if the problem persists:
#model System.Linq.IQueryable<System.Linq.IGrouping<string, Name.Space.Employee>>
I don't know why you'd be getting this error, since you appear to be using correct Razor code. It's possible that there's actually a bug elsewhere in the page that is being made manifest through this incorrect error message.
A workaround, which may help you determine the real source of the bug, would be to create your own strongly-typed model class, which could have this data as its property:
public class EmployeeListViewModel
{
public IQueryable<IGrouping<string, Employee>> EmployeesByCompanyTitle {get;set;}
}
(There are those who would argue that this is a better approach anyway, since you can now add information to your view model more easily.)

How to enable edition of a list inside another object in ASP.NET MVC 2

I'm pretty new to MVC2 and need some help on how to do something. I have a Business Object which has associated a list of childs (example, A class populated with alumns). The thing is, any class can have an arbitrary number of alumns, so, how can I practically put that into a view? How will the user add new alumns or delete existing alumns to the class object, which is the one being edited?
I hope I made myself clear. Sorry no code at the moment since I still have to put up the data model and build the model objects, and then after this I'll write the Controller and the View.
Thanks!
If you're working with a collection/list of alumns then you will need to iterate over them in the view. This will enable a dynamic number of them being displayed.
Adding new ones will require calling an add action with the parent id on which it is to relate to. Similarly with delete you will need the associated id of the alumn and the parent id.
This answer from another questions with child/parent relations explains more with code.
Hope this helps

Categories

Resources