简体   繁体   中英

How pass a model to a view .NET Core Entity Framework

I try to learn Entity Framework and I like to understand a basic concept.

In a test program I have this code:

ApplicationDbContext.cs

  public class ApplicationDbContext : DbContext
  {
        public DbSet<Book> Books { get; set; }
  }

BooksController.cs

public IActionResult Index()
{
    ViewBag.Books = _db.Books.ToList();
    return View();
}

index.cshtml

<br />
<div class="container row p-0 m-0">
    <div class="col-6">
        <h2 class="text-info">Book List</h2>
    </div>
    <div class="col-3 offset-3">
        <a asp-action="Upsert" asp-controller="Books" class="btn btn-info form-control text-white">
            Add New Book
        </a>
    </div>

    <div class="col-12 border p-3">
        <table id="DT_load" class="table table-striped table-bordered" style="width:100%">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Author</th>
                    <th>ISBN</th>
                    <th>IdCat</th>
                    <th>DescCat</th>
                    <th></th>
                </tr>

                @foreach (var book in ViewBag.Books)
                {
                <tr>
                    <td>@book.Name</td>
                    <td>@book.Author</td>
                    <td>@book.ISBN</td>
  
                    <td>
                        <div class="text-center">
                            <a href="/Books/Upsert?id=@book.Id" class='btn btn-success text-white' style='cursor:pointer; width:70px;'>
                                Edit
                            </a>
                            &nbsp;
                            <a class='btn btn-danger text-white' style='cursor:pointer; width:70px;'
                               onclick= "/books/Delete?id=@book.Id">
                                Delete
                            </a>
                        </div>



                    </td>
                </tr>
                }

            </thead>
        </table>
    </div>
</div>

This code works like I expect and show a grid of all books.

But frankly I don't think this is the right way to use controller and models.

I like to pass the list in the view:

   return View(_db.Books.ToList());

or with another format and use it as model by adding in the index.cshtml a line like this:

@model "my parameter"

In short at the place of ViewBag I like to use a model.

First of all, I ask: Is correct what I like to do?

Or in this case I can keep the ViewBag because the code work and this approach is correct?

This question, is not only to find a worked solution, but to find the best practice to follow the MVC concepts.

Thanks !

You can try it as follows.

Your controller

public IActionResult Index()
{
    var books = _db.Books.ToList();
    return View(books);
}

View

@model IEnumerable<YourNamespace.Models.Book>

@foreach (var book in Model)
{
<tr>
    <td>@book.Name</td>
    <td>@book.Author</td>
    <td>@book.ISBN</td>

    <td>
        <div class="text-center">
            <a href="/Books/Upsert?id=@book.Id" class='btn btn-success text-white' style='cursor:pointer; width:70px;'>
                Edit
            </a>
            &nbsp;
            <a class='btn btn-danger text-white' style='cursor:pointer; width:70px;'
               onclick= "/books/Delete?id=@book.Id">
                Delete
            </a>
        </div>
    </td>
</tr>
}

First of all, I ask: Is correct what I like to do?

Yes, most developers prefer typed view models over ViewBag for non-trivial views. This way the compiler can help you finding typos in your view and IDEs can provide itellisense.

but I need to pass a list or similar not a class

That doesn't matter. You provide an instance of "some class" to your view. If it's a list, "some class" = List<Book> .

 // in your view
 @model System.Collections.Generic.List<MyApp.Models.Book>

 // loop
 @foreach(var book in Model) 

(you'll have to adjust the namespace)

But...

In many cases you'll need more than just the list, so it helps to have a separate view model class, which can be as simple as

public record BooksListViewModel(List<Book> Result);

// in your controler
return View(new BooksListViewModel(books));

// in your view
@model WebApplication1.ViewModels.BooksListViewModel

@foreach(var book in Model.Result)

Note that I've used the new record feature of C# 9. If you're on an older version, you'll have to create a "normal" class with a single property "Result". See https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#record-types

The best practice to follow is to create a view model and use that view model for the view. This allows you to add new features down the line with minimal extra work. Generally you will have a different view for add/edit, delete, display, etc.

Model

public class BooksViewModel
{
    public List<Book> books = null;
}

Controller

public IActionResult Index()
{
    var viewModel = new BooksViewModel();
    viewModel.books = _db.Books.ToList();

    return View(viewModel);
}

View

@model BooksViewModel

@foreach (var book in Model.books)
{
    
}

Now if you want to add some other data to this view, you just add it to the model and populate it in the controller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM