I have created MVC3 application using Entity Framework Code First method. My model is very simple:
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int YearsAtCompany { get; set; }
}
and context class is
public class EmployeeDB : DbContext
{
public DbSet<Employee> Employees { get; set; }
}
and controller looks like this:
EmployeeDB context = new EmployeeDB();
public ActionResult Index()
{
return View(context.Employees);
}
}
I have created EmployeesDb.mdf and Employee table.
but I get this error:
The model item passed into the dictionary is of type 'System.Data.Entity.DbSet`1[DFEmployees.Models.Employee]', but this dictionary requires a model item of type 'DFEmployees.Models.Employee'.
[Updated]
#model DFEmployees.Models.Employee
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
Please suggest solution.
It's looks like your view are waiting for a single employee, and you are triying to fill the view with a DBSet of employees.
To solve it, you can set the #model of the view to an IEnumerable of employees, or send only one employee to the view, depending of what are you showing in the view.
EDIT: I think this problem is not related with the previous one. Check this link, I hope it helps you: LINK
Your controller action returns a list of employees so adapt your model respectively in the view:
#model IEnumerable<DFEmployees.Models.Employee>
Or if you wanted to use a single employee make sure you pass a single employee to the view:
public ActionResult Index()
{
return View(context.Employees.FirstOrDefault());
}
and then you can have:
#model DFEmployees.Models.Employee
Related
In asp.net core MVC I need to show two tables in a single view. I have one page and there is a submit button on click of that it will go to another view .there in need to show two tables. I want to use JSON. but from the controller, it returns view model .so how to convert view model data in JSON format to show it in an HTML table?
you can use the Viewbag into your controller to show two tables in one view.
keep this at the top of your view page
#using Newtonsoft.Json
And I think then you can do this which you want.
#Html.Raw(#JsonConvert.SerializeObject(ViewBag.something))
I don't know why you want to return json, the usual solution is to create a ViewModel.
public class Model1
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Model2
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ViewModel
{
public Model1 Model1 { get; set; }
public Model2 Model2 { get; set; }
}
Then you can return a ViewModel to the view.
If you need to return Json,please provide your class model and your view code.
I am working on creating a datagrid in ASP MVC 3 where I have two tables in one view. Each table is being used from its own Model. Therefore, I would have to call two Models into one View which does not seem as simple as I wish it was.
I am pretty new to MVC and I was looking through Stack and found this link:
Two models in one view in ASP MVC 3
Which seems to be the direction that i would want to go... I think.
Here is the code for my first model:
[Table]
public class Model1
{
[Column(IsPrimaryKey = true, IsDbGenerated = true)]
public int Column1 { get; set; }
[Column]
public string Column2 { get; set; }
[Column]
public string Column3 { get; set; }
}
Here is the code for my second model:
[Table]
public class Model2
{
[Column(IsPrimaryKey = true, IsDbGenerated = true)]
public int Column1 { get; set; }
[Column]
public int Column2 { get; set; }
[Column]
public string Column3 { get; set; }
[Column]
public string Column4 { get; set; }
}
Here is the code for the Parent View Model that the other Stack Forum suggested:
public class ParentModelView
{
public Model1 Model1 { get; set; }
public Model2 Model2 { get; set; }
}
I was able to get each one to work individually so i know that it isn't any other issue. The other Stack Forum seemed to be a little too vague for my understanding. I feel like there would have to be more to it than just adding another parent model that is using each model within it (what i am getting out of it).
Some other information that you may find useful is that each model is in its own file. Also, Here is my error:
The model item passed into the dictionary is of type
'System.Data.Linq.Table 1[Model1]', but this dictionary requires a model
item of type 'System.Collections.Generic.IEnumerable 1[ParentModelView]'.
Description: An unhandled exception occurred during the execution of the
current web request. Please review the stack trace for more information
about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The model item passed
into the dictionary is of type 'System.Data.Linq.Table 1[Model1]', but this
dictionary requires a model item of type
'System.Collections.Generic.IEnumerable 1[ParentModelView]'.
Source Error:
An unhandled exception was generated during the execution of the current
web request. Information regarding the origin and location of the exception
can be identified using the exception stack trace below.
---EDIT 1---
Here is the code inside of my View:
#model IEnumerable<ParentModelView>
#{
WebGrid gridModel1 = new WebGrid(Model);
WebGrid gridModel2 = new WebGrid(Model);
}
<div class="Table">
<h2>Model1</h2>
#gridModel1.GetHtml(columns: new[] {
gridModel1.Column("Column1"),
gridModel1.Column("Column2"),
gridModel1.Column("Column3")
})
</div>
<div class="Table" id="rightTable">
<h2>Model2</h2>
#*#gridModel2.GetHtml(columns: new[] {
gridModel2.Column("Column1"),
gridModel2.Column("Column2"),
gridModel2.Column("Column3"),
gridModel1.Column("Column4")
})*#
</div>
EDIT 2
As most of you have requested, here is my controller code. I know that it is not right because i am not quite sure how to pass through the information between two models into the same view. If someone would be able to help with that, it would be much appreciated.
public class HomeController : Controller
{
public ActionResult Index()
{
Model1Repo repoModel1 = new Model1Repo ();
var Model1RepoSQL = repoModel1.All();
Model2Repo repoModel2 = new Model2Repo();
var Model2RepoSQL = repoModel2.All();
return View(Model1RepoSQL);
}
}
Any other information would be much appreciated. Thanks!
I think what you want is something more like this:
public class ParentModelView
{
public IEnumerable<Model1> Model1 { get; set; }
public IEnumerable<Model2> Model2 { get; set; }
}
And in your view
#model ParentModelView
#{
WebGrid gridModel1 = new WebGrid(Model.Model1);
WebGrid gridModel2 = new WebGrid(Model.Model2);
}
EDIT;
Apparently, you aren't populating the parent model correctly. I assumed you would understand how to do that.
public ActionResult MyAction() {
var model1 = // get rows of model1
var model2 = // get rows of model2
return View("myview", new ParentModelView { Model1 = model1, Model2 = model2 }) ;
}
You can always use ViewModel in this case. For example create a viewmodel
public class ViewModel{
public int Table1Column1 { get; set; }
public string Table1Column2 { get; set; }
public string Table1Column3 { get; set; }
public int Table2Column1 { get; set; }
public int Table2Column2 { get; set; }
public string Table2Column3 { get; set; }
public string Table2Column4 { get; set; }
}
Get the data into ViewModel from both the models in business layer or data access layer.
P.S: What McGarnagle said is true but it's vice versa, you are sending child models into the view while it is expecting ParentModelView. If you can post parts of code for controller and view, it would be helpful.
I have a model for a view. This view contains a an #Html.DropDownList whose values are in a model. How can I have my view take both model for different parts of the program?
For example, I have
#model IEnumerable<projectname.mymodel>
#{
ViewBag.Title = "my title"
}
<!--This should use a different model-->
<p>#Html.DropDownList(m =>m.name), new set(Model.list, "value", "key"))
If I have model1 and model2(connects to database)-all stored in the Model folder; and a big model class as something like
public class MyViewModel {
public model1 var1 { get; set; }
public IEnumerable<projectname.Model.model2> var2 { get; set; }
}
And i call this model in my view:
#model ProjectName.Models.Models
How do I reference an item in model1 or model2?
Just pass a new class as model to your view which contains all the data you need:
public class MyViewModel {
public SelectList list { get; set; }
public IEnumerable<projectname.mymodel> Items { get; set; }
}
Another approach would be to pass the list in the Viewbag:
Viewbag.list = new SelectList() ...
I am newbie to MVC3 and I wonder if this is even possible and good practice?
I have a model + view + controller which works fine. This view shows a list of people - I want to be able to click on a person's name and be redirected to a new view that will show that persons details. This new view only has a ViewModel, but no controller because I plan to pass in the object in the action.
The Person object contains all the properties my view needs to show:
#Html.ActionLink(item.Person.FirstName, "PersonDetails", item.Person)
Is this possible/good practice??
I believe you have an misunderstanding of how MVC works. Your ActionLink will ALWAYS redirect to a corresponding ActionMethod of a Controller. What you'll want to do is create an action method in your controller that accepts the necessary parameters and then returns to the View your ViewModel.
Here is a very quick example to get you started:
public class HomeController : Controller
{
public ActionResult List()
{
return View();
}
public ActionResult DetailById(int i)
{
// load person from data source by id = i
// build PersonDetailViewModel from data returned
return View("PersonDetails", PersonDetailViewModel);
}
public ActionResult DetailByVals(string FirstName, Person person)
{
// build PersonDetailViewModel manually from data passed in
// you may have to work through some binding issues here with Person
return View("PersonDetails", PersonDetailViewModel);
}
}
Not a good way to do it like you want to (in your original post). A view should always have a view model. A view model represents only the data that you want to have on the view, nothing more and nothing less. Do not pass your domail model to the view, but rather use a view model. This view model might contain just a portain of the properties of your domain model.
In your list view you probably have a grid, and next to each row you probably have a details link, or a link on the name (as you have it). When either of these links are clicked then you are directed to a details view. This details view will have its own view model with only the properties that you need to display on the details view.
A domail model might look something like:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string ExampleProperty1 { get; set; }
public string ExampleProperty2 { get; set; }
public string ExampleProperty3 { get; set; }
}
Let say you only want to display the person's id, first name, last name and age then your view model will look like this:
public class PersonDetailsViewModel
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
You don't need ExampleProperty1, ExampleProperty2 and ExampleProperty3 because they are not required.
Your person controller might look like this:
public class PersonController : Controller
{
private readonly IPersonRepository personRepository;
public PersonController(IPersonRepository personRepository)
{
// Check that personRepository is not null
this.personRepository = personRepository;
}
public ActionResult Details(int id)
{
// Check that id is not 0 or less than 0
Person person = personRepository.GetById(id);
// Now that you have your person, do a mapping from domain model to view model
// I use AutoMapper for all my mappings
PersonDetailsViewModel viewModel = Mapper.Map<PersonDetailsViewModel>(person);
return View(viewModel);
}
}
I hope this clears things up a little more.
I'm developing a small app in order to better understand how MVC3 anda Razor works. I'm using MVC3, all code was generated automatically (dbContext via T4, Controller via Add Controller, Databese from EDMX model...).
In my model I have this simple model:
http://i.stack.imgur.com/nyqu4.png
public partial class Application
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ApplicationType ApplicationType { get; set; }
}
public partial class ApplicationType
{
public int Id { get; set; }
public string Type { get; set; }
}
As you can see, ApplicationType is basically an enum (shame that EF 4 has no support for enums). So, in my ApplicationController I have this:
public ActionResult Create()
{
ViewBag.AppTypes = new SelectList(db.ApplicationTypes.OrderBy(c => c.Type), "Id", "Type");
return View();
}
[HttpPost]
public ActionResult Create(Application application)
{
if (ModelState.IsValid)
{
db.Applications.Add(application);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(application);
}
And in my view:
#Html.DropDownListFor(model => model.ApplicationType.Id, (SelectList)ViewBag.AppTypes, "Choose...")
Now I'm facing two problems:
1) ApplicationType not being populated:
As #Html.DropDownListFor renders only a simple select, it fills the ID, but does not fill Type property as you can see below (sorry, I can't post images as I'm new here):
http://i.stack.imgur.com/96IR1.png
In the picture you can see that the ID is ok, but Type is empty.
What I'm doing wrong?
2) Duplicated Data
The second problem is that if I fill the Type property manually during debug (simulating a correct workflow scenario), ApplicationType is being duplicated in the database, instead of only referring to an old registry.
So, how can I make #Html.DropDownListFor refer to a previous existing item instead of creating a new one?
Thanks for your help!
I believe the mistake you're making is using your domain models in the view and assuming that on post the entire model should be completely binded and ready to store in the database. While it is possible to use domain models in the view, it's better practice to create separate View Models.
For example :
public class ApplicationViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public SelectList ApplicationTypeList { get; set; }
public string ApplicationTypeId { get; set; }
}
In your view:
#Html.DropDownListFor(model => model.ApplicationTypeId, Model.ApplicationTypeList , "Choose...")
In your controller
[HttpPost]
public ActionResult Create(ApplicationViewModel model)
{
if (ModelState.IsValid)
{
Application application = new Application()
{
Id = model.Id,
Name = model.Name,
ApplicationType = db.ApplicationTypes
.First(a => a.Id == model.ApplicationTypeId);
};
db.Applications.Add(application);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
You can then make verifying that your View Model's ApplicationTypeId corresponds to a real application type part of your modelstate's verification. You can use AutoMapper to speed up the process of converting view models to domain models.
Have you tried:
#Html.DropDownListFor(model => model.ApplicationType.Id, m => m.ApplicationType.Type, "Choose...")
Note the second parameter change.