Issue with Html.EditorFor on MVC3 - asp.net-mvc

I have a view with a form that's is typed to a viewmodel called AddEditItemVM. This viewmodel has the following property:
public List<Category> Categories{get;set;}
What im trying is two things:
Render a checkbox foreach Category in the generic category list of my viewmodel.
Make that when the form is posted receive, in my controller action, the property Categories instantiated (into the instance of AddEditItemVM)
About the first point, i would like to use any helper (if exists) that renders a group of checkboxes using lambda expressions like (m=>m.Categories), instead to render the checkbox with a foreach into the view.
About the second point, i read that there is one feature in MVC called Custom Model Binders. These get values from ValueProviders (querystring, cookies, or Form values) and creates the necessary instances passing it to specific action called after a form was posted. Should i create one custom model binder in order to receive my property Categories instantiated?

This might work
CheckboxList in MVC3.0

Related

ASP.NET MVC Tuple

In my View i have to put two different Forms and i have to use two different ViewModels. So i decided to use Tuple.
View:
#model Tuple<pi.Models.AddNewMechanic,pi.Models.ExistingUser>
and I got two forms
But how can i recive it from View in HttpPost Controler?
I tried like that:
public ActionResult AddMechanic(Tuple<pi.Models.AddNewMechanic, pi.Models.ExistingUser> model) {}
but i got message it cannot find method with parameter, so how I have to implement it inside this method, but there is a question how?
I strongelly sugest you create a new Model and inside of your new model, you can put this two object. Take care to dont mix domain model and view model. Otherwise, you will have always this kind of problem.
Domain Model
- class a
- class b
View Model
- class AB
prop A, prop B
I suggest you do this by the book, which would be:
AddMechanic.cshtml has no special view model, but contains two partial views. This is your "page with two forms".
_AddNewMechanic.cshtml is the first partial view form, which has AddNewMechanic as view model.
_ExistingUser.cshtml is the second partial view form, which has ExistingUser as view model.
The form in _AddNewMechanic.cshtml posts to the AddNewMechanic action method, which takes an AddNewMechanic as parameter.
The form in _ExistingUser.cshtml posts to the AddExistingMechanic action method, which takes an ExistingUser as parameter.
Upsides:
No need for any Tuple weirdness.
You can keep your existing View Models.
Your action method parameters will not normally be null, so no need for weird null checks.
Easy to follow and understand your code.

How to prevent view from passing its model to the partial view, but instead pass null?

In ASP.NET MVC and using Razor, I have a View (parent) calling another View (child) as partial. Both are strongly typed but they have a different Model type.
Normally, in these situations, we pass a Model explicitly from the parent View to the child View.
#Html.Partial("Child", Model)
We can also choose not to specify explicitly a Model to be passed and, in those cases, the parent View will attempt to pass its own Model to the child View. This works if the types match and it is desirable in most cases.
#Html.Partial("Child")
In my case, however, I really want the parent View not to try to pass anything to the child View. How would I do that?
I thought of attempting to pass null explicitly:
#Html.Partial("Child", null)
But this still passes the parent's Model to the child View, resulting in an error: The model item passed into the dictionary is of type 'A', but this dictionary requires a model item of type 'B'.
(As a side note, the child View is a Create View for its model, that's why I don't have an instance to pass to it.)
Try this:
#Html.Partial("Child", null, new ViewDataDictionary<ChildType>(childInstance/*this can be null*/))
I understand the reason you want to not pass the model is so that your inputs are emptied out?
If this is the case, you can rather pass a new Model to this partial:
#Html.Partial("Child", new Model())
Since the Model is new, it won't have any values populated.
You could have your create form not strongly typed... craft your inputs in order to once posted you will have a model binded in your controller action.
Now... for me it doesn't worth the work just for the conceptual subtlety of "Model not existing yet" (AKA not in database yet).
In my case I create dummy models just to set default values in certain fields (for instance: setting today date, default values in dropdownlists, etc.)

Why do my viewmodel properties end up null or zero?

I'm working on my first MVC application, still figuring it all out.
I have a viewmodel which, at this point, is identical to my domain object. My controller builds the viewmodel and passes it to a view. The view only displays a some of the properties because I don't want primary and/or foreign keys displayed for the user yet, in the case of a primary key, I need to have the data in order to update / delete the database.
It appears that unless I use a viewmodel property in the view, it is set to default values (0 for numeric value types and null for reference types) when I pass the viewmodel back. Is this correct behavior?
I confirmed the viewmodel passed to the Edit view does contain all the properties (as I would expect).
The question - Once a view is rendered, what happens to the viewmodel? If my viewmodel contains properties that are not used in the view, do their values just disappear? For example, when I click the Edit actionlink to fire the Edit action on the controller, the viewmodel that gets passed to the action does not contain any properties unless they are visible on the screen. Why?
BTW, this is ASP.NET MVC 4 RC.
It appears that unless I use a viewmodel property in the view, it is
set to default values (0 for numeric value types and null for
reference types) when I pass the viewmodel back. Is this correct
behavior?
Yes, when you invoke a controller action you need to pass all the properties that you want to be bound in the request. So for example if you are using a html <form> to call the action you need to use input fields. You could use hidden fields but they must be present, otherwise nothing is sent to the controller action
The question - Once a view is rendered, what happens to the viewmodel?
It falls out of scope and is eligible for garbage collected.
If my viewmodel contains properties that are not used in the view, do their values just disappear?
Absolutely. But even if you use those properties inside the view they disappear. For example if you only display the values inside the view but do not use input fields to send them back to the server when the form is submitted they will be gone as well.
For example, when I click the Edit actionlink to fire the Edit action
on the controller, the viewmodel that gets passed to the action does
not contain any properties unless they are visible on the screen. Why?
Because the view model no longer exists. It's gone and garbage collected. That's how the HTTP protocol works. It's stateless. Nothing is persisted between the requests. You will have to include whatever properties you want to be populated in the request either as POST form values or as query string parameters if you are using action links or whatever.
If the user is not supposed to modify those values inside the view you could then simply pass an id to the controller action which will allow for this controller action to retrieve the model from wherever it is stored (a database or something) using this id.
If your properties are in any helper methods which generates the input HTML element inside a form, It will be available in your HTTPost action method when you submit the form. If you are simply displaying it in a div/span , it is not going to get you the property values. That is how MVC model binding works.
Expect the values in your HttpPOST action if you use these HTML helpers
#Html.TextBoxFor
#Html.DropDownFor
#Html.EditorFor
#Html.HiddenFor
Dont expect the values if you use these
#Html.DisplayFor

How to access model property in Razor view of IEnumerable Type?

How to access Model property(Like #Html.EditorFor(x=>Model.Name)) in Razor view of IEnumerable Type without using Loops??I.e If a view is strongly typed to some Model holding Model as a LIST.Eg.
#model IEnumerable<EFTest2.DAL.package_master>
Then is it possible to Display TestBoxFor or EditorFor (to create new Model) Html helper without using foreach Loop.???
When some model property is of type IEnumerable<SomeType> you would normally define an editor/display template (~/Views/Shared/EditorTemplates/SomeType.cshtml or ~/Views/Shared/DisplayTemplates/SomeType.cshtml). This template will be automatically rendered for each element of the collection so that you don't need to write loops:
#Html.EditorFor(x => x.SomeCollection)
and inside the template you will be able to access individual properties:
#model SomeType
#Html.EditorFor(x => x.Name)
...
Now, if you absolutely need to directly access some element inside a view which is strongly typed to IEnumerable<SomeType> you would better use some other collection type such as IList<SomeType> or SomeType[] as view model which will give you direct access to elements by index and you will be able to do this for example to access the 6th element of the collection:
#model IList<SomeType>
#Html.EditorFor(x => x[5].Name)
So basically you are mentioning of type List etc.
If you want to add values to the list accepting input from user from form fields and then add to the existing list in model. the easiest but not so elegant way would be
suppose you have class "Person" and then List in your model. first create an instance of person that will have empty person instance , add it to list and then bind this last list item to your edit for.
#{
Person contact = new Person(); //Empty person instance
PersonList.Add(contact);
}
later on bind this to your induvidual fields
#Html.TextBoxFor(m => m.PersonList[PersonList.Count - 1].PrimaryContacts.FirstName)
This works good for Validation on model properties as-well and also after every form submit, for next inclusion you just add the new person. but take care to write the remove peice of code if form is cancelled.

Using a dynamic list of checkboxes in a view, how to create the model

I have an asp mvc 2 app lication where I want to display a list of check boxes that a user can select, based on a list of records in a database. To display the list my model contains a List object and the view has a foreach, and outputs Html.CheckBox for each item in the list.
Is there a way to get the model populated with the selected checkboxes, given that the model can't have specific properties for each checkbox, because the list is dynamic? Or do I have to manually iterate through the forms variables myself?
Edit: Extra details as per sabanito's comment
So in a simple view/model scenario, if my model had a property called Property1, then my view outputted a Textbox for Property1, when the form is posted via a submit button, the mvc framework will automatically populate a model with Property1 containing the text that was entered into the textbox and pass that model to the Controllers action.
Because I am dealing with a dynamic list of options the user could check, I can't write explicit boolean properties in my model and explicitly create the checkboxes in my view. Given that my list is dynamic, I'm wondering if there are ways to create my model and view so that the mvc framework is able to populate the model correctly when the form is posted.
Here's what I would do:
Are you having any issues generating the checkbox's dynamically?
If not, create a property on your ViewModel that is a:
public List<string> CheckboxResults { get; set; }
When you generate your checkbox's in the view make sure they all share the name = "CheckboxResults". When MVC see's your ViewModel as a parameter on the action method it will automatically bind and put all the "CheckboxResults" results in the List (as well as your other ViewModel properties). Now you have a dynamic List based on which checkbox's your user checked that you can send to your DomainModel or wherever.
Pretty cool stuff. Let me know if you're having issues generating the checkbox's dynamically, that's kind of a seperate issue than model binding to a list.
Use a ViewModel that reflects your view exactly, and map your domain model(s) to the viewmodel.
At first it often seems appropriate to use domain models directly in the view, for no better reason than that they're simple to use. However, as the view gets more complex over time, you end up putting a TON of conditional logic in your view, and end up with spaghetti. To alleviate this, we typically create a ViewModel that correlates 1:1 with the view.

Resources