Collections.Generic.Dictionary<TKey,Tvalue> model binding from Viewmodel to controller - asp.net-mvc-2

i have this problem :
when i try to post submit from a View to a httppost actionResult i get always a null value.
this is my code :
public class WhiteListViewModel
{
public string Badge { get; set; }
public IEnumerable<string> Selezioni { get; set; }
public IEnumerable<bool> Abilitazioni { get; set; }
}
public ActionResult WhiteList()
{
return View( "Whitelist", MasterPage, new WhitelistViewModel());
}
[HttpPost]
public ActionResult WhiteListp(IEnumerable<WhiteListViewModel> Whitelist )
{
bool[] abilitato = new bool[Whitelist.Single().Abilitazioni.Count()];
string[] selezione = new string[Whitelist.Single().Selezioni.Count()];
...
}
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/SiteR.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<_21112010.ViewModel.WhiteListViewModel>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
WhiteList
</asp:Content
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>WhiteList</h2>
<table style="width:100%;">
<thead>
</thead>
<tbody >
<%using ( Html.BeginForm( ) )
{%>
<% foreach ( var item in Model ){%>
<tr style="width:100%;">
<td >
<%: item.Badge%>
</td>
<%foreach ( var abit in item.Abilitazioni ){%>
<td >
<%: Html.CheckBoxFor(c=>abit/*, new { onchange = "this.form.submit();" } */ )%>
<%: Html.ValidationMessageFor(c => abit) %>
</td>
<% } %>
<%} %>
<td style=" width:1px;" >
<%: Html.HiddenFor(model=>item.Badge) %>
<% foreach (var sel in item.Selezioni) {%>
<%: Html.HiddenFor(c=>sel) %>
<%} %>
</td>
</tr> <%}%>
</tbody>
<tfoot>
</tfoot >
</table>
<input type="submit" value="Salva ed Esci" style = "background-color:Gray; color:#F6855E; font-weight:bold; border:1px solid black; height:20px;" />
<%:Html.ActionLink( "Aggiungi Badge", "AggiungiBadge")%>
<% } %>
</div>
</asp:Content>
where am I doing wrong?

The binding process will attempt to map the IEnumerable to the parameter Whitelist of the HttpPost action. However, I'm fairly sure that this is failing because the binding process has no information to tie the submitted fields to the expected parameter "Whitelist".
You have a few options:
Try using TryUpdateModel() in your action;
Creating a custom ModelBinder. This will allow you to interogate the submitted Model and build your IEnumerable prior to it being passed to the action parameter;
You could interogate the submitted fields using the FormCollection object from within the action. This is a little messy and not ideal;
Simplify your view.
Personally, I would look at the ModelBinder. If anything, this would give you a better insight into why the Model may not be binding to the action parameter.

Related

List all data from database using asp.net mvc 2.0

I'm new to asp.net mvc 2.0.I have a question about listing data from database using asp.net mvc.
Controller
public ActionResult ListEmployee() {
UserModels emp = new UserModels();
emp.EmployeeList = (List<tblEmployee_Employee>)Session["list"];
return View(emp);
}
Model
public class GetEmployee
{
public string name { get; set; }
public string sex { get; set; }
public string email { get; set; }
}
And I have the view page employee.aspx page but I do not know how to write code in this view page.
please help me to solve this problem.
Thanks,
In ASP.NET MVC views need to be strongly typed to the model you are passing to them. So in your case you are passing a UserModels instance to your view. Assuming you already have a master page and you want to display in a table the list of employees you might have something along the lines of:
<%# Page
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AppName.Models.UserModels>"
%>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<table>
<thead>
<tr>
<th>Name</th>
<th>Sex</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<% foreach (var employee in Model.EmployeeList) { %>
<tr>
<td><%= Html.Encode(employee.name) %></td>
<td><%= Html.Encode(employee.sex) %></td>
<td><%= Html.Encode(employee.email) %></td>
</tr>
<% } %>
</tbody>
</table>
</asp:Content>
or even better, define a reusable display template that will automaticall be rendered for each item of the EmployeeList collection property (~/Views/Shared/DisplayTemplates/GetEmployee.ascx):
<%# Control
Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<dynamic>"
%>
<tr>
<td><%= Html.DisplayFor(x => x.name) %></td>
<td><%= Html.DisplayFor(x => x.sex) %></td>
<td><%= Html.DisplayFor(x => x.email) %></td>
</tr>
and then in your main view simply reference this template:
<%# Page
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AppName.Models.UserModels>"
%>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<table>
<thead>
<tr>
<th>Name</th>
<th>Sex</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<%= Html.EditorFor(x => x.EmployeeList)
</tbody>
</table>
</asp:Content>
Now you no longer need any foreach loops (as ASP.NET MVC will automatically render the display template if the property is a collection property following standard naming conventions) and also you have a reusable display template for your model.

MVC : Model does not submit for multiple forms

This is related to ASP.Net MVC 2
I have a model (MoviesForAll) bound to my view and this model has a collection of class ICollection. I want my user to buy single ticket at a time by clicking submit button 'Buy this ticket' so I have placed a button besides each row representing the ticket details. This lead to following sequence
<%#Page Title="title" Language="C#" MasterPageFile="~/Views/Shared/MyMaster.Master"
Inherits="System.Web.Mvc.ViewPage<OnlineBooking.Movies.MoviesForAll>">
<Table>
<% for(i=0; i<Model.Tickets.count; i++)
{ %>
<tr>
<% using (Html.BeginForm(myaction(), FormMethod.Post, new {id="myform"}))
{ %>
<td>
<%= Model.tickets[i].ticketID %>
<%= Html.HiddenFor(m=>m.tickets[i].ticketID) %>
</td>
<td>
<%= Model.tickets[i].seatNo %>
<%= Html.HiddenFor(m=>m.tickets[i].seatNo) %>
</td>
...
...
<td>
<input type="submit" value="buy this ticket" runat="server">
</td>
<% } %>
</tr>
<% } %>
</table>
This creates a form for each row of tickets having single submit button in that form.
The problem is, when I submit first row (having index 0) by clicking the button, it gets submitted properly and I can see the values in controller method. But no other row gets through to controller even if I have used hidden fields to bind it.
Am I missing anything here specific to index or something?
Thanks in advance..
I would suggest having one form for all the rows, then on each row use the button element instead of an input as follows:
<button type="submit" value="<%= Model.tickets[i].ticketID %>" name="buyticket">Buy this ticket</button>
You should have a parameter on your controller action called buyticket and that should have the ticket id of the button which was clicked
How about the following:
<table>
<% for(i = 0; i < Model.Tickets.Count; i++) { %>
<tr>
<% using (Html.BeginForm("myaction", FormMethod.Post, new { id = "myform" })) { %>
<td>
<%= Model.tickets[i].ticketID %>
</td>
<td>
<%= Model.tickets[i].seatNo %>
</td>
...
...
<td>
<%= Html.Hidden("TicketId", Model.tickets[i].ticketID) %>
<%= Html.Hidden("SeatNumber", Model.tickets[i].seatNo) %>
<input type="submit" value="buy this ticket" />
</td>
<% } %>
</tr>
<% } %>
</table>
and then:
public class TicketToPurchaseViewModel
{
public int TicketId { get; set; }
public int SeatNumber { get; set; }
}
and the action:
[HttpPost]
public ActionResult myaction(TicketToPurchaseViewModel ticket)
{
...
}
Remark: notice that I have removed the runat="server" attribute from the submit button as well because this is something that you definitely don't want to see in an ASP.NET MVC application.

DisplayName metadata does not show up on view

How will I show the correct DsiplayName on my view considering the following model.
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Project.Models.RegisterViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm())
{%>
<table>
<tr>
<td class="label">
<%: Html.LabelFor(model => model.User.UserPrimaryEmail)%>
</td>
<td class="field">
<%: Html.TextBoxFor(model => model.User.UserPrimaryEmail)%>
</td>
<td class="field-error">
<div class="field-error-msg">
<%: Html.ValidationMessageFor(model => model.User.UserPrimaryEmail)%>
</div>
</td>
</tr>
</table>
</asp:Content>
public class RegisterViewModel
{
public User User { get; set; }
}
[MetadataType(typeof(UserMetaData))]
public partial class User : UserBase
{
//Inherits from Generated Class UserBase
//to set default values here for the constructor
// Not used except as a source of metadata
public class UserMetaData
{
[Required]
[DisplayName("Email Login")]
[DataType(DataType.EmailAddress)]
[Email(ErrorMessage = "Invalid Email")]
public string UserPrimaryEmail { get; set; }
}
}
The form does not display "Email Login" but "UserPrimaryEmail"
You View is strongly typed to Project.Models.RegisterViewModel, however you are adding your Data Annotations to the User Object.
Generally you would have:
public class RegisterViewModel
{
[Required]
[DisplayName("Email Login")]
[DataType(DataType.EmailAddress)]
[Email(ErrorMessage = "Invalid Email")]
public String Email { get; set; }
.....
other properties
}

DisplayName metadata does not show up on view [duplicate]

How will I show the correct DsiplayName on my view considering the following model.
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Project.Models.RegisterViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm())
{%>
<table>
<tr>
<td class="label">
<%: Html.LabelFor(model => model.User.UserPrimaryEmail)%>
</td>
<td class="field">
<%: Html.TextBoxFor(model => model.User.UserPrimaryEmail)%>
</td>
<td class="field-error">
<div class="field-error-msg">
<%: Html.ValidationMessageFor(model => model.User.UserPrimaryEmail)%>
</div>
</td>
</tr>
</table>
</asp:Content>
public class RegisterViewModel
{
public User User { get; set; }
}
[MetadataType(typeof(UserMetaData))]
public partial class User : UserBase
{
//Inherits from Generated Class UserBase
//to set default values here for the constructor
// Not used except as a source of metadata
public class UserMetaData
{
[Required]
[DisplayName("Email Login")]
[DataType(DataType.EmailAddress)]
[Email(ErrorMessage = "Invalid Email")]
public string UserPrimaryEmail { get; set; }
}
}
The form does not display "Email Login" but "UserPrimaryEmail"
You View is strongly typed to Project.Models.RegisterViewModel, however you are adding your Data Annotations to the User Object.
Generally you would have:
public class RegisterViewModel
{
[Required]
[DisplayName("Email Login")]
[DataType(DataType.EmailAddress)]
[Email(ErrorMessage = "Invalid Email")]
public String Email { get; set; }
.....
other properties
}

Having difficulty with ModelBinding and Dictionary, ASP.NET MVC 2.0

Using the following model, I expect that when the Submit button is hit, the Edit Method to Fire, and the model parameter to have the adjusted values. But it keeps returning an instance of the class with all null values. It is as if no model binding ever happens.
class Trait
{
string Name { get; set; }
// other properties
}
class DesignViewModel
{
Dictionary<Trait, int> Allocation { get; set; }
}
Controller
public ActionResult Create()
{
var model = new DesignViewModel();
// retrieve traits from database
foreach(var trait in Repository.Traits)
model.Allocation.Add(trait, 0);
return View(model);
}
[HttpPost]
public ActionResult Edit(DesignViewModel model)
{
// nothing works yet, so I don't have a lot of code here...
}
HTML
Top Level Page
<%# Page Title="" Language="C#" MasterPageFile="~/Areas/Setup/Views/Shared/Setup.master"
Inherits="System.Web.Mvc.ViewPage<OtherModel>" %>
<% Html.RenderAction("Design", "Test"); %>
Partial View
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DesignViewModel>" %>
<% using (Html.BeginForm("Edit", "Test", FormMethod.Post ) ) {%>
<div id="eq">
<% foreach (var trait in Model.Allocations) { %>
<div style="margin: 15px;">
<%: trait.Key.Name %>
<br />
<span class="slider"></span>
<%: Html.TextBox(trait.Key.Name, trait.Value, new { #class = "spent" , #readonly = "readonly" })%>
</div>
<% } %>
</div>
<p>
<input type="submit" value="Submit" />
</p>
<% } %>
You need to add [HttpPost] to your Edit method for it to be fired during POST requests.