Entity framework how to pass data to view? - asp.net-mvc

I am learning Entity Framework and MVC.
This is my model:
public class ChatLogContext : DbContext
{
public ChatLogContext()
: base("connString")
{
}
public DbSet<ChatLogs> ChatLogs { get; set; }
}
[Table("ChatLogs")]
public class ChatLogs
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ChatLogId { get; set; }
[Column("Message")]
public string Message { get; set; }
[Column("UserId")]
public int UserId { get; set; }
}
And this is my controller code here:
public ActionResult Index()
{
using(var db = new ChatLogContext())
{
var list = db.ChatLogs.Select(p => p.Message).SingleOrDefault();
ViewBag.data = list;
return View();
}
}
I then access that data in view like this:
#model Chat.Models.ChatLogs
#Html.Raw(ViewBag.data)
I can access 1 record as seen here with this.
But I would like to learn, how to access all records from the table ChatLogs with Entity Framework and pass it to view with Razor method(foreach), so I can format that data (I don't like default tables that VS generates). I am now using ViewBag for one row and 1 column, this is the most far I came.
I just can't find an examples on Google that would help my brains.
Help appreciated.
PS: Is it better to work with pure entity or mix linq(linq to entities)?

Typically the Index action is for showing a grid of all the entities (in this case ChatLogs).
One of the points of the Razor View Engine is that you get typed Views. So typically I would pass the data to the view directly as opposed to using the ViewBag.
public ActionResult Index()
{
using(var db = new ChatLogContext())
{
var list = db.ChatLogs.ToList();
return View(list);
}
}
The next step is to have the View typed to IEnumerable<ChatLog>. Visual Studio should help you with that. Then you can just foreach over the ChatLogs.

Related

MVC passing object from model through controller to view

I don't have much experience with programming and I'm new to MVC.
I want to fetch some data from database with entity framework and print it in the view.
This is my model:
public class Grad
{
public int ID { get; set; }
public string Naziv { get; set; }
public char KoordinataX { get; set; }
public char KoordinataY { get; set; }
public int BrojStanovnika { get; set; }
}
public class GradDBContext : DbContext
{
public DbSet<Grad> Gradovi { get; set; }
}
this is a controller:
private GradDBContext db = new GradDBContext();
public ActionResult Index()
{
List<int> gradoviList = new List<int>();
foreach (sea.Models.Grad g in db.Gradovi)
{
gradoviList.Add(g.ID);
}
ViewData["Gradovi"] = new SelectList(gradoviList);
return View();
}
and this is a view:
#foreach (var item in ViewData["Gradovi"] as IEnumerable<int>) ---> error appears here as null reference exception
{
<p>item</p>
}
I know that I have to parse data but don't have idea what did I do wrong
The ViewData item with the key "Gradovi" is typeof SelectList, so it would need to be
#foreach (var item in ViewData["Gradovi"] as SelectList)
{
<p>#item.Value</p> // or #item.Text
However there is no point generating IEnumerable<SelectListItem> (which is what SelectList is) when you do not need it, and you should be passing your model to the view. Your code in the controller should be
public ActionResult Index()
{
IEnumerable<int> model = db.Gradovi.Select(x => x.ID);
return View(model);
}
and in the view
#model IEnumerable<int>
#foreach(var item in Model)
{
<p>#item</p>
}
Your code can work like you have it, but I am going to modify it a bit and give you some pointers. I am supplying an answer based on what I see in your post, not what I think you want to achieve at a later stage. There are many ways to accomplish a goal, I will select the simplest way that I will normally use:
public ActionResult Index()
{
// You will have a repository layer for this part
GradDBContext db = new GradDBContext();
// Get a list of your items
List<Grad> gradovis = db.Gradovi.ToList();
// I never work with view data, I just pass my view model to the view
// This way you now have more data to display on the screen (if you need more)
return View(gradovis);
}
And then your view could look like this:
#model List<Project.Model.Grad>
#foreach (var grad in Model)
{
<p>#grad.ID</p>
}

Using part of a view in a different controller

I want to do the following and I can't figure it out. I have a controller with a view that shows a list of data. I would like to show that list of data on the home page. Is there any way to use the view of that list of data in the controller of the home page?
You want to achieve two (or more) models to render in one view? If yes, then here is your answer.
Let's suppose that you have two models, Book and Movie
public class Book
{
public int BookId { get; set; }
public string BookTitle { get; set; }
}
public class Movie
{
public int MovieId { get; set; }
public string MovieTitle { get; set; }
}
And then you want to get all Books and all Movies in one view. So create new class (for example in new folder named ViewModels and your class name can be anything, but let's name it for example ViewModel. In your class ViewModel write your Book and Movie model.
public class ViewModel
{
public Book Book { get; set; }
public IEnumerable<Book> Books { get; set; }
public Movie Movie { get; set; }
public IEnumerable<Movie> Movies { get; set; }
}
If you want also to display list you need to specify IEnumerable list, here is for Books and Movies.
And finally in your controller you can simply write:
public ActionResult Index()
{
var viewModel = new ViewModel
{
Movies = db.Movies.ToList(),
//you can also do this:
Movies = db.Movies.Where() //and so on
Books = db.Books.ToList()
};
return View(viewModel);
}
And #model for your view will be
#model MovieSubtitles.ViewModels.ViewModel
Hope it helps.
So you're saying you currently have something like:
public DataController() {
public ActionResult Index()
{
.. load data
return View(data);
}
}
If you convert data list to a PartialView you can then use that in any other view, eg:
public DataController() {
public ActionResult Index()
{
return View();
}
public ActionResult DataPartial()
{
.. load data
return Partial(data);
}
}
then in your original view, move out just the parts related to data into DataPartial.cshtml and in index.cshtml add call to the action:
#Html.Action("DataPartial");
You can then re-use this partial/action anywhere you want by calling it as above, but also specifying the controller
public HomeController() {
public ActionResult Index()
{
return View();
}
}
and home\index.cshtml:
#Html.Action("DataPartial", "Data")
Thanks, I figured it out. I made a partial view and I implemented that partial view in both index views (from home and the actual page of the list of data)

Using DBContext to Select Fields

I've got a couple questions regarding DBContext and achieveing my desired Results.
I can retrieve data like this
---Model
public class InvoiceModel
{
[Key]
public int? Invoice_Number { get; set; }
public decimal Amt_Total { get; set; }
public decimal Amt_Due { get; set; }
public decimal Amt_Paid { get; set; }
public List<InvoiceModel> GetInvoice()
{
using (VuittonEntities db = new VuittonEntities())
{
return (from inv in db.Invoice
select new InvoiceModel
{
Invoice_Number = inv.Invoice_,
Amt_Total = inv.AmountTotal,
Amt_Due = inv.AmountDue,
Amt_Paid = inv.AmountPaid
}).ToList();
}
}
--- Controller
public ViewResult Index()
{
var data = new InvoiceModel().GetInvoice();
return View(data);
}
This is pretty much standard LinQ and it returns my Invoice table with the 4 fields I selected. But now I want to achieve this using DB Context. So I added this new Class to my controller and called it in the view like this.
Controller
public class VuittonEntities : DbContext
{
public DbSet<InvoiceModel> Invoice { get; set; }
}
View
public ViewResult Index()
{
VuittonEntities db = new VuittonEntities();
return View(db.Invoice.ToList());
}
It returns the Entire table and I have to comment out my List'InvoiceModel' class
Assumptions:
VuittonEntities is my Connection String Name,
Invoice is the table
Vuitton is my .edmx class --
I heard that this can be achieved without having to use a Select Statement. It appears I am not linking my model class to a LinQ entity but when I add my context class, it throws errors on my inv."FieldName" columns in my List{InvoiceModel} Class.
TLDR Version:
How Can I return selected fields from DbContext Class instead of entire table
Why does adding a DBContext class raise errors on my List(ModelClass) fields
If you don't want the entire table, then don't just call ToList() on the DbSet, as that will just grab all of the table as you have seen.. You had it right when using Select, since the Select statement is meant to create a projection from one set of data into a new form (new class, model, anonymous object).

MVC - Multiple models in a view

I'm using MVC (for the first time) with Entity framework, Database first
What I want to do is display data from a database in a single view. I created the database first, then I made a ADO.NET Entity Data Model based from the database that contains all the tables. I then created a Index view that was strongly typed with my Entity Data Model as model.
In my Index I have at the top
#model IEnumerable<Forum6.Models.Forum>
This allows me to get the rows from the table "Forum" from my database. If I try to add an extra model I get I get this error message when I run:
Line 1: #model IEnumerable<Forum6.Models.Forum>
Line 2: #model2 IEnumerable<Forum6.Models.Post>
Parser Error Message: Only one 'model' statement is allowed in a file.
After searching for an answer I found this: Two models in one view in ASP MVC 3
The answer was to create a ViewModel (ParentModel) that contained all the Models (Tables).
This is the ViewModel I created:
public class ViewModel
{
public IEnumerable<Forum6.Models.Forum> Forum { get; set; }
public IEnumerable<Forum6.Models.Post> Post { get; set; }
public IEnumerable<Forum6.Models.Topics> Topics { get; set; }
public IEnumerable<Forum6.Models.Users> Users { get; set; }
public IEnumerable<Forum6.Models.PrivMsg> PrivMsg { get; set; }
public IEnumerable<Forum6.Models.Permission> Permission { get; set; }
}
I edited my controller to look like this:
public class HomeController : Controller
{
// ForumDBEntities old_db = new ForumDBEntities();
ViewModel db = new ViewModel();
public ActionResult Index()
{
return View(db);
}
}
Then replaced the old Index view with a new strongly typed view that used the ViewModel as model. Which contains:
#model IEnumerable<Forum6.Models.ViewModel>
Trying to run this gives me this error:
The model item passed into the dictionary is of type 'Forum6.Models.ViewModel', but this dictionary requires a model item
of type
'System.Collections.Generic.IEnumerable`1[Forum6.Models.ViewModel]
How do I make the "ViewModel" enumarable? Or is my error elsewhere?
You'll need to change #model IEnumerable<Forum6.Models.ViewModel> to #model Forum6.Models.ViewModel as you're wrapping your IEnumerables inside a single ViewModel.
A good rule of thumb is to have a 1:1 relationship between your ViewModel and View.
This might be a good read for you: http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/ (just ignore the automapper part if you don't want to go that route)
You'll also need to put in actual data in your ViewModel since
ViewModel db = new ViewModel();
public ActionResult Index()
{
return View(db);
}
will just give your view an empty ViewModel.
One way to do it would be.
public ActionResult Index()
{
var model = new ViewModel
{
Forum = db.GetForum(),
Post = db.GetPost(),
Topic = you get the idea
};
return View(model);
}
One last thing when naming properties or variables in general you should use the plural verb when it contains a list. So your ViewModel would be.
public class ViewModel
{
public IEnumerable<Forum6.Models.Forum> Forums { get; set; }
public IEnumerable<Forum6.Models.Post> Posts { get; set; }
public IEnumerable<Forum6.Models.Topics> Topics { get; set; }
public IEnumerable<Forum6.Models.Users> Users { get; set; }
public IEnumerable<Forum6.Models.PrivMsg> PrivMsgs { get; set; }
public IEnumerable<Forum6.Models.Permission> Permissions { get; set; }
}
Change #model IEnumerable<Forum6.Models.ViewModel> to #model Forum6.Models.ViewModel as you are passing a single instance of a ViewModel class and not a collection of them.
All your collections are passed in a single instance of a view model.

Adding the results of two queries to ViewData.Model

I have the following code in my controller:
public ActionResult Details(int id)
{
var dataContext = new BuffetSuppliersDBDataContext();
var supplier = (from m in dataContext.BO_Suppliers
where m.SupplierID == id
select m).FirstOrDefault();
ViewData.Model = supplier;
return View();
}
This renders a view which contains the properties returned from the linq to sql query. What I need to do now is add another query which will return x amount of ratings for each supplier, i will then loop through the records in the view and display the ratings.
How can I push the results of my ratings query into the view along with what is already there?
Your best option would to be create a class that you can pass into your view.
public class SupplierDetail
{
public Supplier { get; set; }
public SupplierRating { get; set; }
}
public class SupplierDetailViewData
{
public IEnumerable<SupplierDetail> SupplierDetails { get; set; }
}
Then in your controller action use a join and select a new SupplierDetail class in the LINQ query. After that you can create a strongly-typed view by using the code-behind and changing it to this...
public partial class Details : ViewPage<SupplierDetailViewData>
{
}
After that, in your view -- ViewData.Model will be SupplierDetailViewData. Of course the second part is optional but it does make for better compile-time validation.

Resources