I have a controller that return a List of Messages
public ActionResult MainMenu()
{
var myDataOp = new DataBaseOperations();
var Message=myDataOp.GetMessages();
return View(Message);
}
Here is the Function That gets the List
public List<ViewClass> GetMessages()
{
PrincelysDataContext pData = new PrincelysDataContext();
Princelys.Models.ViewClass myViewList =new ViewClass();
var myMessage =from r in pData.Messages select r;
DateTime presentTime = new DateTime();
foreach (var myValues in myMessage)
{
myViewList.myMessage.Add(new ViewClass
{
CreatedName ="ffff",// (from m in pData.Users where m.userid == myValues.createdBy select m.userName).Single(),
Messages = myValues.Message,
CreateOn = myValues.createddatetime.Subtract(presentTime)
});
}
return myViewList.myMessage;
}
I then use my list in the View Page.
#model Princelys.Models.ViewClass
....
#foreach (var messageValues in Model.myMessage)
{
<li class="left clearfix">
<span class="chat-img pull-left">
<img src="http://placehold.it/80/30a5ff/fff" alt="User Avatar" class="img-circle" />
</span>
<div class="chat-body clearfix">
<div class="header">
<strong class="primary-font">#messageValues.CreatedName</strong> <small class="text-muted">#messageValues.CreateOn.TotalHours mins ago</small>
</div>
<p>
#messageValues.Messages
</p>
</div>
</li>
}
I get an error when I run the view page on a browser
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[Princelys.Models.ViewClass]', but this dictionary requires a model item of type 'Princelys.Models.ViewClass'.
This is the class that hold the properties
public class ViewClass
{
public ViewClass()
{ myMessage = new List<ViewClass>(); }
public string CreatedName { get; set; }
public string Messages { get; set; }
public TimeSpan CreateOn { get; set; }
public List<ViewClass> myMessage;
}
This is my first MVC 5 project. Any help would be greatly appreciated.
You are returning List<ViewClass> in your controller action, however looks like your view is strongly typed with ViewClass. Change it to #model IEnumerable<ViewClass> Or other way round i.e. return ViewClas from controller.
Based on the comments the issue is GetMessages should return ViewClass so it should look like below
public ViewClass GetMessages()
{
PrincelysDataContext pData = new PrincelysDataContext();
Princelys.Models.ViewClass myViewList =new ViewClass();
var myMessage =from r in pData.Messages select r;
DateTime presentTime = new DateTime();
foreach (var myValues in myMessage)
{
myViewList.myMessage.Add(new ViewClass
{
CreatedName ="ffff",// (from m in pData.Users where m.userid == myValues.createdBy select m.userName).Single(),
Messages = myValues.Message,
CreateOn = myValues.createddatetime.Subtract(presentTime)
});
}
return myViewList;
}
You are passing a List to the view, but your view is strongly typed to a single member of that list. Try changing this in your model:
#model List<ViewClass>
Related
So the beginning of my View is
#foreach ( var G in ViewBag.GroupedBySec )
{
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<table class="table table-striped assessment-table">
<tbody>
<tr>
<td class="black-n-white" colspan="4">#G.Key</td>
</tr>
<tr>
<td>Section</td><td>Component</td><td>Completeness Level (0-100%)</td><td>Readines</td>
</tr>
#var GroupedBySubsection = G.GroupBy(x => x.SubsectionTitle);
#foreach ( var g in GroupedBySubsection )
{
#foreach ( var qa in g )
{
and I'm getting errors on the
#var GroupedBySubsection = G.GroupBy(x => x.SubsectionTitle);
#foreach ( var g in GroupedBySubsection )
lines which say
The name 'var' does not exist in the current context
and
The name 'GroupedBySection' does not exist in the current context
Any idea what I'm doing wrong?
Alternatively, any suggestions for how I can get a C# object that has the entire groupings and subgroupings so that I don't have to write all this crap in my View?
My Controller method for this page is like
[HttpGet]
public ActionResult Peek ( Guid pid )
{
ViewBag.PartnerId = pid;
List<AnswerInfo> AllAnswers = this._Db.GetAnswersByPartner(pid);
ViewBag.GroupedBySec = AllAnswers.GroupBy(A => A.SectionTitle);
return View();
}
Your error occurs because your missing the braces around your var statement. It should be
#{ var GroupedBySubsection = G.GroupBy(x => x.SubsectionTitle); }
This will then throw a different error because you referring an item in ViewBag which is dynamic so you need to cast it as follows
#{ var GroupedBySubsection = ((IEnumerable<yourModel>)G).GroupBy(x => x.SubsectionTitle); }
making your view even uglier.
how I can get a C# object that has the entire groupings and subgroupings so that I don't have to write all this crap in my View?
Use a view model. Based on some of your previous question, you have a data model which (abbreviated) is
public class Answer
{
public string Section { get; set; }
public string SubSection { get; set; }
public int QuestionID { get; set; }
public string QuestionText { get; set; }
....
}
And that you want to group it in the view by Section and then SubSection. Your view models would then be
public class SectionVM
{
public string Title{ get; set; }
public List<SubSectionVM> SubSections { get; set; }
}
public class SubSectionVM
{
public string Title { get; set; }
public List<QuestionVM> Questions { get; set; }
}
public class QuestionVM
{
public int QuestionID { get; set; }
public string QuestionText { get; set; }
....
}
Your controller code would then be
var answers = db.Answers..... // your previous query
List<SectionVM> model = answers.GroupBy(x => x.Section).Select(x => new SectionVM
{
Title = x.Key,
SubSections = x.GroupBy(y => y.SubSection).Select(y => new SubSectionVM
{
Title = y.Key,
Questions = y.Select(z => new QuestionVM
{
QuestionID = z.QuestionID,
QuestionText = z.QuestionText,
....
}).ToList()
}).ToList()
}).ToList();
return View(model);
and in the view
#model List<SectionVM>
#foreach(var section in Model)
{
<h2>#section.Title</h2>
foreach(var subSection in section.SubSections)
{
<h3>#subSection.Title</h3>
foreach(var question in subSection.Questions)
{
<p>#question.QuestionText</p>
....
}
}
}
Side note: I have made the collection properties List<T> assuming that you might want to also generate a form for editing the Questions/Answers and to do so you will need a for loop which required the collection to implement IList. Alternatively you could save the extra overhead of .ToList(), keep them asIEnumerableand use a customEditorTemplate` for each view model type.
For an example of how an edit view might look (using the for loop option), refer to this answer.
I have a property called UserFunctions where I have several functions and must assign a User for each function. I have a EditorTemplate to return a list of users. I have to create a field dynamically for each function registered in the database and each field will use the EditorTemplate to list users. (like the image below). I created a EditorTemplate (UserFunctions.cshtml) strongly typed (model ICollection ) which generates the fields, like the image below, but I do not know what to do so that the values are returned to the Model. I thought of using a hidden multiselect, but is very complicated.
My class
public class FunctionUser //Não mapeado
{
public int IdFuncao { get; set; } //functin id
public string Usuario { get; set; } //User
public string DscFuncao { get; set; } //Function Description
}
My Field in the View (property UserFunctions)
#Html.EditorFor(i => i.UserFunctions, "UserFunctions")
My EditorTemplate -> UserFunctions.cshtml
#model ICollection<FunctionUser>
#{
var modelMetaData = this.ViewData.ModelMetadata;
var propertyName = modelMetaData.PropertyName;
}
#foreach (FunctionUser item in this.Model)
{
var id = "id" + Guid.NewGuid().ToString().Substring(0, 5);
List<SelectListItem> listValues = new List<SelectListItem>();
if (!string.IsNullOrEmpty(item.Usuario))
{
listValues.Add(new SelectListItem { Selected = true, Text = item.Usuario, Value = item.Usuario });
}
<div id="#id" class="field-middle">
<h3>#String.Format(ModeloResources.ProductDevelopment, item.DscFuncao) :</h3>
#Html.DropDownList("", listValues, new { id = "PD" + item.IdFuncao.ToString() })
</div>
<script language="javascript" type="text/javascript">
$("##id select")
.turnAutoComplete("#Url.Action("UsersListJson", "Security")");
</script>
}
<select name="#propertyName" multiple="multiple" size=30 style='height: 100%;' >
#foreach (FunctionUser item in this.Model)
{
<option value="#item.IdFuncao">teste</option>
}
</select>
Someone answered my question in "pt.stackoverflow.com". The solution was to use the BeginCollectionItem package.
Models:
public partial class Modelo
{
public ICollection<FuncaoUsuario> ProductDevelopment { get; set; }
//Continua...
}
public class FuncaoUsuario
{
public int IdFuncao { get; set; }
public string Usuario { get; set; }
public string DscFuncao { get; set; }
}
Controller:
public ViewResultBase Editar(int id)
{
Modelo model = this.Service.GetForEdit(this.IdEmpresa, id);
return base.SwitchView(model);
}
Main View:
#model Modelo
<div class="box-fields">
#using (Ajax.BeginForm(
this.DefaultActionEdit,
"Modelo",
new DefaultAjaxOptions()
))
{
#Html.EditorFor(i => i.ProductDevelopment) //precisa desta propriedade na view principal, pra nao dar o erro mencionado abaixo. E tem que remover o template Collection.cshtml.
foreach (FuncaoUsuario userFunction in this.Model.ProductDevelopment)
{
Html.RenderPartial("_UsuarioFuncao", userFunction);
}
//Mais coisas....
}
Partial View:
#model FuncaoUsuario
#using (Html.BeginCollectionItem("ProductDevelopment"))
{
List<SelectListItem> listValues = new List<SelectListItem>();
if (!string.IsNullOrEmpty(this.Model.Usuario))
{
listValues.Add(new SelectListItem { Selected = true, Text = this.Model.Usuario, Value = this.Model.Usuario });
}
#Html.HiddenFor(x => x.IdFuncao)
#Html.EditorFor(x => x.Usuario, "Usuario")
}
Following link:
Solution using BeginCollectionItem
I am trying to add multiple rows of data and pass it to the table in database along with another item to a different table. Below is the struct of the databse:
User Table
userid
name
Movie Table
Movieid
userid
moviename
Cinema Table
Movieid
cinemaid
location
time
The movietable has 1 to many realtionship with the Cinema table. The user table has one I have four different viewmodels associating to them:
UserViewModel
{
public int userid;
public string name;
}
MoviewViewModel
{
public int movieid;
public int userid;
public string moviename;
public List<CinemaViewModel> cinema;
}
CinemaViewModel
{
public int movieid;
public int cinemaid;
public string location;
public string time;
}
UserandMovieViewModel
{
public List<MoviewViewModel> movie;
public UserViewModel user;
}
I am passing the userandmoviewmodel from the controller create to the view and would like to add one entry for user and movie, but would like to add multiple entries to the Cinema database from that single page. it works fine when i add a single entry to cinema. however i would like to have the ability to add multiple entries to cinema table when form is posted. I have tried the tutorial below but that doesnt seem to work for create.
http://ivanz.com/2011/06/16/editing-variable-length-reorderable-collections-in-asp-net-mvc-part-1/
EDIT
The code which give null exception
<ul id="movieEditor" style="list-style-type: none">
#foreach (CinemaViewModel cinemamodel in Model.UserandMovieViewModel.cinema) {
Html.RenderPartial("MovieEntryEditor", cinemamodel);
}
</ul>
<a id="addAnother" href="#">Add another</a>
EDIT2
The create controller code
[httpget]
public ActionResult Create()
{
UserViewModel usermodel = new UserviewModel();
List<MovieViewModel> moviemodel= new List<MovieViewModel>();
UserandMovieViewModel model = new UserandMovieViewmodel{user = usermodel, movie=moviemodel }
return View(model)
}
[httppost]
public ActionResult Create(UserandMovieViewmodel model)
{
IRepository<User> userrep = new ApplicationRepository<User>();
IRepository<Movie> userrep = new ApplicationRepository<Movie>();
IRepository<Cinema> userrep = new ApplicationRepository<Cinema>();
User user = null;
Movie movie = null;
Cinema cinema = null;
UserViewModel usermodel = model.usermodel;
MovieViewModel moviemodel= model.moviemodel;
CinemaViewModel cinemamodel = model.moviemodel.cinema;
if(ModelState.valid)
{
user = new user();
user.name = usermodel.name;
userrep.add(user);
movie = new movie();
movie.userid = user.userid; (gets from database as its autoappend)
movie.moviename = moviemodel.moviename;
movierep.Add(movie);
cinema = new cinema();
cinema.movieid = movie.movieid;
cinema.location = cinemamodel.location;
cinema.time = cinemamodel.time;
cinemarep.Add(cinema);
}
return View(model);
}
I have written the code from memory as i dont currently have it. Please correct any errors you see.
EDIT 3
Partial View
#model Application.ViewModels.CinemaViewModel
<li style="padding-bottom:15px">
<div style="width: 450px; float: left;">
<label class="location">
Location
</label>
<span style="margin-left: 26px;">
#Html.TextBoxFor(model => model.location)
#Html.ValidationMessageFor(model => model.location)
</span>
<span>
#Html.TextBoxFor(model => model.time)
#Html.ValidationMessageFor(model => model.time)
</span>
</div>
I suspect that you have your list as null, so you can try just to new it up in constructor:
public class MoviewViewModel
{
public MoviewViewModel(){
cinema = new List<CinemaViewModel>();
}
public int movieid;
public int userid;
public string moviename;
public List<CinemaViewModel> cinema;
}
public class UserandMovieViewModel
{
public UserandMovieViewModel(){
movie = new List<MoviewViewModel>();
}
public List<MoviewViewModel> movie;
public UserViewModel user;
}
EDIT:
Your view:
<ul id="movieEditor" style="list-style-type: none">
#if(Model.UserandMovieViewModel.cinema.Any())
{
foreach (CinemaViewModel cinemamodel in Model.UserandMovieViewModel.cinema) {
Html.RenderPartial("MovieEntryEditor", cinemamodel);
}
}
else
{
#{ Html.RenderPartial("MovieEntryEditor", new CinemaViewModel()) };
}
</ul>
<a id="addAnother" href="#">Add another</a>
I'm trying to obtain list of Id values for which user checked a checkbox. Here's the model:
using System.Collections.Generic;
namespace TestWebApplication3.Models
{
public class TestViewModel
{
public IEnumerable<InnerViewModel> ModelData { get; set; }
public class InnerViewModel
{
public int Id { get; set; }
public bool Checked { get; set; }
}
}
}
Controller:
using System.Web.Mvc;
using TestWebApplication3.Models;
namespace TestWebApplication3.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
var test = new TestViewModel();
test.ModelData = new[]
{
new TestViewModel.InnerViewModel {Id = 10},
new TestViewModel.InnerViewModel {Id = 20},
new TestViewModel.InnerViewModel {Id = 30},
new TestViewModel.InnerViewModel {Id = 40}
};
return View(test);
}
[HttpPost]
public string TestAction(TestViewModel model)
{
string s = "";
foreach (TestViewModel.InnerViewModel innerViewModel in model.ModelData)
{
if (innerViewModel.Checked)
s += innerViewModel.Id + " ";
}
return s;
}
}
}
And the View:
#model TestWebApplication3.Models.TestViewModel
#using (Html.BeginForm("TestAction", "Home"))
{
<ol>
#foreach (var testData in Model.ModelData)
{
<li>
#Html.HiddenFor(m => testData.Id)
#Html.CheckBoxFor(m => testData.Checked)
</li>
}
</ol>
<input type="submit"/>
}
So I'm displaying a list of InnerViewModel objects (created in Index action) as checkboxes. When user submits the form, I'd like to somehow obtain the list of Id values which are "checked" in TestAction method. But the returning model is always null.
In the application I'm making there are many more properties to the model, therefore it's important that the list of InnerViewModel objects is nested in the TestViewModel. I also don't want to use third party solution like MvcCheckBoxList, as it seems to me to be an overkill for such a simple task.
Can anyone explain to me what is missing for this to work?
I slightly changed your code to make it working -
ViewModel -
public class TestViewModel
{
public List<InnerViewModel> ModelData { get; set; }
public class InnerViewModel
{
public int Id { get; set; }
public bool Checked { get; set; }
}
}
Controller -
public ActionResult Index()
{
var test = new TestViewModel();
test.ModelData = new List<TestViewModel.InnerViewModel>()
{
new TestViewModel.InnerViewModel {Id = 10},
new TestViewModel.InnerViewModel {Id = 20},
new TestViewModel.InnerViewModel {Id = 30},
new TestViewModel.InnerViewModel {Id = 40}
};
return View(test);
}
public string TestAction(TestViewModel model)
{
string s = "";
foreach (TestViewModel.InnerViewModel innerViewModel in model.ModelData)
{
if (innerViewModel.Checked)
s += innerViewModel.Id + " ";
}
return s;
}
View -
#model MVC.Controllers.TestViewModel
#using (Html.BeginForm("TestAction", "Home"))
{
<ol>
#for (int i = 0; i < Model.ModelData.Count() ; i++ )
{
<li>
#Html.HiddenFor(m => m.ModelData[i].Id)
#Html.CheckBoxFor(m => m.ModelData[i].Checked)
</li>
}
</ol>
<input type="submit" />
}
You need to understand how the model binder works. Simple once you understand that.
MVC Binding to checkbox
Complex object require indexing in order for the model binder to pick them up.
Change it to this so the model binder will pick them up:
#for (int i = 0; i < Model.ModelData.Count; i++)
{
<li>
#Html.HiddenFor(m => Model.ModelData[i].Id)
#Html.CheckBoxFor(m => Model.ModelData[i].Checked)
</li>
}
This is a good article explaining some of the gotchas in model binding.
http://msdn.microsoft.com/en-us/magazine/hh781022.aspx
One thought would be to use a CheckBoxFor control. It saves you a whole lot of trouble in the end in finding what is checked and what isn't. I built a RadioButtonListFor one before and it wasn't very difficult. In fact, here is a link to use on it.
Create MVC3 CheckBoxFor from List and getting the list back (With updated values) on Post
I'm brand new to ASP.NET MVC, and I would appreciate any help with my question. I already did plenty of research (not enough apparently) on this topic. I need to bind a dropdownlist to a specific column in a table and then render it in the view. I already have the query to retrieve the table in the controller:
public ActionResult SelectAccountEmail()
{
var queryAccountEmail = (from AccountEmail in db.UserBases select AccountEmail)
var selectItems = new SelectList(queryAccountEmail);
return View(selectItems);
}
I get lost when it come to binding the query to a dropdownlist in the view.
#model RecordUploaderMVC4.Models.UserBase
#{
ViewBag.Title = "SelectAccountEmail";
}
<h2>SelectAccountEmail</h2>
#Html.LabelFor(model => model.AccountEmail);
#Html.DropDownList(Model.AccountEmail);
#Html.ValidationMessageFor(model => model.AccountEmail);
<input /type="submit" value="Submit">
I get this error when I run it:
Server Error in '/' Application.
--------------------------------------------------------------------------------
The model item passed into the dictionary is of type 'System.Web.Mvc.SelectList', but this dictionary requires a model item of type 'RecordUploaderMVC4.Models.UserBase'.
Any help will be appreciated.
Thanks in advance.
Few things wrong. Firstly, change your model to add the following properties (Looking at your view, it's RecordUploaderMVC4.Models.UserBase):
public class UserBase
{
public string AccountEmail { get; set; }
public SelectList Emails { get; set; }
//rest of your model
}
Then, build your model in your controller properly:
public ActionResult SelectAccountEmail()
{
UserBase model = new UserBase();
var queryAccountEmail = (from AccountEmail in db.UserBases select AccountEmail)
model.Emails = new SelectList(queryAccountEmail);
return View(model);
}
Then in your view you can do:
#Html.LabelFor(model => model.AccountEmail)
#Html.DropDownListFor(model => model.AccountEmail, Model.Emails)
#Html.ValidationMessageFor(model => model.AccountEmail)
Step 1:
First Create a model Like this to hold your ListofAccountEmail
public class AccountEmailViewModel
{
public int AccountEmailId { get; set; }
public string AccountEmailDescription { get; set; }
}
Step 2: Create your model class
public class UserBaseViewModel
{
public IEnumerable<SelectListItem> AccountEmail { get; set; }
public string AccountEmail { get; set; }
}
Step 3 :
In Controller
[HttppGet]
public ActionResult SelectAccountEmail()
{
var EmailAccounts = (from AccountEmail in db.UserBases select AccountEmail)
UserBase userbaseViewModel = new UserBase
{
AccountEmail = EmailAccounts.Select(x => new SelectListItem
{
Text = x.AccountEmailDescription,
Value = Convert.ToString(x.AccountEmailId)
}).ToList()
};
return View(userbaseViewModel);
}
Step 4 : In View
#model RecordUploaderMVC4.Models.UserBase
#{
ViewBag.Title = "SelectAccountEmail";
}
<h2>SelectAccountEmail</h2>
#Html.ValidationSummary()
<h2>SelectAccountEmail</h2>
#Html.LabelFor(model => model.AccountEmail )
#Html.DropDownListFor(x => x.AccountEmailId, Model.AccountEmail, "Please Select", "")
</div>
<input /type="submit" value="Submit">