Causing problems with foreach into my mvc - c#

This is how I have made a previous post as you can see here.
must retrieve the list from the database
I have tried to make my foreach which have been previously described. but it causes problems for not running my foreach in through while making the mistake on it.
Index.cshtml
#foreach (var u in Model)
{
<div class="col-md-6 col-sm-6">
<div class="plan">
<h3>#u.Name<span>$#u.Price</span></h3>
<p>#u.Text</p>
</div>
</div>
}
and undervisningController.cs
// GET: Undervisning
public ActionResult Index()
{
DatabaseClasseDataContext db = new DatabaseClasseDataContext();
var model = db.Packages.ToList();
return View(model);
}
And the top on index.cshtml have i:
#model MentorOrdblind_MVC.Models.Undervisning.Undervisning
Model Undervisning.cs
public class Undervisning
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Hours { get; set; }
public string Text { get; set; }
}

You are passing your view a List<T> but your model is not a type of IEnumerable. So your view is only expecting a single object of the type Undervisning and not a collection.
Use this:
#model IEnumerable<MentorOrdblind_MVC.Models.Undervisning.Undervisning>

Change your model delcaration to:
#model IEnumerable<MentorOrdblind_MVC.Models.Undervisning.Undervisning>
At this moment your model is a single class, not a list of objects

Always keep in mind what is being passed from controller action to view. If you pass only model from the action then use the model reference in the respective view of the action. If you pass List then use IEnumerable model reference in the view.
If you pass list from action then in the view use:
#model IEnumerable<your model> in the top as reference
If you pass model without a list then use:
#model your model
In your case you are passing list so use IEnumerable of your desired model class.
Thanks

Related

MVC ViewModels - Can't access objects/variable passed from controller to View

I am trying to pass ModelView variables from controller to views but unfortunately views not allowing me to access variables. I mention code below.
Here is the ViewModel:
public class AuctionViewModels
{
public List<Auction> AllAuction { get; set; }
public List<Auction> PromotedAuction { get; set; }
}
Here is the Controller action that passes the data to the View:
public ActionResult Index()
{
AuctionViewModels vmodel = new AuctionViewModels();
vmodel.AllAuction = service.GetAllAuction(); //If we need to send more then 1 model to views
vmodel.PromotedAuction = service.GetPromotedAuction();
return View(vmodel);
}
Here is view:
#model List<DealDouble.Web.ViewModels.AuctionViewModels>
#foreach (var auction in Model.AllAuction )
{
<img class="card-img-top" src="http://placehold.it/700x400" alt="">
}
Here is Error:
CS1061: 'List<AuctionViewModels>' does not contain a definition for
'AllAuction' and no extension method 'AllAuction' accepting a first
argument of type 'List<AuctionViewModels>' could be found (are you missing
a using directive or an assembly reference?)
Can anyone tell me what actually i am doing wrong?
Change
#model List<DealDouble.Web.ViewModels.AuctionViewModels>
To
#model DealDouble.Web.ViewModels.AuctionViewModels
Then you'll be able to do foreach(var auction in Model.AllAuction)
you have error in line:
#model List<DealDouble.Web.ViewModels.AuctionViewModels>
you pass (as a model) Class, not list. List does not contain such property as AllAuction. try to replace this line with this one:
#model DealDouble.Web.ViewModels.AuctionViewModels
It should just be
#model DealDouble.Web.ViewModels.AuctionViewModels
You're only passing in one instance of this object, and then iterating over the AllAuction property.
You're instantiating a single object containing two fields both of which are lists:
AuctionViewModels vmodel = new AuctionViewModels();
vmodel.AllAuction = service.GetAllAuction(); /
vmodel.PromotedAuction = service.GetPromotedAuction();
But treating it as if it were a list in the view
#model List<DealDouble.Web.ViewModels.AuctionViewModels>
You need to change the above to:
#model DealDouble.Web.ViewModels.AuctionViewModels
You can then iterate over the two fields
#foreach (var auction in Model.AllAuction ){}
#foreach (var auction in Model.PromotedAuction ){}

Add model into model using Html helper HiddenFor C# MVC

I have a model like
public class Model
{
public int Value { get; set; }
public List<OtherModel> List { get; set; }
}
public class OtherModel
{
public int Value1 { get; set; }
public int Value2 { get; set; }
public bool IsPropTrue { get; set; }
}
I am using Model in a View where I'm looping through the List to show data in a table.
Depending on whether one of the properties (IsPropTrue) in OtherModel is true or false, I want to use the HiddenFor Html helper and send the data to the HttpPost controller.
#model Model
#foreach (var item in Model.List)
{
if (item.IsPropTrue)
{
#Html.HiddenFor(model=> item.Value1)
#Html.HiddenFor(model=> item.Value2)
}
}
I think it doesn't work because I should in some way add these properties to the OtherModel, which is inside the Model; But the way I have it now, I am adding properties to Model.
you can do it like this :
#model Model
#foreach (var item in Model.List)
{
if (item.IsPropTrue)
{
#Html.HiddenFor(model => model.List[Model.List.IndexOf(item)].Value1)
#Html.HiddenFor(model => model.List[Model.List.IndexOf(item)].Value2)
}
}
this way the binding system will bind the hidden fields with your List OtherModel in the Model
if you want send an array to server based on the Model you have to use indexer in #Html.HiddenFor .
#model WebApplication1.Models.MyModel
<form>
#if (Model != null && Model.List != null)
{
for (int i = 0; i < Model.List.Count; i++)
{
if (Model.List[i].IsPropTrue)
{
#Html.HiddenFor(model => Model.List[i].Value1)
#Html.HiddenFor(model => Model.List[i].Value2)
}
}
}
<button type="submit">submit</button>
</form>
if you want know reason of using indexer on model i recommend How does MVC 4 List Model Binding work?
Consider if it the responsibility of the view or the controller action to make the decisions - you can send everything back to the action to do the decision making.
In your Views/Shared folder, create a controller called EditorTemplates
In this folder, add a partial view called OtherModel
In this view, set the model to OtherModel and set the Layout=null
Add the three OtherModel fields in EditorFor (and HiddenFor if not displaying isPropTrue). This partial view displays just one instance of your list.
In your main view, use the above editor model like so. MVC will take care of all rendering and postback of the Model State for your complete list of items. We like one-liners...
#Html.EditorFor(model => model.OtherModel)
When the data is subsequently posted back to an action, Model State has wrapped up all of your displayed items into a list again, so you can check the isPropTrue value for each item on the server.
The only issue with MVC is that is you pass an empty list out to a view, you get a null value back, so just replace this with an empty list when null is returned

MVC HttpPost strongly typed Model null

View Model looks like this:
public class AsmenysInfoViewModel2
{
public asmenys_info Asmenys_info { get; set; }
public List<miestai> Miestai { get; set; }
public string Test { get; set; }
}
And there are two actions. Get and Post.
public ActionResult Index(long? id)
{
var model = new AsmenysInfoViewModel2();
model.Test = "Test";
model.Asmenys_info = BllFactory.DalFactory.AsmenysInfoDal.GetById(id.Value);
return View(model);
}
[HttpPost]
public ActionResult Index(AsmenysInfoViewModel2 asmenys_info)
{
var model = asmenys_info;
return View(model);
}
And my view looks like this:
#model MODELS.AsmenysInfoViewModel2
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Index", "AsmenysInfo", FormMethod.Post))
{
#Html.ValidationSummary()
#Html.TextBoxFor(m => m.Asmenys_info.adresas)
<input type="submit" value="Išsaugoti" />
}
Doesn't matter if I use EditorFor or TextBoxFor - result is same. My model property "Asmenys_info" on posting is always null. If my class AsmenysInfoViewModel2 would not contain asmenys_info type property and would contain only "string, int etc" (no strongly typed) - it would work.
My question is :
How to post View Model which has strongly typed property which on posting would not be null?
Your model has a property named Asmenys_info and the parameter in your POST method is also named asmenys_info. Internally the DefaultModelBinder reads the values of the form data which includes a value for Asmenys_info and attempts to set property Asmenys_info to that value but it fails because there is no conversion from a string to a complex object.
Change the name of the parameter to anything other than a name of a property in your model and it will bind fine, for example
[HttpPost]
public ActionResult Index(AsmenysInfoViewModel2 model)
Change the below line with another object name
public ActionResult Index(AsmenysInfoViewModel2 asmenys_info)
in above method use any other name of object instead of asmenys_info.
because while mvc framework map your model with object there is confution in asmenys_info and Asmenys_info property of AsmenysInfoViewModel2 class.

count the number of items in view in asp.net mvc

I am very new to asp.net development. In my asp.net mvc project I have model "Employee" and I'm passing a list of "Employee" model to a RAZOR view and I'm trying to count different type of employees and show a summary.
my view is like this,
#{
int available = 0;
int onLeave = 0;
int away = 0;
int unAvailable = 0;
}
#foreach (var employee in Model){
<lable>#employee.Name</lable></br>
#if (#employee.Available){
#available=available+1;
}
#if (#employee.Unavailable){
#unAvailable=unAvailable;
}
#if (#employee.Away){
#away=away+1;
}
#if (#employee.Onleave){
#onLeave=onLeave+1;
}
}
<div>
<!--additional summary is displayed here-->
<label>Available:</label>#available
<label>Unavailable:</label>#unAvailable
<label>Away:</label>#away
<label>On Leave:</label>#onLeave
</div>
but when I run the my project variables "available","unAvailable","away" and "onLeave" don't get updated.
I'm sure that list is not empty because employee names are displaying.
can some explain me what is happening here and correct way of doing this
You should be doing this outside the before passing to the view like I mentioned in my original comment. You can create a new object called a ViewModel to represent the data exactly like you want it on the page. So I created a simple example, I only used the 4 properties of Employee you are displaying in you CSHTML page. On your View where you said your MODEL is either a list, arrary or whatever of Employee change it to EmployeeViewModel. Then in your controller where you get your list of employees set them to the Employees property of the Employee ViewModel.
public class EmployeeViewModel
{
public IEnumerable<Employee> Employees { get; set; }
public int TotalAvailable { get { return Employees.Count(emp => emp.Available); } }
public int TotalUnavailable { get { return Employees.Count(emp => emp.Unavilable); } }
public int TotalAway { get { return Employees.Count(emp => emp.Away); } }
public int TotalOnLeave { get { return Employees.Count(emp => emp.OnLeave); } }
}
public class Employee
{
public bool Available { get; set; }
public bool Unavilable { get; set; }
public bool Away { get; set; }
public bool OnLeave { get; set; }
}
//In the controller do this.
public ActionResult Index() //use your controller Action Name here
{
var employeeViewModel = new EmployeeViewModel { Employees = /*Your list of empoyees you had as a Model before here*/}
return View(employeeViewModel)
}
Change your CSHTML code to something like this:
#foreach(var employee in Model.Employees)
{
<label> #employee.Name </label></br>
}
<div>
<!--additional summary is displayed here-->
<label> Available:</label> #Model.TotalAvailable
<label> Unavailable:</label> #Model.TotalUnavailable
<label> Away:</label> #Model.TotalAway
<label> On Leave:</label> #Model.TotalOnLeave
</div>
An easy and quick way is:
<div>
<!--additional summary is displayed here-->
<label>Available:</label>#Model.Count(i => i.Available)<br>
<label>Unavailable:</label>do the same.
<label>Away:</label>do the same.
<label>On Leave:</label>do the same.
</div>
Make sure the model has already been "ToList()", or it might lead to mult-access of database.
Basically, I only use viewmodel when I need to pass more than 1 models to the view. Not worth in this case.
Make such calculations in View considered a BAD practice.
In your case better option will be create ViewModel with corresponding properties and then pass it to the model, previously calculating count for every type in controller using LINQ. Where you could reference your types like Model.available, Model.away and so on. Using ViewModel it is the best practice for MVC.
#Thorarins answer show you how to use LINQ in your code to calculate count for you types.
UPDATE:
You can use JS, but you should not, because it still not what supposed to happen in View. Work with data should not be handled in View. Don't be scared by ViewModels, they not that hard as it could seem. Please read this article which consider all ways to pass data to View, which has good example how create and pass ViewModel.
Mvc sample on how to do it:
you need a model class
public class EmployeeModel
{
public int Available {get; set;}
public int OnLeave {get; set;}
public int Away {get; set;}
public int UnAvailable {get; set;}
}
and a command:
public ActionResult Index()
{
var model = new EmployeeModel();
model.Available = employee.count(e=> e.available);
model.OnLeave = employee.count(e=> e.onLeave);
model.Away = employee.count(e=> e.away);
model.UnAvailable = employee.count(e=> e.unAvailable );
return View(model);
}
and a view
#model EmployeeModel
<div>
<!--additional summary is displayed here-->
<label>Available:</label>#Model.Available
<label>Unavailable:</label>#Model.UnAvailable
<label>Away:</label>#Model.Away
<label>On Leave:</label>#Model.OnLeave
</div>

How to save data in two tables? (In Create)

Good Day,
I wonder how to save the information in a create.
#model Request.Models.Chamados
#model Request.Models.InteracoesChamados
#{
ViewBag.Title = "Create";
}
as shown in the two tables above only that of course does not work.
please give me an example of this because it confused me.
NOTE: So for clarity, I fill out a form and save to 2 tables when I hit save.
environment:
Windows 7,
Visual Studio 2010,
C #,
MVC3 + Razor Entity Framework
There seems to be a few things here but for starters, you can only declare one model per view.
You could create a ViewModel that has both of those above, e.g.
public class ChamodosViewModel{
public Chamados Chamados {get;set;}
public InteracoesChamados InteracoesChamados {get;set;}
}
and then in your view
#model ChamodosViewModel
Do not use the Domain model for your view. Create a new POCO class which is specific for your view. Let's call it ViewModel, in general.
public class ChamodoVM
{
[Required]
public string ChamdoName { set;get;}
[Required]
public string InteracoName { set;get;}
//other properties here as needed
}
Now in yout GET action create an object of this class and pass to the View method.
public ActionResult Create()
{
var vm=new ChamodoVM();
return View(vm);
}
Make your view strongly typed to the ViewModel class.
#model ChamodoVM
#using(Html.BeginForm())
{
#Html.LabelFor(x=>x.ChamodoName)
#Html.TextBoxFor(x=>x.ChamodoName)
#Html.LabelFor(x=>x.InteracoName)
#Html.TextBoxFor(x=>x.InteracoName)
<input type="submit" />
}
When user submit the form, read the values from view model and assign it to an object of your domain modal and save. Thanks to MVC model binding. :)
[HttpPost]
public ActionResult Create(ChamodoVM model)
{
if(ModelState.IsValid)
{
var domainModel=new Chamodo();
domainModel.Name=model.ChamodoName;
domainModel.Interaco=new Interaco();
domainModel.Interaco.Name=model.InteracoName;
yourRepositary.SaveClient(domainModel);
//If saved successfully, Redirect to another view (PRG pattern)
return RedirectToAction("ChamodoSaved");
}
return View(model);
}

Categories

Resources