MVC4: View appears to be maintaining state independently of the controller - c#

I have a dropdown (customer) and list of checkboxes (sales orders), dependent upon the currently selected customer. I would expect the checkboxes to clear if I select a new customer, but they are maintained from one to the other, despite the model being cleared in the postback.
I'm not a seasoned MVC developer, but I'm not sure why this should be. When debugging the ViewModel I'm sending back to the view, it is showing IsSelected = false for all the checkboxes, yet in the View, they are selected. What am I doing wrong? (Thanks in advance)
View Model:
namespace MvcTest1.Models
{
public class Customer
{
public int CustomerID { get; set; }
public string Name { get; set; }
}
public class SalesOrder
{
public int SalesOrderID { get; set; }
public string Reference { get; set; }
public bool IsSelected { get; set; }
}
public class SalesOrderPageViewModel
{
public List<Customer> Customers { get; set; }
public int SelectedCustomerID { get; set; }
public List<SalesOrder> SalesOrders { get; set; }
}
}
Controller:
namespace MvcTest1.Controllers
{
public class SalesOrderPageController : Controller
{
[HttpGet]
public ActionResult Index()
{
SalesOrderPageViewModel viewModel = BuildViewModel(1);
return View(viewModel);
}
[HttpPost]
public ActionResult Index(SalesOrderPageViewModel viewModelInput)
{
SalesOrderPageViewModel viewModel = BuildViewModel(viewModelInput.SelectedCustomerID);
return View(viewModel);
}
public SalesOrderPageViewModel BuildViewModel(int customerID)
{
SalesOrderPageViewModel viewModel = new SalesOrderPageViewModel
{
Customers = new List<Customer>
{
new Customer { CustomerID = 1, Name = "Alan" },
new Customer { CustomerID = 2, Name = "Bob" },
new Customer { CustomerID = 3, Name = "Charlie" }
}
};
viewModel.SelectedCustomerID = customerID;
if (customerID == 1)
{
viewModel.SalesOrders = new List<SalesOrder>
{
new SalesOrder { SalesOrderID = 11, Reference = "AA11" },
new SalesOrder { SalesOrderID = 12, Reference = "AA22" },
new SalesOrder { SalesOrderID = 13, Reference = "AA33" }
};
}
if (customerID == 2)
{
viewModel.SalesOrders = new List<SalesOrder>
{
new SalesOrder { SalesOrderID = 21, Reference = "BB11" },
new SalesOrder { SalesOrderID = 22, Reference = "BB22" },
new SalesOrder { SalesOrderID = 23, Reference = "BB33" }
};
}
if (customerID == 3)
{
viewModel.SalesOrders = new List<SalesOrder>
{
new SalesOrder { SalesOrderID = 31, Reference = "CC11" },
new SalesOrder { SalesOrderID = 32, Reference = "CC22" },
new SalesOrder { SalesOrderID = 33, Reference = "CC33" }
};
}
return viewModel;
}
}
}
View:
#model MvcTest1.Models.SalesOrderPageViewModel
#{
ViewBag.Title = "SalesOrderPage";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>SalesOrderPage</h2>
<br /><br />
#using (Html.BeginForm())
{
#Html.DropDownListFor(model =>
model.SelectedCustomerID,
new SelectList(
Model.Customers,
"CustomerID",
"Name",
Model.SelectedCustomerID
),
new { id = "customerSelect" }
);
<script type="text/javascript">
$(function () {
$('#customerSelect').change(function () {
this.form.submit();
});
})
</script>
<br /><br />
for (int i = 0; i < Model.SalesOrders.Count(); i++)
{
#Html.DisplayFor(m => Model.SalesOrders[i].Reference)
#Html.CheckBoxFor(m =>
m.SalesOrders[i].IsSelected
)
<br />
}
}

Looks like Ryan is correct about ModelState.Clear(). Here's an article explaining why it is necessary:
http://patrickdesjardins.com/blog/modelstate-clear-is-required-to-display-back-your-model-object

Related

Store Data In a Generic List and use Linq

Model.cs contains the Data of the User which is stored in a list type Now We have to fetch all those students whose age is more than 25.
public class Model
{
public int Age { get; set; }
public string Name { get; set; }
public string Sports { get; set; }
List<Model> objModels = new List<Model>() {
new Model { Name = "Manish", Age = 27, Sports = "Cricket" },
new Model { Name = "Rajan", Age = 25, Sports = "FootBall" },
new Model { Name = "Prashant", Age = 25, Sports = "Kabaddi" },
new Model { Name = "Garima", Age = 24, Sports = "Ludo" },
new Model { Name = "Neha", Age = 25, Sports = "Carom" }
};
}
ModelController.cs
public class ModelController : Controller
{
// GET: Model
public ActionResult Index()
{
List<Model> objModel = new List<Model>();
var query = from models in objModel select models;
foreach(var item in query.ToList())
{
objModel.Add(
new Model
{
Name = item.Name.ToString(),
Age = int.Parse(item.Age.ToString()),
Sports = item.Sports.ToString()
});
}
return View(objModel);
}
}
But The object is always empty because it is not fetching the data from the model class.
Hi have you tried to do:
public class Model
{
public int Age { get; set; }
public string Name { get; set; }
public string Sports { get; set; }
public List<Model> Models
{
get
{
return objModels;
}
set {
Model = value;
}
}
List<Model> objModels = new List<Model>() {
new Model { Name = "Manish", Age = 27, Sports = "Cricket" },
new Model { Name = "Rajan", Age = 25, Sports = "FootBall" },
new Model { Name = "Prashant", Age = 25, Sports = "Kabaddi" },
new Model { Name = "Garima", Age = 24, Sports = "Ludo" },
new Model { Name = "Neha", Age = 25, Sports = "Carom" }
};
}
And then use it in your controller as :
List<Model> newModelList=new List<Model>();
Model objModel = Model;
var query = from models in objModel.Models where models.age<25 select models;
foreach (var item in query.ToList())
{
newModelList.Add(
new Model
{
Name = item.Name.ToString(),
Age = int.Parse(item.Age.ToString()),
Sports = item.Sports.ToString()
});
}
return View(newModelList);
DBCOntext.cs - a new class for Handeling The Data.
public class DBContext
{
List<Model> objModel = new List<Model>();
public List<Model> GetData()
{
objModel.Add(new Model
{
Name = "Manish",Age = 27,Sports = "Cricket"
});
objModel.Add(new Model
{
Name = "Rajan",Age = 25,Sports = "FootBall"
});
objModel.Add(new Model
{
Name = "Prashant", Age = 25,Sports = "Kabaddi"
});
objModel.Add(new Model
{
Name = "Garima", Age = 24,Sports = "Ludo"
});
objModel.Add(new Model
{
Name = "Neha",Age = 25,Sports = "Carom"
});
return objModel;
}
}
And Controller class to access all the DBContext Data which can be used to send the data to the View
List<Model> objModel = new List<Model>();
// GET: Model
public ActionResult Index()
{
DBContext db = new DBContext();
var query = from models in db.GetData() where models.Age>25 orderby models.Age select models;
foreach (var item in query.ToList())
{
objModel.Add(
new Model
{
Name = item.Name.ToString(),
Age = int.Parse(item.Age.ToString()),
Sports = item.Sports.ToString()
});
}
return View(objModel);
}

ASP.NET MVC PresentationModel Binding to ComboBoxes stays empty

Hello I'm learning to program MVC style in ASP.NET. I'm trying to populate a combobox with my PresentationModel, somehow it stays empty.
I'm using the ASP tag-helpers:
View (Index.cshtml)
#model Week3_oef2_ITPro.PresentationModel.PMRegistration
<h2>New Registration</h2>
<h4>Registration</h4>
<form asp-controller="Register" asp-action="" method="post">
<table>
<tr>
<td>Organization</td>
<td class="form-group">
<select asp-for="OrgId.Id" asp-items="#Model.Org" class="form-group" />
</td>
</tr>
<tr><td><input type="submit" /></td></tr>
</table>
</form>
PresentationModel (PMRegistration.cs)
public class PMRegistration
{
public Organization OrgId { get; set; }
public List<SelectListItem> Org { get; set; }
}
Model (Organization.cs)
public class Organization
{
public int Id { get; set; }
public string Name { get; set; }
}
Data (Where all the objects are initialized)
public class Data
{
private static List<Session> sessions = new List<Session>();
private static List<Organization> organizations = new List<Organization>();
private static List<Device> devices = new List<Device>();
static Data()
{
organizations.Add(new Organization() { Id = 1, Name = "Howest" });
organizations.Add(new Organization() { Id = 2, Name = "Vives" });
organizations.Add(new Organization() { Id = 3, Name = "HoGent" });
organizations.Add(new Organization() { Id = 4, Name = "HoLimburg" });
organizations.Add(new Organization() { Id = 4, Name = "De blauwe smurfen" });
devices.Add(new Device() { Id = 1, Name = "Laptop" });
devices.Add(new Device() { Id = 2, Name = "Tablet" });
devices.Add(new Device() { Id = 3, Name = "Apple Watch" });
}
public static List<Device> GetDevices()
{
return devices;
}
public static List<Organization> GetOrganizations()
{
return organizations;
}
}
Controller (RegisterController.cs)
public class RegisterController : Controller
{
// GET: /<controller>/
[HttpGet]
public IActionResult Index()
{
PMRegistration pm = new PMRegistration();
pm.OrgId = new Organization();
pm.Org = ConverToListItems(Data.GetOrganizations());
return View(pm);
}
#region methodes
private List<SelectListItem> ConverToListItems(List<Organization> data)
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (var item in data)
{
items.Add(new SelectListItem() { Text = item.Name, Value = item.Id.ToString() });
}
return items;
}
#endregion
}
Your HTML markup for the SELECT element is wrong. The SELECT element requires a closing tag.
It should be
<select asp-for="OrgId.Id" asp-items="#Model.Org" class="form-group"></select>

Recursive call of #helper method in ASP.NET MVC Razor, code inside the #helper method is skipped during execution

I am trying to populate the nested Ordered list using #functions & #helper features in ASP.NET MVC Razor.
I am successful in creating nested list using #functions, but when I tried to the same with #helper method execution is not going inside the helper method.
Model:
public class NavigationMenuModels
{
public int ID { get; set; }
public int? ParentID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<NavigationMenuModels> SubNavigationMenu { get; set; }
}
View Model:
public class NavigationMenuViewModel
{
public NavigationMenuViewModel()
{
ListMenu = new List<NavigationMenuModels>();
}
public string ListName { get; set; }
public List<NavigationMenuModels> ListMenu { get; set; }
}
Controller:
public ActionResult NavigationMenu()
{
//Menu
NavigationMenuModels objMenu = new NavigationMenuModels() { ID = 1, ParentID = null, Name = "Menu", Description = "Menu" };
//Menu Items
List<NavigationMenuModels> objMenuItems = new List<NavigationMenuModels>();
objMenuItems.Add(new NavigationMenuModels() { ID = 1, ParentID = 1, Name = "Home", Description = "Home" });
objMenuItems.Add(new NavigationMenuModels() { ID = 2, ParentID = 1, Name = "About", Description = "About" });
objMenuItems.Add(new NavigationMenuModels() { ID = 3, ParentID = 1, Name = "Help", Description = "Help" });
objMenuItems.Add(new NavigationMenuModels() { ID = 4, ParentID = 1, Name = "Contact", Description = "Contact" });
objMenu.SubNavigationMenu = objMenuItems;
//Admin
NavigationMenuModels objAdmin = new NavigationMenuModels() { ID = 2, ParentID = null, Name = "Admin", Description = "Admin" };
//Admin Items
List<NavigationMenuModels> objAdminItems = new List<NavigationMenuModels>();
objAdminItems.Add(new NavigationMenuModels() { ID = 1, ParentID=2, Name = "User Permissions", Description = "User Permissions" });
objAdminItems.Add(new NavigationMenuModels() { ID = 2, ParentID=2, Name = "Security", Description = "Security" });
objAdmin.SubNavigationMenu = objAdminItems;
//Account
NavigationMenuModels objAccount = new NavigationMenuModels() { ID = 3, ParentID = null, Name = "Account", Description = "Account" };
//Account Items
List<NavigationMenuModels> objAccountItems = new List<NavigationMenuModels>();
objAccountItems = null;
objAccount.SubNavigationMenu = objAccountItems;
NavigationMenuViewModel objNavigationMenu = new NavigationMenuViewModel();
objNavigationMenu.ListName = "Master Navigation";
objNavigationMenu.ListMenu.Add(objMenu);
objNavigationMenu.ListMenu.Add(objAdmin);
objNavigationMenu.ListMenu.Add(objAccount);
return View(objNavigationMenu);
}
CSHTML:
#using LearnAngularJs_App1.Models
#using System.Text
#model LearnAngularJs_App1.Models.NavigationMenuViewModel
#{
ViewBag.Title = "NavigationMenu";
}
#functions
{
public static HtmlString GetNestedListHtml(NavigationMenuViewModel Crudeinput)
{
StringBuilder sb = new StringBuilder();
var orderedList = new TagBuilder("ol");
foreach (NavigationMenuModels NavMenu in Crudeinput.ListMenu)
{
var listItem = new TagBuilder("li");
listItem.SetInnerText(NavMenu.Name);
sb.AppendLine(listItem.ToString(TagRenderMode.Normal));
if (NavMenu.SubNavigationMenu != null)
{
if (NavMenu.SubNavigationMenu.Count > 0)
{
sb.AppendLine(BuildNestedList(NavMenu.SubNavigationMenu));
}
}
}
orderedList.InnerHtml = sb.ToString();
return new HtmlString(orderedList.ToString(TagRenderMode.Normal));
}
public static string BuildNestedList(List<NavigationMenuModels> SubMenuList)
{
var sb = new StringBuilder();
var orderedList = new TagBuilder("ol");
if (SubMenuList.Count > 0)
{
foreach (NavigationMenuModels SubNavgationMenuitem in SubMenuList)
{
var listItem = new TagBuilder("li");
listItem.SetInnerText(SubNavgationMenuitem.Name);
sb.AppendLine(listItem.ToString(TagRenderMode.Normal));
if (SubNavgationMenuitem.SubNavigationMenu != null)
{
if (SubNavgationMenuitem.SubNavigationMenu.Count > 0)
{
sb.AppendLine(BuildNestedList(SubNavgationMenuitem.SubNavigationMenu));
}
}
}
}
orderedList.InnerHtml = sb.ToString();
return orderedList.ToString(TagRenderMode.Normal);
}
}
#helper BuildNestedListHelper(List<NavigationMenuModels> Crudeinput)
{
if (Crudeinput.Any())
{
<ol>
#foreach (NavigationMenuModels NavMenu in Crudeinput)
{
<li>
#NavMenu.Name
#if (NavMenu.SubNavigationMenu != null)
{
BuildNestedListHelper(NavMenu.SubNavigationMenu);
}
</li>
}
</ol>
}
}
<h2>NavigationMenu</h2>
<div>
<div><span>Bind Navigation Menu using razor ##funtions</span></div>
<div>
#GetNestedListHtml(Model)
</div>
</div>
<div>
<div><span>Bind Navigation Menu using razor ##helper</span></div>
<div>
#BuildNestedListHelper(Model.ListMenu)
</div>
</div>
When a recursive call to the helper method is made execution is going to the method, but the execution is skipped.
just add "#" in front of the method when recursive call.

Fill Dropdownlist with values from database - MVC4

i have a table in my database which i select all rows to fill it in my dropdownlist in my view.
i canĀ“t understand how can i fill the values in there.
someone can give me a hand?
My code:
Model:
public class MyList
{
public int id { get; set; }
public string name{ get; set; }
}
public class Empresas
{
public static IEnumerable<MyList> Getmyinformation()
{
var list = new List<MyList>();
string connection = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
using (var con = new SqlConnection(connection))
{
con.Open();
using (var command = new SqlCommand("SELECT * FROM mytable", con))
{
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string Name= reader[1] as string;
list.Add(new MyList() { name= Name});
}
}
con.Close();
}
return list;
}
}
public class DefaultConnection : DbContext
{
public DbSet<MyList> lat { get; set; }
}
Controller:
private DefaultConnection db = new DefaultConnection();
public ActionResult Add()
{
return View(db.lat.ToList());
}
View:
#Html.DropDownListFor("-- Select --", new SelectList("")) <=== ???? i dont know
Simply in controller type:
ViewBag.CategoryList = new SelectList(db.Categories.ToList(), "Id", "Name");
And in view write:
#Html.DropDownListFor(model => model.CategoryId, ViewBag.CategoryList as IEnumerable<SelectListItem>, new { #class = "anyclass" })
In my practice I create dropdownlist as follow:
first I create view model
public class MyObj
{
public int id { get; set; }
public string name{ get; set; }
}
// viewmodel
public class MyviewModel
{
public IQuerable<MyObj> MyObjs{get;set;}
public Other Other{get;set;}
}
then I pass this model from controller to view
private DefaultConnection db = new DefaultConnection();
public ActionResult Index()
{
var drop = new MyviewModel
{
MyObjs = db.MyObjs,// selecting table...
Other = new Other
}
return View(drop);
}
in Controller
#Html.DropDownListFor(model => model.Other.MyObjId, new SelectList(Model.MyObjs , "id", "name","--select--"))
Try this,
View :-
#Html.DropDownListFor(m => m.CustomerId, Model.customerNameList, "--Select--")
Controller:-
public ActionResult CustomerInfo()
{
var List = GetCustomerName();
ViewBag.CustomerNameID = new SelectList(List, "CustomerId", "customerName");
ViewBag.RegisterItems = GetAllRegisterData();
return View();
}
public List<CustomerModel> GetCustomerName()
{
// Customer DropDown
using (dataDataContext _context = new dataDataContext())
{
return (from c in _context.Customers
select new CustomerModel
{
CustomerId = c.CID,
customerName = c.CustomerName
}).ToList<CustomerModel>();
}
}
Model:
public class CustomerModel
{
public int CustomerId { get; set; }
[StringLength(9), Required, DisplayName("Social security number")]
[RegularExpression(#"\d{3}-\d\d-\d{4}", ErrorMessage = "Invalid social security number")]
public string customerName { get; set; }
public List<MyListItems> customerNameList { get; set; }
}
Create a ViewModel like this:
public class ListViewModel
{
public MyList MyList { get; set; }
public int SelectedId { get; set; }
}
Then, change your Action to this:
public ActionResult Add()
{
var viewModel = new ListViewModel { MyList = db.lat.ToList() };
return View(viewModel);
}
And, then, this is what you will have in your View:
#model MyApp.ViewModels.ListViewModel
#Html.DropDownListFor(model => model.SelectedId, new SelectList(Model.MyList as IEnumerable, "Id", "Name"))

How to update a textarea in the current view on Submit in ASP.net MVC 3?

I have a page that has two drop down lists and based upon the selection of these two lists I would like to populate a textarea with some data on submit button press.
The behavior that I am seeing while debugging is that the page is rendered, I make my selections and press submit. The DataAccess returns the correct results and the View returns, but with an exception "There is no ViewData item of type 'IEnumerable' that has the key 'People'.
I can see that I could re-setup the drop down lists, but it feels like I'm approaching this incorrectly. Is there another approach for doing this sort of action in MVC 3?
public ActionResult Test()
{
//People for dropdownlist 1
var db = peopleRepository.People;
var query = db.Select(c => new {c.Id, c.Name});
ViewBag.People = new SelectList(query.AsEnumerable(), "Id", "Name");
//Elements for dropdownlist 2
var list = new Dictionary<string, string> {{"1", "Name"}, {"2", "Address"}, {"3", "Zip"}};
ViewBag.Elements = new SelectList(list, "Key", "Value");
return View();
}
// This part is what I'm confused about.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Test(string people, string elements)
{
if (ModelState.IsValid)
{
// Output from persistent storage query
var da = new DatabaseAccess(people, elements);
ViewBag.Results = da.Execute();
}
return View();
}
View:
#using (Html.BeginForm("Test", "Home", FormMethod.Post))
{
#Html.DropDownList("People", (SelectList)ViewBag.People, "--Select One--")
#Html.DropDownList("Elements", (SelectList)ViewBag.Elements, "--Select One--")
#Html.TextArea("Results", (string)ViewBag.Results, 10, 120, "")
}
Here is how I would quickly construct it :
Model :
public class People
{
public int Id { get; set; }
public string Name { get; set; }
}
ViewModel (everything needed by the view):
public class TestViewModel
{
public int SelectedPeopleId { get; set; }
public string SelectedElementId { get; set; }
public SelectList People { get; set; }
public SelectList Elements { get; set; }
public String Results { get; set; }
}
Controller (used Index as the default Action, create an init function for the view model that can be adapted)to anything more appropriate :
public class HomeController : Controller
{
private static TestViewModel InitTestVM()
{
//People for dropdownlist 1
var db = new List<People>();//peopleRepository.People;
db.Add(new People { Id = 1, Name = "Name 1" });
db.Add(new People { Id = 2, Name = "Name 2" });
var query = db.Select(c => new { c.Id, c.Name });
//Elements for dropdownlist 2
var list = new Dictionary<string, string> { { "1", "Name" }, { "2", "Address" }, { "3", "Zip" } };
TestViewModel testVM = new TestViewModel
{
People = new SelectList(query.AsEnumerable(), "Id", "Name"),
Elements = new SelectList(list, "Key", "Value")
};
return testVM;
}
public ActionResult Index()
{
return View(InitTestVM());
}
// This part is what I'm confused about.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(TestViewModel testVM)
{
var vm = InitTestVM();
if (ModelState.IsValid && testVM != null)
{
ModelState.Clear();
// Output from persistent storage query
//var da = new DatabaseAccess(people, elements);
vm.Results = "sfdfsdfsdfsdfsdfsdfsdfsdf";//da.Execute();
vm.SelectedElementId = testVM.SelectedElementId;
vm.SelectedPeopleId = testVM.SelectedPeopleId;
return View(vm);
}
return View(vm);
}
}
And finally the View :
#model ViewModels.TestViewModel
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.DropDownListFor(m => m.SelectedPeopleId, Model.People, "--Select One--")
#Html.DropDownListFor(m => m.SelectedElementId, Model.Elements, "--Select One--")
#Html.TextAreaFor(m => m.Results, 10, 120, "")
<input type="submit" value="Test" />
}

Categories

Resources