asp.net MVC "Add View" wizard won't pre-populate fields when using a ViewModel - model-view-controller

In VS 2010, When you use the "Add View" wizard to create an Edit view with a strongly typed view, such as Models.Person, the template generates all of Person fields for you.
If you use a view model instead, like this:
public class PersonVM
{
public Person person;
public List<Team> TeamList = new TeamServices().TeamPickList();
...
}
the template wont create all of the fields for Model.person.
Is there a way to make that work?

Not automatically.
Easiest method is to create a new View, select Team as the view data class, Select 'List' as the view content. Then you could cut and paste the markup generated from this view into the one you have already created.

If you use the List template it will normally create a table and iterate over an IEnumerable Model. You can also use one of the helpers and/or custom templates in your CodeTemplates folder:
<% Html.DisplayForModel(); %>
If you need to edit:
<% Html.EditorForModel(); %>
If you're having trouble with the list, maybe start with one of the helpers?
<%: Html.DropDownListFor(model => model.TeamList, new SelectList(Model.TeamList)) %>

Related

ASP.Net MVC 3 - DropDownListFor fails to select the value form the model if HtmlFieldPrefix is set on the partial view

when using
<%= Html.DropDownListFor(model => model.FeeTypeId, Model.GetFeeTypes(), new { })%>
in this case the right option is selected according to Model.FeeTypeId when the select is rendered.
BUT
if you render the form using a partial view, passing it a specific HtmlFieldPrefix (you will need it if,for example, you want to render two identical views and want different ids the elements)
<% Html.RenderPartial("path-to-partial-view", Model, new ViewDataDictionary() { TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = "myPrefix" } }); %>
then the value will not be selected.
looks similar to the problem at DropDownListFor in EditorTemplate not selecting value but from different cause.
looked in the MVC 3 source and seems like the problem is at the SelectInternal method
it uses the htmlHelper.ViewData.Eval(fullName);
which fails to get the value by the full name when it contains the prefix,
TextBoxFor doesn't fail as it passes the value of the expression to InputHelper so it doesn't get to use the ViewData.Eval
just to be sure tested it at the partial view:
in the partial view the following will print "myPrefix.FeeTypeId"
<%= Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName("FeeTypeId") %>
and the following will print "by property name: [value] by full name: [empty string]"
<%="by property name: " + Html.ViewData.Eval("FeeTypeId")%><br />
<%= "by full name: " + Html.ViewData.Eval(Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName("FeeTypeId"))%>
The only solution i found is to generate a List at Model.GetFeeTypes() and mark the option i want as selected:
<%= Html.DropDownListFor(model => model.FeeTypeId, Model.GetFeeTypes(Model.FeeTypeId), new { })%>
don't really like this solution + i know i can create the List in the partial view which is also ugly,
is there another solution to this?
I have discovered that this is a bug in MVC. It's not fixed, though there is a work around.
See my question answered by myself (I had the same problem before finding your post).
MVC4 binding drop down list in a list (bug)
Regards
Craig

Dynamically Add Rows when using Editor Templates and EditorFor in MVC 3

Expanding on a previous question, I'm using EditorFor to edit a list of objects of type (let's say) Hobby.
Now, I need to implement functionality to add editors for individual Hobby objects, so that the user can add additional hobbies.
I read Steven Anderson's blog about how to do that in MVC 2. However, he's rendering the individual Hobby instances using a loop and RenderPartial, rather than using EditorFor. I understand his approach of making Ajax calls to render another partial view and inserting the view result into the DOM, but don't know how to apply the Ajax add in my case, with EditorFor.
His code:
<% foreach (var item in Model)
Html.RenderPartial("GiftEditorRow", item);
%>
My code is using EditorFor like this:
// Model is a List<Hobby>
#Html.EditorFor(model => model.AllowedSurveys)
How do I add an additional Hobby editor, given that the editor is implemented as an Editor Template rather than as a Partial View?
You could replace your editor template with a partial:
#foreach (var item in Model.AllowedSurveys)
{
Html.RenderPartial("_Hobby", item);
}
and inside the partial (~/Views/controllerName/_Hobby.cshtml):
#model Hobby
<div class="editorRow">
#using(Html.BeginCollectionItem("AllowedSurveys"))
{
#Html.EditorFor(x => x.Name)
...
}
</div>
The Html.BeginCollectionItem custom helper is used to generate names with Guids and allow for reordering and adding new items to the collection using javascript. You can download it from the updated article. The one you were reading was for ASP.NET MVC 1 and is obsolete.

MVC 3 Partial View and what I need to send to it?

I am wondering about a couple variations of forms and partial forms. The submit is on the parent page and I have varied what I pass to the partial view. I have a parent view with a related HomeViewModel (which has public properties Name and public Person Employee {get;set;}
1.) Scenario 1: The main view has something like the following
#model MasterDetailSample.Models.HomeViewModel
#using (Html.BeginForm()) {
<div>
#{Html.RenderPartial("_PersonView", #Model);}
</div>
<input type="submit" value="Save" />
}
In this scenario I am passing to the partial view _PersonView the entire HomeViewModel. Within _PersonView partial view I have to reference a property of the HomeViewModel i.e. Person object via #model.Employee.Name (in this scenario the submit is on the parent form (not within the partial view))
When I hit submit on the form (POST) in the controller i have to access the property of Employee "Name" via the following model.Employee.Name
This seems to work however notice the following variation scenario 2 (where I only pass to the partial the Employee object)
2.) Scenario 2
In this scenario I only want to send the Employee object to the partial view. Again the begin form and submit is on the parent form.
So from the parent form i have
#{Html.RenderPartial("_MasterView", #Model.Employee);}
and so within the partial view i reference the Name property of the Person object via #Employee.Name Now when I submit the form within the controller the Employee object is not available from the auto model binder. I can access the properties via formcollection but not from the model parameter
i.e.
[HttpPost]
public ActionResult Index(ModelViewModel model) {
**//model.Employee is null!**
return View();
}
Why? (is model.Employee null) I would like my partial view to only accept an object of type Person however after submitting from the parent page, the Employee property is null. On the partial view I am using the following on the #model line
#model MasterDetailSample.Models.Person
I would like the partial to only need a Person object to be sent to it, but I would like the submit on the main form. If i do it this way I can re-use the partial view in a few situations however IF i must send HomeViewModel i have significantly limited how I can use this partial view. So, again, I only want to use Person as the model with the partial view but I need to be able to access the properties when submitted from the parent view.
Can this be done? If yes how?
thx
You have a couple of options:
1) One I recommend -> Dont use partial views, instead use EditorFor and create an editor template for Person. With partial views the context is whatever model you pass into the view, this is why your example (1) works and (2) not. However with editor templates the parent context is taken into consideration with the html helpers and will generate the correct input names. Have a look at Darin Dimitrov's answer to a similar question.
2) Use your second example as is, but change the post action to look something like this:
[HttpPost]
public ActionResult Index(ModelViewModel model) {
TryUpdateModel(model.Employee);
**//model.Employee should now be filled!**
return View();
}
3) Use custom html helpers that accepts prefix for input, see this answer I posted a while back for example code. You could then use this inside your partial view.

Using two partial view in MVC3

In my asp.net mvc3 application i have created two partial views for two different action that is,
partialviewresult setcomment and
partialviewresult getcomment
i have created partial view using create a strongly type view and different scaffold template
for _setcomment i am using create template and for _getcomment i am using List template.
Now i want to call both _setcomment and _getcomment partial view in one view.
in my view file .cshtml
_setcomment -
#model <NAMESPACE>.<MODELNAME>
<some code>
_getcomment -
#model IEnumerable<<NAMESPACE>.<MODELNAME>>
<some code>
how can i call diiferent partial view in one view?
any suggestions?
There are different ways to do it.
If you already have the model class data in the Main view you can use like
In the main view call
#Html.Partial("PartialViewName1",model1)
#Html.Partial("PartialViewName1",model2)
If you do not have the model class data in the mail view then you can call the action on the controller and from there return the partial view.
#Html.Action("Controller","Action1")
#Html.Action("Controller","Action2")
In the Controller class
PartialResult Action1()
{
model = new ModelClass();
return PartialView(model);
}
Hope this helps.
The answer to your question is to use the following within a single view:
#{ Html.RenderAction("ActionName", "ControlerName"); }
#{ Html.RenderAction("ActionName2", "ControlerName2"); }
This would do what you are trying to achieve, however, I think there is a problem with design. What are you trying to achieve?

How to manipulate data in View using Asp.Net Mvc RC 2?

I have a table [Users] with the following columns:
INT SmallDateTime Bit Bit
[UserId], [BirthDate], [Gender], [Active]
Gender and Active are Bit that hold either 0 or 1.
I am displaying this data in a table on my View.
For the Gender I want to display
'Male' or 'Female', how and where do
I manipulate the 1's and 0's? Is it done in the repository where I fetch the data or in the View?
For the Active column I want to show
a checkBox that will AutoPostBack on selection change
and update the Active filed in the
Database. How is this done without
Ajax or jQuery?
For Question #1:
Use a DisplayTemplate. In View/Shared create a folder named DisplayTemplates. Then Add a partial View to this folder named Gender.ascx. Make sure it is not strongly typed.
the markup in this file will look like this:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Boolean>" %>
<span><%= Model ? "Male" : "Female" %></span>
Then in your Model you decorate the Gender property with a UIHint thusly:
[UIHint("Gender")]
public boolean Gender { get; set; }
In your View you make it use this template by using DisplayFor
<%= Html.DisplayFor(model => model.Gender) %>
If you cannot use the UIHint you can explicity name your template in DisplayFor
<%= Html.DisplayFor(model => model.Gender, "Gender") %>

Resources