MVC 3 Cascading DropDownLists - c#

I don't know how to exactly have Cascading DropDownLists
My scenario is the next:
Category has Items and Items have quantities depending on Establishment
I want to have two DropDownLists one which you select a Category, next one is populated when you make a selection of the first with the Items in that Category, and when you select the Item a table with the quantities for each establishment is shown.
Ok this would be my ActionResult
public ActionResult ItemByClinic(Guid? Item_ID, Guid? Category_ID)
{
ViewData["Categories"] = InventoryDb.Categories;
if (Category_ID != null)
{
ViewBag.Category_ID = Category_ID;
ViewData["Items"] = InventoryDb.Items.Where(i => i.Category.ID == Category_ID);
if (Item_ID != null)
{
ViewBag.Item_ID = Item_ID;
ViewData["Inventory"] = InventoryDb.Items.Single(i => i.ID == Item_ID).Inventory;
}
}
return View();
}
then, I would have my two DropDownLists that should post values to Item_ID and Category_ID ... first category then item
#Html.DropDownList("Categories", new SelectList((IQueryable<Inventario_Data.Models.Category>)ViewData["Categories"], "ID", "Name", ViewBag.Category_ID), "Select an Item Category", new { onchange = "window.location.href = '/Inventory/ItemByClinic/Categody_ID=' + this.value" })
This is what I don't know how to do ... how should I put the URL or how should I send it, so when I send the other ID does'nt mix up and I can receive my IDs
How do I receive the values of each DropDownList in the ActionResult? how should they be sent?
ANSWER
I found the answer from this website, just wanted to let know what I did
http://kmsystems.squarespace.com/journal/2009/5/31/aspnet-mvc-cascading-dropdownlists.html

The way you are describing your problem sounds like you are trying to do too many things at once.
To make it easier to explain, I'm going to use the Country / State lookup use case. (When I select "Country", the "State" drop down is populated.)
You have 4 elements:
Initial form load (no country, no state selected)
Country selected, State populated
Country selected, State selected
Error handling (invalid Country & State combination)
When I have come across this, I handle Step 1 & 3 in a view similar to your example.
So are you getting stuck on step 2? What do you mean when you say " how should I put the URL or how should I send it,"
For me, I'll address step 2 by creating javascript controller and use jquery to post & return json objects triggered when the Country dropdown box is selected.
I found the MVC Music Store and Nerd Dinner examples to be extremely helpful.
If you need an example of the json / jquery, see the shopping cart in The Music Store example.

Related

ASP.net MVC/EF/C# add none related table records to query in controller

I am trying to add records from table position for positionName(s) to let user select a position for employee when editing.My last attempts is to add a navigation property like field in company model
public virtual ICollection<Position> Mpositions { get; set; }
But all I got so far is null ref exception or no element in viewModel with property "PositionName" ass per viewbag didn't bother using everybody keeps recommending to avoid it so not going to do so either.
public ActionResult Edit([Bind(Include = "CompanyID,CompanyName,EntityForm,Address,Dissolute,CreationDate,FiscaleYear,Description")] Company company)
{
var GlbUpdate = db.Companies.Include(c => c.Members).Include(p => p.Mpositions);
List<Company> mdlCompanies = new List<Company>();
foreach (var item in GlbUpdate)
{
if ((item.Mpositions==null) || (item.Mpositions.Count() == 0))
{
item.Mpositions = (ICollection<Position>)new SelectList(db.Positions.Except((IQueryable<Position>)db.Positions.Select(xk => xk.Members)), "PositionID", "PositionName");
}
mdlCompanies.Add(item);
//I tried first to edit the Mpositions property directly in gblUpdate
//item.Mpositions = (IEnumerable<Position>)db.Positions.Select(p => new SelectListItem { Value = p.PositionID.ToString(), Text = p.PositionName}) ;
//(ICollection<Position>)db.Positions.ToListAsync();
}
In the view I have this
List<SelectListItem> mPositionNames = new List<SelectListItem>();
#*#this yields no results if I try gettign it from the compani record itself it gives a logic error where all id match all positionNames impossible to select an item and only positions already registered are available on the dropDownlist*#
#{foreach (var item in Model.Mpositions)
{
mPositionNames.Add(new SelectListItem() { Text = item.PositionName, Value = item.PositionID.ToString(), Selected = (false) ? true : false });
#*#selected attribute set to false not an issue, no data to select from :p so far*#
}
}
#*#null exception(if i try to midify Mpositions directly in controler) here or empty list if modify it then put it with original query in a new list*#
<div class="SectionContainer R-sectionContainerData" id="MwrapperDataRight">
#Html.DropDownListFor(mpos => item.PositionID, (SelectList)Model.Mpositions)
</div>
All I want to do is pull the positions table to create a drop downList so users can change the position of an employee but since position has a 1>many relation with employee not companies it is not bound automatically by EF nor I seem to be able to use Include() to add it.
Your query for editing positions are complex. This query must edit person's info only. Using Edit action for formalizing position's edit are not correct.It's againts to Single Responsibility Principle. Use ViewComponents for this situation. Load positions separately from person info.
I found a suitable solution using a model that encapsulate the other entities then using Partialviews/RenderAction so each part handles one entity/operation.

Passing non selected listboxfor values back to controller

I have a listboxfor on my view which I populate with a list of users. I can add users to and from this listbox (from another listbox).
I can pass the values back to the contoller but I have to select users in the listbox for this to happen. I don't want to have to select users..just pass back whatever is in the listbox.
On my view:
#Html.ListBoxFor(m => m.SelectedIDs, DropdownHelper.GetGroupMembers(Model.Id), new { size = 20, #class = "select field small", #style = "width:200px" })
In my view model:
public int[] SelectedIDs { get; set; }
The controller HtttPost Edit takes the view model and SelectedIDs does contain the ids for the users, but only when selected.
I just don't want to have to select users in the listbox...just passback whatever values are there.
Any ideas?
Thanks
Someone will correct me if I missed any, but basically you have five options for passing data to the server:
Cookies
QueryString
Ajax
WebSocket
POST (form variables)
It seems like you want to POST data, so to me hidden inputs is the most appropriate way.

asp.net MVC 4 - output list of checkbox items, associate selections with user - allow display & editing later

ASP.NET C# MVC 4 Code First application - in Visual Studio 2012 Express, SQL Server 2012 Express.
I have a places object. I would like to output the name of all places in a list - with a check box next to each.
I would then like logged in users to select the places they like - and have that saved. Then later they can login and see a them all again, with the appropriate check boxes selected.
What is the best approach? I'm new to MVC and not sure of best practice here.
thanks
Update
The below CheckboxListFor helper worked great, though it wasn't obvious how to process the user selection (it just returns a list of IDs).
I created the below to take that list of IDs - convert it to a list of objects, and add it to the SelecteCities list in the view model. This will select all the checkboxes that the user selected before the page was posted:
public ActionResult Examples(PostedCities postedCities)
{
// ViewModel
CitiesViewModel cvm = new CitiesViewModel();
// Create list of cities
List<City> cities = new List<City>{
new City { Id = 1, Name = "London"},
new City { Id = 2, Name = "Saigon"},
new City { Id = 3, Name = "New York"}
};
// Assign list of cities to ViewModel
cvm.AvailableCities = cities;
// If posted cities present, user posted something (else probably first call)
if (postedCities.CityIDs != null)
{
// temporary city object
City cty = new City();
// List of selected cities
List<City> selCities = new List<City>();
// Go through each postedCity ID
foreach (string s in postedCities.CityIDs)
{
// Get ID of postedCity
int IdSel = Convert.ToInt32(s);
// Lookup city Id in cities
cty = cities.Single(c => c.Id == IdSel);
// Add selected city to cty object
selCities.Add(cty);
}
// Fill cvm.SelectedCities with selCities
cvm.SelectedCities = selCities;
}
return View(cvm);
}
This works - is it a good approach or have I overcomplicated it? Or done something badly?
You can save yourself the work and use the existing MvcCheckBoxList library.
Install it with nuget using the command:
PM> Install-Package MvcCheckBoxList
Here is their home page: MvcCheckBoxList
And here is the documentation: MvcCheckBoxList/Documentation
Other solutions will require some ugly coding.
Update
As Klas Mellbourn suggested (I'm sorry for taking it for granted) a view model with a list will be the best practice for such sceneria. The documentation link I provided contains such examples for you to understand more easily.
I would say that MVC best practices would be to have a viewmodel mirroring the fields you wish to display. It would contain a List with items, each item containing a placename string and a bool for the checkbox.
In the controller method that displays the page you build the view model based on the places objects that you have populated from the database using Entity Framework.
The users presumably save the state using some command, a submit button perhaps. This calls a second controller method that reads the viewmodel and persists the content using Entity Framework.

How to get all the records in a dropdown list?

I have a dropdown list that filters the records by category, but I need the "-- Filter by category --" option to act as the "view all", whereby all the records are returned.
This is in C# .NET. I don't expect it to be too difficult, but its just stumping me right now.
Here is the code-behind for the method:
protected void PopulateCategories()
{
category myCategory = new category();
category[] myCategoryList = myCategory.Listing("title ASC");
ddlCategories.Items.Add("-- Filter by category --");
foreach (category category in myCategoryList)
{
ListItem item = new ListItem(category.title, category.category_id);
ddlCategories.Items.Add(item);
}
}
Depending on what your data source is, and how it reacts to the category.category_id value, you should put a value as part of your "-- Filter by category --" entry...
ddlCategories.Items.Add(New ListItem("-- Filter by category --", "-1"));
Then when you use the ddlCategories.SelectedValue (or however you use it) make sure that if the value is -1 then return everything
In order to make your form more intuitive, you may want to populate the dropdown as shown below:
ddlCategories.Items.Add(new ListItem("- View all categories -", "-1"));
foreach (category category in myCategoryList)
{
ListItem item = new ListItem("View category: " + category.title, category.category_id);
ddlCategories.Items.Add(item);
}
Then, to answer your question, create 2 data access methods: #1 for retrieving all rows, #2 for retrieving rows filtered by the chosen category.
public DataTable GetData(int categoryId)
{
if(categoryId <= 0)
{
// #1
return CatProvider.FindAll(); // Ex. SELECT * FROM table_cats;
}
else
{
// #2
return CatProvider.FindByCategoryId(categoryId); // Ex. SELECT * from table_cats where id_category = #id_category;
}
}
However, I would consider using checkboxes instead (1 for each category), so the user can select any permutation of either all categories, just 1 category, or any combination of multiple categories.
(That's about all I can suggest for now based on the info you provided.)

Beginner MVC question - Correct approach to render out a List and details?

I'm trying to set up a page where I display a list of items and the details of the selected item. I have it working but wonder whether I have followed the correct approach. I'll use customers as an example
I have set the aspx page to inherit from an IEnumerable of Customers. This seems to be the standard approach to display the list of items. For the Details I have added a Customer user control which inherits from customer.
I think i'm on the right track so far but I was a bit confused as to where I should store the id of the customer whose details I intend to display. I wanted to make the id optional in the controller action so that the page could be hit using "/customers" or "customers/1" so I made the arg optional and stored the id in the ViewData like this:
public ActionResult Customers(string id = "0")
{
Models.DBContext db = new Models.DBContext();
var cList = db.Customers.OrderByDescending(c => c.CustomerNumber);
if (id == "0")
{
ViewData["CustomerNumber"] = cList.First().CustomerNumber.ToString();
}
else
{
ViewData["CustomerNumber"] = id;
}
return View("Customers", cList);
}
I then rendered the User control using RenderPartial in the front end:
<%var CustomerList = from x in Model
where x.CustomerNumber == Convert.ToInt32(ViewData["CustomerNumber"])
select x;
Customer c = (Customer)CustomerList.First(); %>
<% Html.RenderPartial("Customer",c); %>
Then I just have an actionLink on each listed item:
<%: Html.ActionLink("Select", "Customers", new { id = item.CustomerNumber })%>
It all seems to work but as MVC is new to me I would just be interested in others thoughts on whether this is a good approach?
In regards to proper MVC and separations of concerns, you shouldn't be calling LINQ queries in your view. To get around that, change your controller action code from what you have to this:
if (id == "0")
{
ViewData["CustomerDetails"] = cList.First();
}
else
{
ViewData["CustomerDetails"] = From x in db.customers where x.id = cInt(id);
}
then your partial
<% Html.RenderPartial("Customer",ViewData["CustomerDetails"]); %>
Are you showing the customer information on the same screen that you have your list of customers and not a separate view?
In this case I would take the following approach.
Display a list of customer's, be it a listbox or drop down list.
Let's assume it's a drop down list, probably not very user friendly
You would have the text as the customer name and then the value as the customer id
<select title="Customers">
<option label="Pieter" value="001"></option>
</select>
and using JQuery's $.getJSON you could load the new data via a call to an asp.net MVC action.
Note that your Action should return JsonResult

Categories