I have two related ddl's. When page loads, I can POST them to controller and everything is ok. But also I have some fields in page, and if they are empy I call ModalError in my controller, then page should be reloaded with text of errors. But it throughs an error, that says IEnumerable<SelectList> with name City is empty. What is the problem?
View:
#using (#Html.BeginForm())
{
<div>
#Html.LabelFor(model=>model.Buyer.buyers_name)
</div>
<div>
#Html.EditorFor(model=>model.Buyer.buyers_name)
#Html.ValidationMessageFor(model=>model.Buyer.buyers_name)
</div>
<div>
#Html.LabelFor(model=>model.Buyer.buyers_email)
</div>
<div>
#Html.EditorFor(model=>model.Buyer.buyers_email)
#Html.ValidationMessageFor(model=>model.Buyer.buyers_email)
</div>
<div>
#Html.LabelFor(model=>model.Buyer.buyers_phone)
</div>
<div>
#Html.EditorFor(model=>model.Buyer.buyers_phone)
#Html.ValidationMessageFor(model=>model.Buyer.buyers_phone)
</div>
<div>
<h2>Выберите адрес доставки:</h2>
<h3>Выберите город</h3>
#Html.DropDownList("City", ViewBag.cities as SelectList, new { id = "city" })
<h3>Выберите адрес</h3>
#Html.DropDownList("Address", ViewBag.addresses as SelectList, new { id = "address" })
</div>
<input type="submit" value="Send" class="btn" />
}
Controller:
public ActionResult GetItems(decimal id)
{
return PartialView(_db.bs_delivery_type.Where(x => x.delivery_city_id == id).ToList());
}
public ActionResult Checkout()
{
int selectedIndex = 1;
SelectList cities = new SelectList(_db.bs_cities, "cities_id", "cities_name", selectedIndex);
ViewBag.cities = cities;
SelectList addresses = new SelectList(_db.bs_delivery_type.Where(x => x.delivery_city_id == selectedIndex), "delivery_id", "delivery_address");
ViewBag.addresses = addresses;
return View();
}
[HttpPost]
public ActionResult Checkout(Cart cart, DeliveryModel deliveryModel, decimal city, decimal address)
{
if (cart.Lines.Count() == 0)
{
ModelState.AddModelError("", "Your cart is empty");
}
if (ModelState.IsValid)
{
//adds to db;
return View("Completed");
}
else
{
return View(deliveryModel);
}
}
DeliveryModel:
public class DeliveryModel
{
public bs_buyers Buyer { get; set; }
public List<bs_cities> CitiesModel { get; set; }
public SelectList FilteredDelivery { get; set; }
}
Also PartialView GetItems:
<select id="address" name="Address">
#foreach (var item in Model)
{
<option value="#item.delivery_id">#item.delivery_address</option>
}
As you invoke the Checkout Action in your Controller via HttpPost you then return the Checkout View in case the ModelState is invalid. However you do net set your ViewBag Variables as you do in your HttpGet Action.
You have to set ViewBag Variables in each and every Action. In this case I would recommend a separate method that gets invoked in both Actions.
private void SetViewBagForCheckout(){
int selectedIndex = 1;
SelectList cities = new SelectList(_db.bs_cities, "cities_id", "cities_name", selectedIndex);
ViewBag.cities = cities;
SelectList addresses = new SelectList(_db.bs_delivery_type.Where(x => x.delivery_city_id == selectedIndex), "delivery_id", "delivery_address");
ViewBag.addresses = addresses;
}
Related
I have an DropDownList ,which is showing list of Status,but when i Select an item from DropDownlist and than i Checked HTML Markup i can see there isnt Selected attr and than i researched and find out I need SelectListItem in my Controller and than i tried to implement it in my Controller,but i got some errors :) as usually i implement DropDown in my Razor View (static) , but this time which is first time :) i want implement in my Controller so it becomes dynamic.
Can anyone point me in right direction :)
Thanks in advance :)
Controller:
//DropDown
public List<VMRMA.NameStatusDropDown> GetStatusForDropDown()
{
List<VMRMA.NameStatusDropDown> result = new List<VMRMA.NameStatusDropDown>();
var obj = db.RMAStatus.Select(u => u).ToList();
if (obj != null && obj.Count() > 0)
{
foreach (var data in obj)
{
VMRMA.NameStatusDropDown model = new VMRMA.NameStatusDropDown();
model.Status = data.Status;
model.ID = data.ID;
result.Add(model);
}
}
return result;
}
//Dropdown runs in this Action
public ActionResult RMA ()
{
VMRMA model = new VMRMA();
model.NameStatusDropDowns = GetStatusForDropDown();
//RMA query and some an other stuff
return View(model);
}
ViewModel:
public class VMRMA
{
public List<NameStatusDropDown> NameStatusDropDowns { get; set; }
//DropDown
public class NameStatusDropDown
{
public NameStatusDropDown()
{
}
public NameStatusDropDown(int ID, string Status)
{
this.ID = ID;
this.Status = Status;
}
public int ID { get; set; }
public string Status { get; set; }
}
}
View:
#using ModelNamespace.Models
#model VMRMA
<form>
<div class="form-group">
<label class="form-control-label">Select a status</label>
<br />
<select>
<option>Select</option>
#foreach (var item in Model.NameStatusDropDowns)
{
<option value="#item.ID">#item.Status</option>
}
</select>
</div>
<div class="form-group">
<input type="submit" value="Send data" class="btn btn-primary">
</div>
</form>
HTML Markup:
<div class="form-group">
<label class="form-control-label">Select a status</label>
<br>
<select>
<option>Select</option>
<option value="1">Sendt</option>
<option value="2">Under behandling</option>
<option value="3">Blive behandlet</option>
<option value="4">Modtaget</option>
</select>
</div>
This two Post helped me out to solve the problem and Thanks to #Stephen Muecke with his good post, Which is wroted Here and Thanks to this post with great explanation, which is wroted Here.
Here is what i did , maybe it helped someone one day :) :
Add To Property to my View Model :
public class VMRMA
{
public List<SelectListItem> Status { set; get; }
public int? SelectedStatus { set; get; }
}
Change my ActionResult to :
public ActionResult RMA (int Id)
{
VMRMA model = new VMRMA();
model.Status = new SelectList(DatabaseNameSpace.RMAStatus, "ID",
"Status").ToList();
//some an other stuff
return View(model);
}
and than change my View to :
#Html.DropDownListFor(s => s.SelectedStatus, Model.Status, "- Select -", new { #class = "form-control" })
Controller:
ViewBag.Statuses= new SelectList(_context.RMAStatus
.Select(item => new { value = item.Id, text = item.Status}), "value", "text", selectedId);
View:
#Html.DropDownListFor(x => x.StatusId, ViewBag.Statuses as SelectList, "- please select -")
Create a partial view as this:
#model MyApp.Models.MyClass
#{
Layout = null;
}
#*#Html.Partial("ActionMethod", "Controller", new ViewDataDictionary { { "Name", "TestName" } })*#
#Html.DropDownList((String)TempData["Name"], new SelectList( ViewBag.Specialities,"Value","Text"),
new { #class = "form-control", #multiple="multiple" });
Then in your controller
List<MyClass> lstSpecialities =
ViewBag.Specialities = lstSpecialities; // Now it is available for the view
Last step, load your view using #Html.RenderAction()
In my application, my model contains a field id, and in the view I need to select an id with a radio button and post back the selected id to the controller. How can I do this? My view is as follows,
#model IList<User>
#using (Html.BeginForm("SelectUser", "Users"))
{
<ul>
#for(int i=0;i<Model.Count(); ++i)
{
<li>
<div>
#Html.RadioButtonFor(model => Model[i].id, "true", new { #id = "id" })
<label for="radio1">#Model[i].Name<span><span></span></span></label>
</div>
</li>
}
</ul>
<input type="submit" value="OK">
}
You need to change you model to represent what you want to edit. It needs to include a property for the selected User.Id and a collection of users to select from
public class SelectUserVM
{
public int SelectedUser { get; set; } // assumes User.Id is typeof int
public IEnumerable<User> AllUsers { get; set; }
}
View
#model yourAssembly.SelectUserVM
#using(Html.BeginForm())
{
foreach(var user in Model.AllUsers)
{
#Html.RadioButtonFor(m => m.SelectedUser, user.ID, new { id = user.ID })
<label for="#user.ID">#user.Name</label>
}
<input type="submit" .. />
}
Controller
public ActionResult SelectUser()
{
SelectUserVM model = new SelectUserVM();
model.AllUsers = db.Users; // adjust to suit
return View(model);
}
[HttpPost]
public ActionResult SelectUser(SelectUserVM model)
{
int selectedUser = model.SelectedUser;
}
Need help in MVC : Please help in Creating dropdownlist(child) based on the count from a dropdownlist selected value(integer)- consider it as a parent control. And insert the child dropdownlist selected values to the database using MVC Eg; If 3 is selected in parent dropdownlist,3 new dropdownlist needs to be created and selected values of 3 dropdownlist needs to be inserted into DB--By using MVC dropdownlist . While I tried,only first child dropdownlist selected value is getting inserted or three times..Please help in resolving it
First Creating parent dropdownlist. Starting with Home Controller, i create a list
public ActionResult Index()
{
List<int> key =new List<int>();
key.Add(1); key.Add(2); key.Add(3); key.Add(4); key.Add(5);
ViewBag.RequiredKey = new SelectList(key);
return View();
}
In the Index View i show the parent dropdownlist
#using (Html.BeginForm("SelectedDropDownResult", "Home",FormMethod.Post))
{
#Html.DropDownList("SelectedDropDownValue", (SelectList)ViewBag.RequiredKey, new { #class = "form-control" })
<input type="submit" value="Submit">
}
Here in this dropdownlist user selects a value which is posted to the action named SelectedDropDownResult in the Home controller
public ActionResult SelectedDropDownResult(FormCollection fc)
{
int dropDown = int.Parse(fc["SelectedDropDownValue"]);
ViewBag.dropDownValue = dropDown;
List<int> key = new List<int>();
key.Add(1); key.Add(2); key.Add(3); key.Add(4); key.Add(5);
ViewBag.RequiredKey = new SelectList(key);
return View();
}
Using FormCollection lets extract the user selected value in parent drop down
#{
ViewBag.Title = "SelectedDropDownResult";
}
<h3> Generating #ViewBag.dropDownValue based on parent drop down selected value</h3>
#using (Html.BeginForm("ChildDropDown", "Home", FormMethod.Post))
{
<input type="hidden" name="childDropDownValue" value=#ViewBag.dropDownValue>
for (int i=0; i< #ViewBag.dropDownValue;i++ )
{
#Html.DropDownList("SelectedDropDownValue"+i, (SelectList)ViewBag.RequiredKey, new { #class = "form-control" })
}
<input type="submit" value="Submit">
}
Here child drop down lists are created based on the count of parent list and action ChildDropDown is called to save data to database
public ActionResult ChildDropDown(FormCollection fc)
{
List<int> child=new List<int>();
int dropDown = int.Parse(fc["childDropDownValue"]);
for(int i=0;i<dropDown;i++)
{
child.Add(int.Parse(fc["SelectedDropDownValue"+i]));
}
// code to add data child list to the database
return View();
}
}
You can now add code to save data to the database in ChildDropDown action of Home controller
A sample how you can hold your child Dropdowns value.
ViewModels-
public class TestModelViewModel
{
public int ParentId { get; set; }
public IEnumerable<ParentListViewModel> ParentList { get; set; }
public int ChildId { get; set; }
public IEnumerable<ParentListViewModel> ChildList { get; set; }
public IEnumerable<int> ChildIds { get; set; }
}
public class ParentListViewModel
{
public int Id { get; set; }
public string Value { get; set; }
}
public class ChildListViewModel
{
public int ChildId { get; set; }
public string ChildValue { get; set; }
}
Controller-
public ActionResult Index()
{
var model = new TestModelViewModel
{
ParentList = new List<ParentListViewModel>
{
new ParentListViewModel{
Id = 1,
Value = "One"
},new ParentListViewModel{
Id = 2,
Value = "Two"
},new ParentListViewModel{
Id = 3,
Value = "Three"
},
}
};
return View(model);
}
[HttpPost]
public ActionResult Index(TestModelViewModel model)
{
var ChildIds = model.ChildIds;
/* now you can save these ChildIds to your db */
return View(model);
}
View-
#model WebApplication1.Models.TestModel
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { area=""}))
{
<div class="row">
<div class="col-md-12">
<h2>Parent List</h2>
<p>
<select id="ParentList" name="ParentId">
<option value="">--- select parent list ---</option>
#foreach (var item in Model.ParentList)
{
<option value="#item.Id">#item.Value</option>
}
</select>
</p>
</div>
<div class="col-md-12">
<h2>Child List</h2>
<p id="childListCotnainer">
</p>
</div>
<div class="col-lg-12"><input class="btn btn-default" type="submit" value="submit" /> </div>
</div>
}
#section scripts{
<script>
$(function () {
$("#ParentList").change(function () {
var length = parseInt($(this).val());
var dropHtml = '';
for (i = 0; i < length; i++) {
dropHtml += '<select name="ChildIds"><option value="1">Child One</option><option value="2">Child Two</option><option value="3">Child Three</option></select><br /><br />';
}
$("#childListCotnainer").html(dropHtml);
});
});
</script>
}
In MVC web app it is a view with strongly typed model where a drop down is being generated / bind by model.
Below is view code:
#model LoanViewModel
<form class="wrapper minheight homeloan-form border-top" id="homeloan-form" method="post" action="LeadContact" novalidate="novalidate">
<p>#Html.ValidationSummary()</p>
<p>Select an Item : #Html.DropDownListFor(x => x.HomeLoanLead.Items, new SelectList(Model.HomeLoanLead.Items), "--Choose any Item--")</p>
<div class="formnav row">
<button class="">Show Top Home Loans <i class="fa fa-chevron-right"></i></button>
</div>
</form>
In model I m hardcoding options for drop down list:
public List<string> Items
{
get { _items = new List<string>();
_items.Add("One");
_items.Add("Two");
_items.Add("Three");
return _items;
}
}
On post back I cant get what was selected value in drop down. Please guide me how to get in post action which drop down value was selected.
A simple example of using Html.DropDownFor() to display a list of options and bind to a property:
Model
public class LoanViewModel
{
[Required]
[Display(Name="Select Item")]
public string Item { get; set; }
public SelectList ItemList { get; set; }
}
Controller
public ActionResult Edit()
{
LoanViewModel model = new LoanViewModel();
model.Item = "Two"; // this will now pre-select the second option in the view
ConfigureEditModel(model);
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(LoanViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureEditModel(model); // repopulate select list
return View(model); // return the view to correct errors
}
// If you want to validate the the value is indeed one of the items
ConfigureEditModel(model);
if (!model.ItemList.Contains(model.Item))
{
ModelState.AddModelError(string.Empty, "I'm secure!");
return View(model);
}
string selectedItem = model.Item;
....
// save and redirect
}
private void ConfigureEditModel(LoanViewModel model)
{
List<string> items = new List<string>() { "One", "Two", "Three" };
model.ItemList = new SelectList(items); // create the options
// any other common stuff
}
View
#model LoanViewModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.DisplayFor(m => m.Item)
#Html.DropDownListFor(m => m.Item, Model.ItemList), "--Choose any Item--")
#Html.ValidationMessageFor(m => m.Item)
<input type="submit" value="Submit" />
}
EDIT: whoever fixed my question so the code displayed right, thank you! :)
I have a silly problem I really need som help with, after a whole day of googling I'm close to loosing my head!
I am working with the asp.net membership, and I want to be able to set roles on user once the web app is upp and running.
To implement this I am sending a model to a strongly typed view with a list of checkboxes, if the user is in one of the roles in the list the checkbox is checked. (this part works)
But I cant figure out how to return the checkbox values in the Edit method, as the model returns 'null' on the List-property.
I am sure I've missed something obvious here, and would be very happy for any help...
And how can I add code to this question? I cant get the formatting right...
View
#model Mvc4m.Models.UserRoles
#{
ViewBag.Title = "Edit";
}
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>UserRoles</legend>
<div class="editor-label">
<h2> #Html.DisplayFor(model => model.Name)</h2>
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Roles)
</div>
<div class="editor-field" id="testar">
#foreach (var model in Model.AllRolles)
{
#Html.CheckBoxFor(item => model.IsActive, model.Role)
#Html.Label(model.Role)
}
</div>
<div class="editor-label">
#Html.LabelFor(model => model.IsApproved)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.IsApproved)
#Html.ValidationMessageFor(model => model.IsApproved)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Controller
public List<AllRolles> UserActiveRoles(string name)
{
var list = new List<AllRolles>();
foreach(var role in Roles.GetAllRoles())
{
var hej = new AllRolles()
{
Role = role,
IsActive = Roles.IsUserInRole(name,role)
};
list.Add(hej);
}
return list;
}
public ActionResult Index()
{
var roles = Roles.GetAllRoles();
var users = from MembershipUser u in Membership.GetAllUsers()
select new UserRoles()
{
Name = u.UserName,
AllRolles = UserActiveRoles(u.UserName)
};
return View(users);
}
public ActionResult Edit(string name)
{
var user = Membership.GetUser(name);
var model = new UserRoles()
{
Name = user.UserName,
AllRolles = UserActiveRoles(name)
};
return View(model);
}
//
// POST: /Admin/ManageUsers/Edit/5
[HttpPost]
public ActionResult Edit(UserRoles user)
{
var name = user.Name;
foreach (var role in user.AllRolles)
{
if (role.IsActive == true)
Roles.AddUserToRole(name,role.Role);
else
Roles.RemoveUserFromRole(name,role.Role);
}
return RedirectToAction("Index");
}
Models
public class UserRoles
{
public string Name { get; set; }
public List<string> Roles { get; set; }
public bool IsApproved { get; set; }
public List<AllRolles> AllRolles { get; set; }
}
namespace Mvc4m.Areas.Admin.Models
{
public class AllRolles
{
public string Role { get; set; }
public bool IsActive { get; set; }
}
}
At UserRoles.cs
Change
public List<AllRolles> AllRolles { get; set; }
to
public AllRolles[] AllRolles { get; set; }
At Edit.cshtml
Change
#foreach (var model in Model.AllRolles)
{
#Html.CheckBoxFor(item => model.IsActive, model.Role)
#Html.Label(model.Role)
}
to
#for (int i = 0; i < Model.AllRolles.Length; i++)
{
#Html.CheckBoxFor(item => Model.AllRolles[i].IsActive)
#Html.HiddenFor(item => Model.AllRolles[i].Role)
#Html.Label(Model.AllRolles[i].Role)
}
At your controller
Add .ToArray() after UserActiveRoles(u.UserName)
public ActionResult Index()
{
var roles = Roles.GetAllRoles();
var users = from MembershipUser u in Membership.GetAllUsers()
select new UserRoles()
{
Name = u.UserName,
AllRolles = UserActiveRoles(u.UserName).ToArray()
};
return View(users);
}
The problem
You must show to the ModelBinder that you're sending a collection, instead of a bunch of parameters.
What's sent to the server?
AllRolles[0].IsActive:false
AllRolles[0].Role:Admin
AllRolles[1].IsActive:false
AllRolles[1].Role:User
Hope it helps
It's really simple. You must give your checkboxes a name let's say myCheckboxes and you pass a int[] myCheckboxes to POST action. I've provided you a code sample:
In your view let's say you have
#foreach (var role in Model.AllRoles)
{
<input type="checkbox" name="UserNotInRoles" value="#role.RoleId" checked/>#role.RoleName
<br />
}
#foreach (var role in Model.UserRole)
{
<input type="checkbox" name="UserInRoles" value="#role.RoleId" checked/>#role.RoleName
<br />
}
Now to post what user has checked/unchecked you use the following:
[HttpPost]
public ActionResult Edit(UserRoleSaveVM saveRoles)
{
if (saveRoles.UserNotInRoles != null)
{
foreach (int roleID in saveRoles.UserNotInRoles)
{
//DO SOMETHING
}
}
where UserRoleSaveVM is
public class UserRoleSaveVM
{
public int UserID { get; set; }
public int[] UserInRoles { get; set; } //note that property name is the same as checkbox name
public int[] UserNotInRoles{ get; set; } //note that property name is the same as checkbox name
}