List item inside model contains null on post - c#

I have a model class. Inside that, I have a class and a list which is that type.
public class ItemSetupModel
{
public class UPC
{
public int ItemNumberForUPC { get; set; }
public string GCOwner { get; set; }
public string GCFeeItem { get; set; }
public string GCBranded { get; set; }
public string query { get; set; }
}
public List<UPC> lstUPC { get; set; }
public UPC upc;
public ItemSetupModel()
{
this.upc = new UPC();
this.lstUPC = new List<UPC>();
this.lstUPC.Add(this.upc);
}
}
cshtml is as below :
#model PricingUpdates.Models.ItemSetupModel
#using (Html.BeginForm())
{
#for (int i = 0; i < Model.lstUPC.Count; i++)
{
#Html.Label("ItemNumberForUPC", "ItemNumber")
#Html.TextBoxFor(m => m.lstUPC[i].ItemNumberForUPC, new { #class = "form-control", Name = "UPCUpdate" + i })
}
}
Whenever I am posting the values, the action result model will never contain the values entered by me in the textbox. It will always show null values for the list.

Related

How to pass List model to controller from view http post

I have a CategoryModel that contains a list item for the ItemModel as well as some other strings etc.
I'm trying to pass the list from the view to the controller. The model on the view is the ABCModel which contains a list of 'Categories' of type CategoryModel. On the view I'm only looking to post the 'active' Category back to be saved.
When I do this the active category is passed with details added from the form but the list of items is null.
.cs Models
namespace Company.Models
{
public class ABCModel
{
public IList<CategoryModel> Categories;
public SummaryModel Summary;
}
}
namespace Company.Models
{
public class CategoryModel
{
public string Label { get; set; }
public bool Active { get; set; }
public decimal Amount { get; set; }
public string Frequency { get; set; }
public string Type { get; set; }
public List<ItemModel> Items;
}
)
namespace Company.Models
{
public class ItemModel
{
public string Label { get; set; }
public string Explanation { get; set; }
public string Amount { get; set; }
public string Frequency { get; set; }
public bool Flag { get; set; }
public string Note { get; set; }
}
}
Controller
[HttpPost]
public ActionResult SaveItems([FromForm] CategoryModel activeCategoryModel, [FromForm] List<ItemModel> items, [FromQuery] string activecategory, [FromQuery] string nextcategory)
{
...
}
View
#model ABCModel
#{ CategoryModel nextCategory = null; }
#{ CategoryModel activeCategoryModel = null; }
#if (Model.Categories.Any())
{
#for (var i = 0; i < Model.Categories.Count; i++)
{
Company.Models.CategoryModel category = Model.Categories[i];
#if (category.Active)
{
activeCategoryModel = category;
if ((i + 1 < Model.Categories.Count) && (Model.Categories[i + 1] != null))
{
nextCategory = Model.Categories[i + 1];
}
}
}
}
<form id="ABC-form" class="needs-validation" novalidate="" asp-action="SaveItems" asp-controller="Home" method="post">
#if (activeCategoryModel != null)
{
<input asp-for="#activeCategoryModel.Label" type="hidden" />
<input asp-for="#activeCategoryModel.Active" type="hidden" />
<input asp-for="#activeCategoryModel.Amount" type="hidden" />
<input asp-for="#activeCategoryModel.Frequency" type="hidden" />
<input asp-for="#activeCategoryModel.Type" type="hidden" />
#if (activeCategoryModel.Items.Any())
{
#for (var i = 0; i < activeCategoryModel.Items.Count; i++)
{
#Html.HiddenFor(x => activeCategoryModel.Items[i].Label)
#Html.HiddenFor(x => activeCategoryModel.Items[i].Explanation)
#Html.TextBoxFor(x => items[i].Amount, new { #class = "form-control" })
}
}
}
<button id="continue" type="submit" asp-action="SaveItems" asp-route-activecategory="#activeCategoryModel.Label" asp-route-nextcategory="#(nextCategory != null ? nextCategory?.Label : null)">Continue</button>
</form>
I had been including IFormCollection as a parameter within the SaveItems on the controller and this showed that the items are being passed in the format I was thinking would work but the model only shows the values entered and the list of items is null.
How can I populate the list of items on the active category model from the view?
Items in CategoryModel should be a property not a filed,so your CategoryModel should be like below:
public class CategoryModel
{
public string Label { get; set; }
public bool Active { get; set; }
public decimal Amount { get; set; }
public string Frequency { get; set; }
public string Type { get; set; }
public List<ItemModel> Items { get; set; }
}

How can I bind CountryNames in DropDownListFor

I'm using mvc4. How can I Bind CuntryName and its values in DropdownList
Country?
public class Country
{
public int Cnt_Id { get; set; }
public string Cnt_Name { get; set; }
}
This is my private class
public class HybridEmployee
{
public IEnumerable<Country> GetCount { get; set; }
}
Controller
public ActionResult GetCountry()
{
var x = ObjRepo.GetCountry();
hybrid.GetCount = x;
return View(hybrid);
}
Index.cshtml
#model Mvc_Application.Models.HybridEmployee
#using Mvc_Application.Models
#using (Html.BeginForm("SaveEmp", "Home", FormMethod.Post))
{
#Html.DropDownListFor(x=>x.GetCount.FirstOrDefault().Cnt_Id),new SelectList(Model.GetCount,"","");
}
We can have two approaches as shown below:
Using a ViewBag containing the data for dropdown list.
Model file:
public class State
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int CountryID { get; set; }
}
In .cs file:
ViewBag.Countries = countryService.All().Select(x => new SelectListItem() { Text = x.Name, Value = x.Id.ToString() }).ToList();
In .cshtml file:
#Html.DropDownListFor(x => x.CountryID, ViewBag.Countries as IEnumerable<SelectListItem>, "Select Country", new { #class = "form-control" })
Using a Model's property containing the data for dropdown list.
Model file:
public class State
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int CountryID { get; set; }
public List<SelectListItem> Countries { get; set; }
}
In .cs file:
model.Countries = countryService.All().Select(x => new SelectListItem() { Text = x.Name, Value = x.Id.ToString() }).ToList();
In .cshtml file:
#Html.DropDownListFor(x => x.CountryID, Model.Countries, "Select Country", new { #class = "form-control" })
This expression totally doesn't makes sense:
#Html.DropDownListFor(x=>x.GetCount.FirstOrDefault().Cnt_Id),new SelectList(Model.GetCount,"","");
The first argument of DropDownListFor helper (Expression<Func<TModel, TProperty>> expression) doesn't use LINQ expression, it is model binding expression - you must use a property to hold selected value instead. The drop down list binding should be used like this:
Model
public class Country
{
public int Cnt_Id { get; set; }
public string Cnt_Name { get; set; }
public int SelectedCountry { get; set; } // additional property to get selected value
}
View
#Html.DropDownListFor(x => x.SelectedCountry, new SelectList(Model.GetCount, "Cnt_Id", "Cnt_Value"), null)

BeginCollectionItem can not bind partial values

I´m doing Editing a variable length list, ASP.NET MVC 2-style tutorial, but I can´t bind values of my ViewModel to my Create View
Model:
public class WebPages
{
[Key]
public int WebPagesId { get; set; }
public String DomainName { get; set; }
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime DomainStart { get; set; }
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime DomainExp { get; set; }
public String DomainEmails { get; set; }
public String DomainUsers { get; set; }
public String DomainPasswords { get; set; }
}
}
ViewModel:
public class WebPagesViewModel
{
[Key]
public int Id { get; set; }
public String DomainName { get; set; }
public class Domain
{
public String DomainEmails { get; set; }
public String DomainUsers { get; set; }
public String DomainPasswords { get; set; }
}
public List<Domain> Domains { get; set; }
}
}
Create GetController
public ActionResult Create(WebPages model)
{
var ejemdata = new List<WebPagesViewModel.Domain>
{
new WebPagesViewModel.Domain
{
DomainEmails = "email#gmail.com",
DomainUsers = "Testuser",
DomainPasswords = "testpassword"
}
};
var vm = new WebPagesViewModel
{
Clients = new SelectList(db.ClientsList, "ClientsId", "ClientsName"),
Domains = ejemdata
};
return View(vm);
}
Create View:
#foreach (var item in Model.Domains)
{
{ Html.RenderPartial("_WebPagesPartial", item);}
}
Partial:
#using xxx.Models.ViewModels
#model WebPagesViewModel.Domain
#using HtmlHelpers.BeginCollectionItem
<h2>Partial View</h2>
<div>
#using (Html.BeginCollectionItem("Domains"))
{
Html.EditorFor(x => x.DomainPasswords);
Html.EditorFor(x => x.DomainUsers);
Html.EditorFor(x => x.DomainEmails);
}
I use breakpoint debug, and controller gets values from my ejemdata and it pass to my create view into foreach
Receiving data in View photo
So when the page loads it only loads label from partial but no display anything that is in BeginCollectionItem method and I get this on HTML
HTML:
<input type="hidden" name="Domains.index" autocomplete="off" value="28f4e8e7-cde3-44fe-a739-b4c8acb15ec2">
You use of
Html.EditorFor(x => x.DomainPasswords);
just calls the method but does not output its result. You need to change it to
#Html.EditorFor(x => x.DomainPasswords)
(and ditto for the other 2 HtmlHelpers)

checkboxes matrix with MVC4

I need to disply a matrix of checkboxes like the one in here
asp.net mvc checkbox/radiobutton matrix model-binding
well, instead of subquestions I haves roles and types, so here is my code:
my models:
public class role
{
public role()
{
types = new List<role_type>();
}
[Key]
public int role_id { get; set; }
public string role_name { get; set; }
public int role_value { get; set; }
public Boolean IsSelected { get; set; }
public IList<role_type> types { get; set; }
}
public class role_type
{
public int Id { get; set; }
public Boolean IsSelected { get; set; }
public string type { get; set; }
}
My view Model:
public class roleViewModel
{
public roleViewModel()
{
Roles = new List<role>();
}
public int ID { get; set; }
public IList<role> Roles { get; set; }
}
My controller:
public class roleviewmodelController : Controller
{
private Context db = new Context();
[HttpGet]
public ActionResult Index(roleViewModel rvm)
{
return View(rvm);
}
}
and my view
#model UsersManagement.Models.roleViewModel
#{
ViewBag.Title = "Index";
}
#for (var i = 0; i < Model.Roles.Count(); i++)
{
<div id="roles">
<ul>
#for (var j = 0; j <4; j++)
{
<li>#Html.CheckBoxFor(m=>Model.Roles[i].types[j].IsSelected)</li>
}
</ul>
</div>
}
this doesn't display anything, what am i missing?
the types should be like (Edit, Delete, Read, Create) and the roles like: manage companies, manage invoices, etc...
PS: My final goal is to customise the authorization system but this is another issue.

MVC Form Model returning null for complex object collection

I have a table with 4 rows (mobile, work, cell, email), and 5+ columns. When I POST I don't get back any data. Can I refactor the code to make it work?
Model:
public class ContactInfoViewModel {
public string HomePhone { get; set; }
public ICollection<bool> HomePhoneChecks { get; set; }
public string MobilePhone { get; set; }
public ICollection<bool> MobilePhoneChecks { get; set; }
public string WorkPhone { get; set; }
public ICollection<bool> WorkPhoneChecks { get; set; }
public string Email { get; set; }
public ICollection<bool> EmailChecks { get; set; }
public string Email2 { get; set; }
public IEnumerable<RowData> Rows { get; set; }
public IEnumerable<RowData> GetAllRows() {
return new List<RowData> {
new RowData { Name = "HomePhone", Label = "Home Phone", Heading = HomePhone, Columns = HomePhoneChecks},
new RowData { Name = "MobilePhone", Label = "Mobile Phone", Heading = MobilePhone, Columns = MobilePhoneChecks},
new RowData { Name = "WorkPhone", Label = "Work Phone", Heading = WorkPhone, Columns = WorkPhoneChecks},
new RowData { Name = "Email", Label = "Email", Heading = Email, Columns = EmailChecks},
};
}
public class RowData {
public string Name { get; set; }
public string Label { get; set; }
public string Heading { get; set; }
public ICollection<bool> Columns { get; set; }
}
View:
#foreach (var row in Model.ContactInfo.GetAllRows()) {
<tr>
<td class="boxRows noMargin">
<div>
<div class="boxLabel">#row.Label</div>
<div class="boxValue">#Html.TextBoxFor(m => row.Heading)</div>
</div>
</td>
#foreach (var item in row.Columns) {
<td>#Html.CheckBoxFor(m => item)</td>
}
</tr>
}
I would change your model collections to use List properties that are capable of model binding.
As an example:
public List<RowData> AllRows { get; set; }
Then change your loop to this which will be picked up by the model binder.
#for (int i = 0; i < Model.AllRows.Count; i++)
{
.....
#Html.EditorFor(model => Model.AllRows[i].Heading)
.....
}
They will then be posted back to the server.
For more info on it see here:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

Categories

Resources