ASP.NET MVC How to post complex model - c#

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

Related

Using MvcScaffold, I'm getting "Sequence contains no elements" for most files, for each model

Example error; I try to Scaffold Controller Region -Repository
Region class
public class Region
{
public int RegionId { get; set; }
public string RegionCode { get; set; }
public string ApiUrl { get; set; }
public Universe[] Universes { get; set; }
}
The error repeats essentially for each file it tries to generate (the views, mostly).
I'm not sure what information to include other than this, because I have no clue what causes it. I've tried searching for a solution, but most solutions seems unrelated to my particular issue.
What I will suggest to you is to replace the Array by a List or better an generic interface ICollection. And then try again. Working with array you need to intialize it in the constructor.
public class Region
{
public int RegionId { get; set; }
public string RegionCode { get; set; }
public string ApiUrl { get; set; }
public ICollection<Universe> Universes { get; set; }
}
I solved the problem immediately after submitting with a last-resort option.
I changed:
public Universe[] Universes { get; set; }
To:
public ICollection<Universe> Universes { get; set; }
Then I ran the Scaffold command again, and it worked perfectly. Strange!

Is there a system that converts C# Models into knockout objects?

I've been tasked with adding a feature to an app written by someone who has since left my company. This is implemented with C#/Knockout/Breeze/Durandal. I'm wondering if anyone can answer some of the questions I have regarding the inner workings of knockout and C# interactions:
1) Why is knockout converting an existing ICollection to an observableArray properly, but not a new one that I've added to the model?
2) What is the mechanism that converts the Model to obs/obsArrays? I'm guessing it's got something to do with how the data is pulled back but I'm not sure.
I do not see any js code that would initialize the existing Collection as an observableArray, there's no
vm.existingCollection = ko.observableArray();
He just uses it in is source code as
vm.existingCollection.push(stuff);
Edit to include some code for reference
Here's the model code I'm working with:
public class SimCompare : Report
{
public string LeftGraphName { get; set; }
public int? LeftConsolidationId { get; set; }
public int LeftAsOfDateOffset { get; set; }
public int LeftSimCompareSimulationTypeId { get; set; }
public virtual Consolidation LeftConsolidation { get; set; }
public virtual ICollection<SimCompareSimulationType> LeftSimCompareSimulationTypes { get; set; }
public string RightGraphName { get; set; }
public int? RightConsolidationId { get; set; }
public int RightAsOfDateOffset { get; set; }
public int RightSimCompareSimulationTypeId { get; set; }
public virtual Consolidation RightConsolidation { get; set; }
public virtual ICollection<SimCompareSimulationType> RightSimCompareSimulationTypes { get; set; }
public bool IsQuarterly { get; set; }
public virtual ICollection<SimCompareScenarioType> SimCompareScenarioTypes { get; set; }
}
Then there's a simcompareconfig.js file that starts off like this:
define([
'services/globalcontext',
'viewmodels/simulationselectconfig',
'durandal/app'
],
function (globalContext, simulationselectconfig, app) {
var simCompareVm = function (simCompare) {
var self = this;
this.simCompare = simCompare;
...
There is an existing function to add a scenarioType with a line that looks like this:
simCompare().simCompareScenarioTypes().push(newSimCompareScenarioType);
But that simCompareScenarioTypes() isn't defined anywhere in terms of JS (that I can see). However there is a similar definition in the C# model. This is what's leading me to believe that the model is somehow getting mapped behind the scenes.
Any help is greeeeatly appreciated.

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

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.

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.

Categories

Resources