MVC 5 DB first EF displaying view model with 3 classes(DAL) - c#

I have a MVC 5 with EF (DB first approach) application I am creating. The issue I am having is to correctly display the list with the correct data in each column.
I have 3 classes in my DAL:
public partial class MenuItem
{
public int MenuItemID { get; set; }
[DisplayName("Item Name")]
public string name { get; set; }
[DisplayName("Description")]
public string description { get; set; }
public int catID { get; set; }
public virtual Category Category { get; set; }
}
public partial class PricingTier
{
public PricingTier()
{
this.MenuItemsPricingTiers = new HashSet<MenuItemsPricingTier>();
}
public int PricingTierID { get; set; }
public string tierName { get; set; }
public virtual ICollection<MenuItemsPricingTier> MenuItemsPricingTiers { get; set;}
}
public partial class MenuItemsPricingTier
{
public int MenuItemPricingTierID { get; set; }
public int itemID { get; set; }
public int tierID { get; set; }
public Nullable<decimal> price { get; set; }
public Nullable<int> sortOrder { get; set; }
public Nullable<bool> hide { get; set; }
public virtual PricingTier PricingTier { get; set; }
}
The view I require is to list menu items (filtered by a selected category id passed to the controller) with a column for each pricing tier. If the menu item has a menu item pricing tier, I need the price to be displayed in that column. The issue is that each menu item may or may not have a menu item pricing tier. Also, the tables were poorly designed as there is no foreign key between the menu item pricing tier and the menu items.
I tried to create a viewmodel class to display this, but I cannot seem to tie things together. Here is the view model class:
public class MenuItemViewModel
{
public MenuItemViewModel(MenuItem menuitem, IEnumerable<MenuItemsPricingTier> menuitemspricingtiers)
{
this.menuitem = menuitem;
this.menuitemspricingtiers = menuitemspricingtiers.Where(x=>x.itemID == menuitem.MenuItemID);
}
public MenuItem menuitem { get; set; }
public IEnumerable<MenuItemsPricingTier> menuitemspricingtiers { get; set; }
}
Here is my controller:
public ActionResult Index(int catID)
{
var menuitems = db.MenuItems.Include(m => m.Category);
IEnumerable<MenuGridData> viewmodel = new IEnumerable<MenuGridData>();
foreach (MenuItem mi in menuitems) {
// add to viewmodel using repository.GetMenuItem(mi.MenuItemID) ??
}
IEnumerable<MenuItemsPricingTier> menuitemspricingtiers = repository.GetMenuItemsPricingTiers();
return View(viewmodel);
}
I am not sure if this is the correct approach on how I should go about this. I have been playing around with this without much success. I would appreciate any help here, thanks in advance!

You should create dedicated view model classes. You mention that each MenuItem may or may not have a PriceItem, why not do this for your view model:
public class MenuItemViewModel
{
public MenuItem MenuItem { get; set; }
public List<PriceItem> PriceItems { get; set; }
}
I could go on with that view model, the point is don't try and force your EF model classes as view models. create specific view models that contain everything you need. Sometimes people write entirely new models for the view and then convert to the Domain/EF models via the controller.

Related

ASP.NET MVC How to post complex model

I faced a problem. I can't figure out how to post collection with dependency.
I'll show you a code then it maybe clearer what I'm trying to achieve.
I have ViewModel:
public class ProjectViewModel : BaseViewModel
{
public int Id { get; set; }
public string Customer { get; set; }
public string CustomerRepresentative { get; set; }
public string ProjectTitle { get; set; }
public string WWSNumber { get; set; }
public List<Los> Service { get; set; }
}
LosViewModel:
public class Los
{
public int LosNumber { get; set; }
public string Service { get; set; }
public List<Pos> Pos { get; set; }
}
Pos view model:
public class Pos
{
public int PosNumber { get; set; }
public string PosDescription { get; set; }
}
As you see first ViewModel has list. That meens that when user fills LosNumber and enters Service he can add to it PosNumber and PosDescription.
I can't find information how to post with Razor such model.
All I have found is how to display such ModelViewm but not edit.
Maybe somebody had faced this kind of problem ? Any help ?
You need to put the collection into a for loop in your view, then reference the object by index on the collection. MVC is smart enough to figure out that this is a collection when you post it back. Something like...TextBoxFor(m => Model.Service[i].LosNumber). The collection inside a collection will most likely just be a nested for loop.
MVC Razor view nested foreach's model

ASP.NET MVC Complex View Mapping

I have looked around and found some close answers, but I haven't seen one yet like this:
Using Entity Framework I have the following:
A Role model:
public class Role
{
[Key]
public short RoleId { get; set; }
public string RoleName { get; set; }
public string RoleDescription { get; set; }
}
A User model:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Username { get; set; }
//more fields etc...
public virtual ICollection<UserRole> UserRoles { get; set; }
}
and a UserRole model:
public class UserRole
{
[Key]
public int UserRoleId { get; set; }
public int UserId { get; set; }
public short RoleId { get; set; }
public virtual Role Role { get; set; }
}
What I am trying to do is determine how to compose a viewmodel such that I can display a list of all available roles when creating a new user and a list of available+selected roles when editing a user. I can achieve the first part already using a foreach, but I feel like its dirty.
In all of the examples I have seen, the entire viewmodel is wrapped in an IEnumerable on main view and is rendered using #Html.EditorForModel() with an editor template. This seems to allow for automagic mapping of the view data back into the underlying model. I would like to achieve this using the same technique, but I can't seem to wrap my head around handling the collection of Role/UserRole within a singular User model.
StackOverflow question I am referencing: Generate Dynamically Checkboxes, And Select Some of them as Checked
I would suggest 2 view models for editing
public class RoleVM
{
public short RoleId { get; set; }
public string RoleName { get; set; }
public bool IsSelected { get; set; }
}
public class UserVM
{
public int Id { get; set; }
public string Name { get; set; }
public List<RoleVM> Roles { get; set; }
}
GET method
public ActionResult Edit(int ID)
{
UserVM model = new UserVM();
// map all avaliable roles to model.Roles
// map user to model, including setting the IsSelected property for the users current roles
return View(model);
}
View
#model YourAssembly.UserVM
...
#Html.TextBoxFor(m => m.Name)
...
#EditorFor(m => m.Roles)
EditorTemplate (RoleVM.cshtml)
#model YourAssemby.RoleVM
#Html.HiddenFor(m => m.RoleId) // for binding
#Html.CheckBoxFor(m => m.IsSelected) // for binding
#Html.DisplayFor(m => Name)
POST method
[HttpPost]
public ActionResult Edit(UserVM model)
{
// model.Roles now contains the ID of all roles and a value indicating if its been selected

Updating/Insert 2 different models on same screen?

I am working on an edit view that allows a user to edit a particular entity. One of the drop down menus needs to allow the user to create a new instance of a different related entity if they don't see one that exists already. I'm trying to figure out the best practice for this.
The model they are editing:
public class SurveyProgramModel
{
[Key]
public int ProgramId { get; set; }
[DisplayName("Year")]
public int ProgramYear { get; set; }
[DisplayName("Status")]
public int ProgramStatusId { get; set; }
[DisplayName("Program Title")]
public string ProgramTitle { get; set; }
public int ProgramTypeId { get; set; }
[DisplayName("Program Type")]
public virtual SurveyProgramTypeModel ProgramType { get; set; }
[DisplayName("Status")]
public virtual ProgramStatusModel ProgramStatusModel { get; set; }
public virtual ICollection<SurveyResponseModel> SurveyResponseModels { get; set; }
}
If the user does not see a ProgramType that fits what they want, they need to have an empty text box that allows them to create a new ProgramType.
Here is the ProgramType model:
public class SurveyProgramTypeModel
{
[Key]
public int ProgramTypeId { get; set; }
[DisplayName("Program Type")]
public string ProgramType { get; set; }
public virtual ICollection<SurveyProgramModel> SurveyProgramModels { get; set; }
}
What is the best practice for updating 2 models in a single submission? How do I keep my view Strongly Typed to SurveyProgramModel? Create a View Model?
You already know the answer, you would create a View Model and make the necessary changes in your HttpPost action.

Nested ViewModel Classes in asp.net MVC

I have four MVC model layer domain classes.
namespace MvcMobile.Models.BusinessObject
{
public class Speaker
{
public int SpeakerID { get; set; }
public string SpeakerName { get; set; }
}
public class Tag
{
public int TagID { get; set; }
public string TagName { get; set; }
}
public class Seminar
{
public string Seminar_Code { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Room { get; set; }
}
public class Seminar_Detail
{
public string Seminar_Code { get; set; }
public int SpeakerID { get; set; }
public int TagID { get; set; }
public string DateAndTime { get; set; }
}
}
I would like to make CRUD operation by using these classes. So I create two VeiwModel Classes.
namespace MvcMobile.ViewModel
{
public class Seminar_Root_ViewModel
{
public Seminar_Subsidiary_ViewModel Seminars { get; set; }
public List<Speaker> Speakers { get; set; }
public List<Tag> Tags { get; set; }
}
public class Seminar_Subsidiary_ViewModel
{
public Seminar Seminar { get; set; }
public List<Seminar_Detail> Seminar_Detail { get; set; }
}
}
For Controller layer, I consider that I will use Seminar_Root_ViewModel to make the whole CRUD operation processes.
What I would like to ask is that Is this proper way or correct way?
If you have more elegant way to make model layer and ViewModel layer, Please let me get suggestion.
Every suggestion will be appreciated.
[updated]
Let's assume that I make master-Detail form design.
Speaker and Tag are just look-up tables for dropdownlist or some controls like that.
Seminar is Master Data and Seminar_Detail will be Item Grid Data.
So As for this scenario, all of this classes are needed for this program.
Please let me know if my thinking is wrong.
The only thing I can see is if you are not going to re-use your Seminar_Subsidiary_ViewModel view model you could skip it.
If you are going to need those two properties Seminar and Seminar_Detail on another view or ajax call, it's perfectly fine to have that kind of separation.
Personally I'm not a huge fan of _ on class name, but that have nothing to do with the question.

In ASP.NET MVC, How do I synchronise or combine two collections of different types

I have two collections, OrderItems and Items. The reason there are two is because in my model I have an Item which is fixed, and an OrderItem which relates to an Item and adds order specific information such as quantity and a property (OrderID) that relates back to my Order object.
In Entity Framework 4, in order to have a collection of objects in a model you need to relate back to that model in the collection type's object. This makes the OrderID property in Item necessary.
Here are the POCO's in code:
public class Order {
public int OrderID { get; set; }
public DateTime DatePlaced { get; set; }
public bool Filled { get; set; }
public string Comment { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItem {
public int OrderItemID { get; set; }
public int OrderID { get; set; }
public int Quantity { get; set; }
public int ItemID { get; set; }
}
public class Item {
public int ItemID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int Size { get; set; }
}
So now I have my models, and I want to display an Order Details page. I can send over the Order to the ViewModel (MVC 3) or ViewData (MVC 2/1) from the controller which works fine, and I can send a collection of Item as well, but how do I display a list of Items that contain both the Item properties and the Quantity from the OrderItem? Since both are collections, I could OrderBy ItemID and loop over both at the same time in the view, but that seems really messy.
I fiddled with creating an anonymous class that combined both Items and Order but that didn't really work when it came to combining the collections.
I basically want to loop through each Item and OrderItem and display the following properties, without doing it in the view:
Name
Description
Size
Quantity
Ideas?
I believe, forgive me if I'm wrong, but with EntityFramework (assuming code first, but I think db first you can still do it) you can set the following:
public class OrderItem {
public int OrderItemID { get; set; }
public int OrderID { get; set; }
public int Quantity { get; set; }
public virtual Item Item { get; set; }
}
And then when you refer to Item.Name etc. it will lazily load the data in. I don't have access at the moment to test.
Hope this helps, or at least guides you in the right direction.
Edit
Thinking about it, I believe if you're doing db first then as long as you've got the relationship defined in the database then you should be able to access the associated Item from the OrderItem through the relationship property.
Is Item not supposed to derive from OrderItem and you only show Item which has all info for OrderItem and a bit more?
So you will only get the items from database and display using templates, ...
public class OrderItem {
public int OrderItemID { get; set; }
public int OrderID { get; set; }
public int Quantity { get; set; }
public int ItemID { get; set; }
}
public class Item : OrderItem {
// public int ItemID { get; set; } not anymore needed
public string Name { get; set; }
public string Description { get; set; }
public int Size { get; set; }
}

Categories

Resources