Listboxfor MVC3 Razor. User selection from database fields - asp.net-mvc-3

I'm working with a Razor MVC3 project
I have a model
public class ProductFormatModel
{
public int ID {get; set;}
public string SerialID { get; set; }
public ProductTypes ProductType { get; set; }
public List<ProductComponent> Components { get; set; }
}
The ProductComponent class has two properties: int ID and string Description.
I would like the controller to work with a strongly typed view of ProductFormatModel type to create a new ProductFormatModel. The Create view should look like this:
A textfield to insert SerialID (done)
A dropdownlist to select the value of the enumerator ProductType (done)
A listbox with different rows showing the "Description" property of ProductComponent. Every row should present a record in the database. The user must be able to select one or more rows and in this way the property "Components" should have those objects in the list.
The database is a simple DbContext. MyDB.Components gives me the recordset of table "Components"
How do I pass the values of the recordset from the controller to the view?
Should I call a listboxfor with multiselectlist?
Should I add another property to the model like List ComponentsToBeSelected in which I can pass the list?

One possible design:
Use two listboxes in your view. Load the first with all possible ProductComponents that are not in model.Components, and use ListBoxFor to bind the second to the model.Components list.
Place two buttons, Add and Remove, between the lists. Wire these up with jQuery to move items between the two listboxes.

Related

How to select multiple items from dropdown list, save it and again repopulate the dropdown with the selected list?

I am working on an ASP.NET MVC3 project. I am facing issues regarding multiple selection in dropdown.
The problem is, I have to save multiple items in database from a dropdown list and repopulate it.
I have used the class below to represent each list data:
public class IDNameValueTO {
public int ID { get; set; } //Value of the selection Element
public string Name { get; set; } //Name of the selectionElement
public int Value { get; set; } //1 if value is checked and 0 if not
}
My List goes as follows:
public List<IDNameValueTO> tempList = new List<IDNameValueTO>();
ViewBag.SelectedList = tempList;
I am generating the dropdown list as follows:
#Html.DropDownList("SelectedValue", new SelectList(ViewBag.SelectedList, "ID", "Name"))
Now how do I save the multiple selection and display it later on using dropdown?
The default DropDown helper that is provide in asp.net mvc does not support multiselet.
You'll have to create your own custom multiselect dropdown helper.
Here are some links that can help you create you own custom dropdown helper:
http://blogs.msdn.com/b/rickandy/archive/2012/01/30/asp-net-mvc-dropdownlist-multiselect-and-jquery.aspx
http://utsavized.com/chosen-multiselect-dropdown-list-with-asp-net-mvc3/

Show display values for a foreign key property in a model

I have a model that looks kinda like this:
public class Notes
{
public int NoteID {get; set;}
public string Note {get; set;}
public int CustomerID {get; set;}
{
On the Notes Details view, I would like to be able to show Customer Name instead of CustomerID. Obviously if this were a Create or Edit view I use a dropdown list.
However I am not sure how to show the value and not the ID in a read only Details view.
Thanks!
Code First is mainly... code, not Database logic.
So, instead of having the Foreign Keys (like CustomerID) in your models (it's also possible, and sometimes needed, but not always), you'll be more confortable having a reference property
public virtual Customer Customer {get;set;}
So in your view having Notes as Model, you could simply use
#Html.DisplayFor(m => m.Customer.Name);
When you retrieve your Notes entity, don't forget to include the related entities / properties needed for your View / ViewModel (I let you read about lazy loading)
You can try this:
var applicationDbContext = _context.Notes.Include(n => n.Custumer);
return View(await applicationDbContext.ToListAsync());
This code must be in your controller, in the Index method or whatever you named it.
And this is in view.
#Html.DisplayFor(modelItem => item.Customer.Name)

List vs IEnumerable vs IQueryable when defining Navigation property

I want to create a new model object named Movie_Type in my ASP.NET MVC web application. What will be the differences if I define the navigation proprty of this class to be either List, ICollection or IQueryable as following?
public partial class Movie_Type
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<Movie> Movies { get; set; }
}
OR
public partial class Movie_Type
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public IQueryable<Movie> Movies { get; set; }
}
OR
public partial class Movie_Type
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<Movie> Movies { get; set; }
}
Edit:-
#Tomas Petricek.
thanks for your reply. in my case i am using the database first approach and then i use DbContext template to map my tables, which automatically created ICollection for all the navigation properties, So my questions are:-
1. Does this mean that it is not always the best choice to use Icollection. And i should change the automatically generated classes to best fit my case.
2. Secondly i can manage to choose between lazy or Eager loading by defining .include such as
var courses = db.Courses.Include(c => c.Department);
Regardless of what i am using to define the navigation properties. So i can not understand ur point.
3. i did not ever find any examples or tutorials that use IQuerable to define the navigation properties ,, so what might be the reason?
BR
You cannot use a navigation property of type IQueryable<T>. You must use ICollection<T> or some collection type which implements ICollection<T> - like List<T>. (IQueryable<T> does not implement ICollection<T>.)
The navigation property is simply an object or a collection of objects in memory or it is null or the collection is empty.
It is never loaded from the database when you load the parent object which contains the navigation property from the database.
You either have to explicitely say that you want to load the navigation property together with the parent which is eager loading:
var movieTypes = context.Movie_Types.Include(m => m.Movies).ToList();
// no option to filter or sort the movies collection here.
// It will always load the full collection into memory
Or it will be loaded by lazy loading (which is enabled by default if your navigation property is virtual):
var movieTypes = context.Movie_Types.ToList();
foreach (var mt in movieTypes)
{
// one new database query as soon as you access properties of mt.Movies
foreach (var m in mt.Movies)
{
Console.WriteLine(m.Title);
}
}
The last option is explicit loading which comes closest to your intention I guess:
var movieTypes = context.Movie_Types.ToList();
foreach (var mt in movieTypes)
{
IQueryable<Movie> mq = context.Entry(mt).Collection(m => m.Movies).Query();
// You can use this IQueryable now to apply more filters
// to the collection or sorting, for example:
mq.Where(m => m.Title.StartWith("A")) // filter by title
.OrderBy(m => m.PublishDate) // sort by date
.Take(10) // take only the first ten of result
.Load(); // populate now the nav. property
// again this was a database query
foreach (var m in mt.Movies) // contains only the filtered movies now
{
Console.WriteLine(m.Title);
}
}
There are two possible ways of looking at things:
Is the result stored in memory as part of the object instance?
If you choose ICollection, the result will be stored in memory - this may not be a good idea if the data set is very large or if you don't always need to get the data. On the other hand, when you store the data in memory, you will be able to modify the data set from your program.
Can you refine the query that gets sent to the SQL server?
This means that you would be able to use LINQ over the returned property and the additional LINQ operators would be translated to SQL - if you don't choose this option, additional LINQ processing will run in memory.
If you want to store data in memory, then you can use ICollection. If you want to be able to refine the query, then you need to use IQueryable. Here is a summary table:
| | Refine query | Don't change query |
|-----------------|--------------|--------------------|
| In-memory | N/A | ICollection |
| Lazy execution | IQueryable | IEnumerable |
More of a standard is IEnumerable as it is the least common denominator.
Iqueryable can be returned if you want extra querying functionality to the caller without having 10 repository methods to handle varying querying scenarios.
A downside is ienumerable could 'count()' slowly but if the object implements ICollection then this interface is checked for this value first without having to enumerate all items.
Also be aware if you return iqueryable to an untrusted caller they can do some casting and method calls on the iqueryable and get access to the context, connection, connection string, run queries, etc
Also note nhibernate for example has a query object you can pass to a repository to specify options. With entity framework you need to return IQueryable to enhance querying criteria
The collection that entity framework actually creates for you if you use virtual navigation properties implements ICollection, but not IQueryable, so you cannot use IQueryable for your navigation properties, as Slauma says.
You are free to define your properties as IEnumerable, as ICollection extends IEnumerable, but if you do this then you will lose your ability to add new child items to these navigation properties.

Reusable editor template with DropDownList for business objects

I'm using MVC3 with Razor views and would like to build reusable DropDownLists for several of my classes, but after much searching I have not found an example that performs exactly how I need it...
For this example I have two classes like this:-
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public Group Group { get; set; }
}
public class Group
{
public int ID { get; set; }
public string Name { get; set; }
}
I have a working Controller/View for Person. The view has a DropDownListFor control:
#model Person
...
#Html.DropDownListFor(o => o.Group.ID, (ViewData["groups"] as SelectList))
The view uses the Person class directly, not an intermediary model, as I haven't found a compelling reason to abstract one from the other at this stage.
The above works fine... in the controller I grab the value from Group.ID in the Person returned from the view, look it up, and set Person.Group to the result. Works, but not ideal.
I've found a binder here: MVC DropDownList values posted to model aren't bound that will work this out for me, but I haven't got that working yet... as it only really seems useful if I can reuse.
What I'd like to do is have something like this in a template:-
#model Group
#Html.DropDownListFor(o => o.Group.ID, (ViewData["groups"] as SelectList))
And use it in a view like this:-
#Html.EditorFor(o => o.Group)
However the above doesn't seem to work... the above EditorFor line inserts editors for the whole class (e.g. a textbox for Group.Description as well)... instead of inserting a DropDownList with my groups listed
I have the above template in a file called Group.cshtml under Views/Shared/EditorTemplates
If this worked, then whenever a class has a property of type Group, this DropDownList editor would be used by default (or at least if specified by some attribute)
Thanks in advance for any advice provided...
You can create a drop down list user control to handle this. Under your Shared folder create a folder called EditorTemplates and place your user control there. MVC, by convention, looks in the Shared/EditorTemplates for any editor templates. You can override where it looks for the editor templates but I won't go in to that here.
Once you have your user control created, you'll need to decorate the appropriate property with the "UIHint" attribute to tell the engine what editor it should use for that property.
Following would be a sample implementation.
In the Shared/EditorTemplates folder your user control (_GroupsDropDown.cshtml in this case) would look like:
#model Group
#Html.DropDownListFor(o => o.ID, (ViewData["groups"] as SelectList))
Modify the Group property in the Person to add the UIHint attribute as follows:
**[UIHint("_GroupsDropDown")]**
public Group Group { get; set; }
In your controller you would need
ViewData["groups"] = new SelectList(<YourGroupList>, "ID", "Name");
Once you have the above code you can use the EditorFor syntax like you desire.
Hope this helps.

Using JQGrid with LinQ

I am trying to populate a JQGrid with LinQ but am having problems in getting a value from a foreign table.
Scenario: I have a Users table and a Country table. I am returning a List from the data layer and binding it to the grid. The values from the users table populate with no problem. My problem is when trying to link a JQGrid column to a column in the Country table, such as Country Name. If I debug the data returned from the data logic, the Country Name is filled in, but I can't find a way to link a JQGrid column to the Name column in the Country table. I tried, with no luck, the following:
<trirand:JQGridColumn DataField="Country.Name"/>
<trirand:JQGridColumn DataField="Country_Name"/>
Thanks for your time...
Have you tried using a ViewModel so it is not trying to bind to a navigation property?
something like:
public class UserViewModel
{
public int UserID { get; set; }
public string Username { get; set; }
public string CountryName { get; set; }
}

Resources