locked
Creating A Global Model, With No Associated Database Table RRS feed

  • Question

  • User-1580299748 posted

    Hello All,

    I am using ASP .Net Core 3.1 Razor Pages (non-MVC) with Entity Framework Core.

    Consider the following OnGet() Handler in an Index.cs file:

    public IActionResult OnGet()
    {
    var webRootPath = _hostingEnvironment.WebRootPath;
    var docsPath = Path.Combine(webRootPath, "documents");

    var DocumentInformation = Directory.GetFiles(docsPath, "*.*", SearchOption.TopDirectoryOnly);

    return Page();
    }

    This code returns an array of files in the wwwroot/documents directory.

    This array is read into the local variable  var DocumentInformation

    My question:

    Instead of using a local variable, I would like to create a model, that can not only be passed back to the .cshtml file, but can be used in other parts of my application.

    I don't want the model to be used to create a database table.

    I would appreciate any guidance on how to accomplish this.

    Thanks in advance for your time....

    Friday, March 6, 2020 4:40 AM

All replies

  • User1120430333 posted


    I am using ASP .Net Core 3.1 Razor Pages (non-MVC) with Entity Framework Core.


    ASP.NET Razor pages is part of ASP.NET MVC using the ASP.NET MVC pipeline.

    namespace WebRazor3.x.Models
    {
       public class FilesObject
       {  
     
         private string _webRootPath;
         public FilesObject(string webrootpath)
         {
            _webRootPath = webrootpath;
         }
    
          public string [] Files { get; set; } = new string[1000];
    
          public void LoadFiles()
          {
    
            var docsPath = Path.Combine(_webRootPath, documents);
    
             Files = Directory.GetFiles(targetDirectory);
          }
        }
    }
    public IActionResult OnGet()
    {
        new FilesObj(_hostingEnvironment.WebRootPath).LoadFiles();
    
     // foreach it 
         foreach(string fileName in FilesObj.Files) 
         {
              // do something 
         }
    
     // you can also send it into a view on bind.
    
       [BindProperty]
       public string [] TheFiles = FilesObj.Files;
       return Page();
    }

    The above is just a possible way you can do it with a class called FilesObj you made in the Models folder that can be called from anywhere in Razor Pages project.

    Friday, March 6, 2020 8:47 AM
  • User753101303 posted

    Hi,

    You could also try https://www.learnrazorpages.com/advanced/dependency-injection that shows step by step how you cen generalize this kind of local code up to using "dependency injection" to provide services to classes needing them.

    Friday, March 6, 2020 10:06 AM
  • User-1580299748 posted

    Hello DA924...  Thanks for the reply.

    I tried the following:

    I created this class, in the Models folder:

        public class FilesObject
        {
            private string _webRootPath;
     
            public FilesObject(string webrootpath)
            {
                _webRootPath = webrootpath;
            }
     
            public string[] Files { get; set; } = new string[1000];
     
            public void LoadFiles()
            {
                var docsPath = Path.Combine(_webRootPath, "documents");
                Files = Directory.GetFiles(docsPath, "*.*", SearchOption.TopDirectoryOnly);
            }
        }

    In the OnGet() Handler of my Index.cs file I have the following

        [BindProperty]
        public FilesObject FilesObject { get; set; }

    <div>    public IActionResult OnGet()</div> <div>        {</div> <div>            new FilesObject(_hostingEnvironment.WebRootPath).LoadFiles();</div> <div>            return Page();</div> <div>        }</div>

    I call the .LoadFiles() Method, which correctly loads the names of the files into FilesObject

    However, when I try to use the FilesObject Class in my .csthml file I cannot.

    I thought I would be able to do something like this:

    @foreach (string fileName in FilesObject.Files)

    {

    }

    But I cannot, and am getting the following error:

    Error CS0103 The name 'FilesObject' does not exist in the current context

    Any further help appreciated.  Many thanks.

    Sunday, March 8, 2020 1:39 PM
  • User1120430333 posted

    You are not sending the FilesObj into the view, and the FilesObj just creates the array of file names it got from GetDirectory(). You are using the bound TheFiles array and sending it into the view that was populated by the FilesObj.Files that is an array, but you don't send in the FilesObj into the view. 

    [BindProperty]
    public string [] TheFiles = FilesObj.Files;

    It's similar as to what you see in the code as far as how the bound object gets to the view in the example, that was the AuthorVM VM=viewmodel is loaded by the GetAll() method and it was called by the OnGet in the Index page model. The GetAll() in is a class called AuthorDM that's in the Models folder. The AutorVM is passed into the view. You'll be passing TheFiles into the view that was bound in the pagemodel that was populated by FilesObj.Files after the FilesObj is instanced by the 'new' keyword and calls the LoadFiles().

    new FilesObj(_hostingEnvironment.WebRootPath).LoadFiles();

    That should be the first line of code executed in the pagemodel before you hit the line

    public string [] TheFiles = FilesObj.Files;  // that loads TheFiles fron The FilesObj.Files that was loaded by the LoadFiles().

    sing System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace WebRazor3.x.Models
    {
        public class AuthorVM
        {
            public class Author
            {
                public int AuthorID { get; set; }
    
                [Required(ErrorMessage = "First Name is required")]
                [StringLength(50)]
                public string FirstName { get; set; }
    
                [Required(ErrorMessage = "Last Name is required")]
                [StringLength(50)]
                public string LastName { get; set; }
            }
    
            public List<Author> Authors { get; set; } = new List<Author>();
        }
    }
    
     public AuthorVM GetAll()
            {
                var vm = new AuthorVM();
    
                var dtos = svc.GetAll().ToList();
    
                vm.Authors.AddRange(dtos.Select(dto => new AuthorVM.Author()
                {
                    AuthorID = dto.AuthorId,
                    FirstName = dto.FirstName,
                    LastName = dto.LastName
                }).ToList());
    
                return vm;
            }
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    using WebRazor3.x.Models;
    
    namespace WebRazor3.x.Pages.Author
    {
        public class IndexModel : PageModel
        {
            private readonly IAuthorDM _authorDm;
            public IndexModel(IAuthorDM authorDm)
            {
                _authorDm = authorDm;
            }
    
            [BindProperty]
            public AuthorVM AuthorVM { get; set; } 
            public IActionResult OnGet()
            {
                AuthorVM = _authorDm.GetAll();
                return Page();
            }
    
            public IActionResult OnGetDelete(int id)
            {
                _authorDm.Delete(id);
                return RedirectToPage("Index");
            }
        }
    
    @page
    @model IndexModel
    @{
        ViewData["Title"] = "Author Page";
    }
    
    <h1>Authors</h1>
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Authors</title>
    </head>
    <body>
       
            <a asp-page="/Author/Create">Create</a> 
    
            <br /><br />
            <table border="1" cellpadding="10">
                <tr>
                    <th>AuthorID</th>
                    <th>First Name</th>
                    <th>Last Name</th>
                    <th colspan="4">Actions</th>
                </tr>
                @foreach (var item in Model.AuthorVM.Authors)
                {
                    <tr>
                        <td>@item.AuthorID</td>
                        <td>@item.FirstName</td>
                        <td>@item.LastName</td>
                        <td>
                            <a href="/Author/Edit?id=@item.AuthorID">Edit</a>
                        </td>
                        <td>
                            <a href="/Author/Detail?id=@item.AuthorID">Detail</a>
                        </td>
    
                        <td>
                            <a href="/Author/Index?id=@item.AuthorID&handler=Delete"
                               onclick="return confirm('Are you sure, you want to delete this author?')">Delete</a>
                        </td>
                    </tr>
                }
            </table>
    </body>
    </html>
    
    

    Monday, March 9, 2020 3:30 AM