locked
Query data from Database directly in Razor cshtml ? RRS feed

  • Question

  • User-1370514677 posted

    Hi everyone,

    I'd like to print every "Message" entities which are present in my "Message" Table (ASP.NET Core MVC with EF Core):

    Message model :

    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace WebApp.Models
    {
      public class Message
      {
        public int Id { get; set; }
        [Required]
        public string Author { get; set; }
        [Required]
        public string Content { get; set; } 
      }
    }

    CSHTML page :

    @{
        Layout = "_Layout";
        ViewData["Title"] = "WebApp";
    }
    
    @section site_content{
        <p>Welcome on Message</p>
    
        <form asp-controller="Message" asp-action="PublishMessage" method="POST">
            @model WebApp.Models.Message
            <label asp-for="Author">Author : </label>
            <input name="Author" type="text">
    
            <label asp-for="Content">Content : </label>
            <input name="Content">
    
            <input value="Publish" type="submit">
        </form>
    
        @using WebApp.Data
        @{
                var db = new WebAppContext(new DbContextOptions<WebAppContext>{});
                var Messages = db.Message.ToList();
        }
    
        @foreach (var Message in Messages)
        {
            <div>
                <p>Author : </p>
                <p>@Message.Author</p>
    
                <p>Message</p>
                <p>@Message.Content</p>
            </div>
        }
    }

    Actually the code above doesn't work, can I directly call a method from the MessageController instead ? (I read that it is a bad design practice so I've tried to avoid it).

    Thanks in advance for your help

    Friday, December 18, 2020 11:13 AM

Answers

  • User-1370514677 posted

    EDIT :

    I found the solution:

            @using WebApp.Models
            @foreach(var message in (List<Message>)ViewData["message_list"])
            {
                <p>Title : </p>
                <p>@message.Title</p>
    
                <p>Content: </p>
                <p>@message.Content</p>
            }

    I basically had to cast the type of my ViewData object (in this case, a List<Message>).

    I also had to specify where to find my Message model, at first I thought that using @model would be the solution but no, I had to use @using

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, December 19, 2020 5:13 PM

All replies

  • User475983607 posted

    You are not following standards or fundamentals which has been pointed out several times in your recent posts.   The DbContext is passed to the constructor using dependency injection.  The Dbcontext configuration (connection string) is setup in the startup.  Model are populated in Actions or Razor Page code not the markup.

    I recommend going through a few beginning level tutorials rather than guessing how the framework works.  

    Fundamentals

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/?view=aspnetcore-5.0&tabs=windows

    Tutorials

    https://docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/?view=aspnetcore-5.0

    https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/?view=aspnetcore-5.0

    https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/intro?view=aspnetcore-5.0&tabs=visual-studio

    https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/?view=aspnetcore-5.0

    Friday, December 18, 2020 1:29 PM
  • User-474980206 posted

    If you don’t want to use the mvc pattern, then maybe you should switch to Razor pages instead. Also it’s a very bad practice to sync database queries with asp,net core.

    I know the sync methods where added for compatibility , but they should be marked obsolete.

    Friday, December 18, 2020 3:40 PM
  • User-1370514677 posted

    Hi @Bruce,

    I do want to use MVC pattern, I read again the beginner tutorials for ASP.NET Core MVC.

    So according to what I saw, I should use the ViewData dictionnary in order to send data from the Controller to the View : https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-view?view=aspnetcore-3.1&tabs=visual-studio-code#passing-data-from-the-controller-to-the-view

    Here is my rewrote code :

    Message.cs

    using System;
    
    namespace WebApp.Models
    {
        public class Message
        {
            public int Id { get; set; }
            public string Title { get; set; }
            public string Content { get; set; }
        }
    }

    HomeController.cs

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using WebApp.Data;
    using System.Linq;
    using System;
    using WebApp.Models;
    
    namespace WebApp.Controllers
    {
        public class HomeController : Controller
        {
            private readonly WebAppContext _context;
    
            public HomeController(WebAppContext context)
            {
                _context = context;
            }
    
            public IActionResult Index()
            {
                var db = _context;
                var message_list = db.Message.ToList();
    
                ViewData["message_list"] = message_list;
                
                return View();
            }
        }
    }

    Index.cshtml

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>WebApp</title>
        </head>
    
        <body>
            <form asp-controller="Message" asp-action="PublishMessage" method="POST">
                @model WebApp.Models.Message
                <label asp-for="Title">Title : </label>
                <br>
                <input name="Title" type="text">
                <br>
                <label asp-for="Content">Message : </label>
                <br>
                <input name="Content" type="text">
                <br>
                <input value="Publish" type="submit">
            </form>
    
            @foreach(var message in ViewData["message_list"])
            {
                <p>Title : </p>
                <p>@message.Title</p>
    
                <p>Content: </p>
                <p>@message.Content</p>
            }
        </body>
    </html>

    So, I now have my foreach loop set in order to loop through every message in my Message Table (sent from Controller to the View via ViewData["message_list"].

    Yet, I now get a compile error :

    Views\Home\Index.cshtml(24,33): error CS1579: foreach statement cannot work on variables with type object

    So the issue is here :

            @foreach(var message in ViewData["message_list"]) // do I have to cast a type like (type)ViewData["message_list"] ?
            {
                <p>Title : </p>
                <p>@message.Title</p>
    
                <p>Content: </p>
                <p>@message.Content</p>
            }

    Saturday, December 19, 2020 4:12 PM
  • User-1370514677 posted

    EDIT :

    I found the solution:

            @using WebApp.Models
            @foreach(var message in (List<Message>)ViewData["message_list"])
            {
                <p>Title : </p>
                <p>@message.Title</p>
    
                <p>Content: </p>
                <p>@message.Content</p>
            }

    I basically had to cast the type of my ViewData object (in this case, a List<Message>).

    I also had to specify where to find my Message model, at first I thought that using @model would be the solution but no, I had to use @using

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, December 19, 2020 5:13 PM