Search code examples
c#asp.net-mvc.net-coreviewmodel

NullReferenceException: Object reference not set to an instance of an object When accessing ViewModel list through controller


So my View Model is not giving my CSV file's information to the view correctly. I have already placed a break point and the List "Stocks" fills up nicely and I can even see all the values in public IEnumerable<Stock> Stocks { get; set; } However the var, ViewModel is null when I got to my controller? Any suggestions? Here is the View Model

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using StockApp.Models;
using System.Windows;
using System.IO;
using System.Text;
using CsvHelper;
using Microsoft.VisualBasic;


namespace StockApp.ViewModels.StockInfo
{
    public class StockInfoViewModel
    {
        public StockInfoViewModel()
        {
            List<Stock> Stocks = new List<Stock>();

            string file ="../StockApp/App_Data/companylist.csv";
            using(var reader = new StreamReader(file))
            {


                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    var values = line.Split(',');
                    Stocks.Add(new Stock { Name = values[1], Symbol = values[0] });
                }
            }

        }
        public IEnumerable<Stock> Stocks { get; set; }

    }
}

And Here is the Controller

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using StockApp.Models;
using System.Windows;
using System.IO;
using System.Text;
using CsvHelper;
using Microsoft.VisualBasic;

namespace StockApp.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult StockInfo()
        {
            var ViewModel = new ViewModels.StockInfo.StockInfoViewModel().Stocks;

            return View(ViewModel);
        }
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Register()
        {
            return View();
        }


        public IActionResult About()
        {
            ViewData["Message"] = "Your application description page.";

            return View();
        }

        public IActionResult Contact()
        {
            ViewData["Message"] = "Your contact page.";

            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }


        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

The Model

using System;
using System.Collections.Generic;

namespace StockApp.Models
{
    public class StockNamesModel
    {
        public List<Stock> Stocks {get; set;}

    }

    public class Stock 
    {
        public string Symbol{get; set;}
        public string Name {get; set;}
    }


}

Last but not least the Razor Code

@model StockApp.ViewModels.StockInfo.StockInfoViewModel
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

<h1>Our Advanced Algorithims To Buy and Sell These Stocks</h1>

<table class="table table-dark">
    <thead>
        <tr>
            <th scope="col">Symbol</th>
            <th scope="col">Name</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var stock in Model.Stocks)
        {
            <tr>
                <td>@stock.Symbol</td>
                <td>@stock.Name</td>
            </tr>
        }

    </tbody>
</table>

Any help would be apreciated, thank you!


Solution

  • You just need to change 2 things in your ViewModel

    ViewModel

    • Remove List<Stock> and assign directly, which looks like Stocks = new List<Stock>();
    • IEnumerable<Stock> to List<Stock> which becomes public List<Stock> Stocks { get; set; }


    Reason for null:

    List<Stock> Stocks scope is within the constructor and IEnumerable<Stocks> is not tracking List<Stock> Stocks

    And from your Controller you are trying to access the IEnumerable which is not assigned anything in the first place

    Updated Code:

    public class StockInfoViewModel
    {
        public StockInfoViewModel()
        {
            Stocks = new List<Stock>();
    
            string file ="../StockApp/App_Data/companylist.csv";
            using(var reader = new StreamReader(file))
            {
    
    
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    var values = line.Split(',');
                    Stocks.Add(new Stock { Name = values[1], Symbol = values[0] });
                }
            }
    
        }
        public List<Stock> Stocks { get; set; }
    
    }
    }