ASP.Net Object is set back to null after OnGet() method

I build a shopping website and I encountered this error when I tried to post some data.The weird thing is the object apparently is null, even though, I can place the product’s name,price,photo and quantity on the page.I have a product class and a product model class which contains a list of products.In the product model class constructor I create the list with the products that I want to display on the site.Anyway, I have the “Clothing” page which has a list of “Product” objects and it uses the ProductModel class to access the product list which has all the data regarding the products that I want to display.When I used a breakpoint to check if the products are sent to the “Clothing” page, I found out that the Product list is null.

In the “Clothing” page model the ProductModel object is first instantiated to null then the constructor kicks in.The list is created with the objects that I put in there and the Product list on the “Clothing” page has the values that were previously created and everything is fine.After the page page loads the Product list on the “Clothing” page is set back to null.

I will provide the code that I’ve written:

public class Product
    {
        public string ID { get; set; }
        public string Name { get; set; }

        public string Photo { get; set; }
        public double Price { get; set; }

        public int Quantity { get; set; }
        public Product()
        {
            
        }
    }

The product model class:
 public class ProductModel
        {
            public List<Product> Products { get; set; }
            public ProductModel()
            {
                Products = new List<Product>()
                {
                    new Product{
                        ID="1",
                        Name="Tommy Hilfiger T-Shirt",
                        Photo="/lib/tommyH.jpg",
                        Price=120,
                        Quantity=0
                    },
                    new Product{
                        ID="2",
                        Name="Tommy Hilfiger T-Shirt 2",
                        Photo="/lib/h6.jpg",
                        Price=120,
                        Quantity=0
                    },
                    new Product{
                        ID="3",
                        Name="Tommy Hilfiger T-Shirt 3",
                        Photo="/lib/h3.jpg",
                        Price=120,
                         Quantity=0
                    },
                    new Product{
                        ID="4",
                        Name="Tommy Hilfiger T-Shirt ",
                        Photo="/lib/tommyH.jpg",
                        Price=120,
                           Quantity=0
                    },
                };
            }
    
            public List<Product> findAll()
            {
                return this.Products;
            }
    
            public Product find(string id)
            {
                return this.Products.Where(p => p.ID == id).FirstOrDefault();
            }
    
        }

This is the code behind the “Clothing” page:
 public class ClothingModel : PageModel
    {
        public List<Product> Products { get; set; }
        public void OnGet()
        {
            ProductModel productModel = new ProductModel();
           
            Products = productModel.findAll();
        }

        public void OnPostAdd(string ID)
        {
            Product toBuy = Products.Where(p => p.ID == ID).FirstOrDefault();
            toBuy.Quantity++;
            List<Product> Stored = SessionHelper.GetObjectFromJson<List<Product>>(HttpContext.Session, "Products");
            Stored.Add(toBuy);
            SessionHelper.SetObjectAsJson(HttpContext.Session, "Products", Stored);
        }
    }

And finally here is how I display the products on the page:
 <div class="card-deck">
        @foreach (var product in Model.Products)
        {
            <div class="card">
                <img src="@product.Photo" class="card-img-top">
                <div class="card-body">
                    <h5 class="card-title">@product.Name</h5>
                    <p class="card-text">@product.Price</p>
                    <input type="hidden" value="@product.ID" />
                    <form method="post" asp-page-handler="add">
                        <button class="btn btn-primary" type="submit" asp-route="@product.ID">Buy</button>
                    </form>
                </div>
            </div>
        }

    </div>

The problem occurs in the @foreach (var product in Model.Products) statement. It says that the Products in Model.Products has a null value.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I tried your code and the same problem as yours appeared. Seems the route is incorrect, the Post Add handler is not triggered. You should remove asp-route attribute from the button.

<div class="card-deck">
@foreach (var product in Model.Products)
{
    <div class="card">
        <div class="card-body">
            <h5 class="card-title">@product.Name</h5>
            <p class="card-text">@product.Price</p>
            <form method="post" asp-page-handler="Add">
                <input type="hidden" value="@product.ID" name="ID" />
                <button class="btn btn-primary" type="submit">Buy</button>
            </form>
        </div>
    </div>
}
</div>

The code behind the “Clothing” page:
public class ClothingModel : PageModel
{
    public List<Product> Products { get; set; }
    public void OnGet()
    {
        ProductModel productModel = new ProductModel();
        Products = productModel.findAll();
    }

    public void OnPostAdd(string  ID)
    {
        ProductModel productModel = new ProductModel();
        Products = productModel.findAll();
        Product toBuy = Products.Where(p =>p.ID==ID).FirstOrDefault();
        //your code
    }
}

Result:

ASP.Net Object is set back to null after OnGet() method

Method 2

Requests in general are contextless, so unless you store Products somewhere they will be null everytime you make new request.
So you have 2 problems: Not hitting your post method and not “reloading” Producs.

First problem is you are not hitting your post method OnPostAdd (you should verify with breakpoints) and are instead hitting default OnPost, which since you didn’t define it, goes straight to rendering your view and because asp.net is contextless Products is null and you get NullReferenceException.

If you wish to “disable” default OnPost you should add public IActionResult OnPost() => NotFound(); to your page model, this will also verify that you are hitting the default one.

Second problem, Producs are null in your post method, so you have to load them again otherwise it you will endup with same exception on Products.Where(p => p.ID == ID)

Method 3

You only filled Products property but never have sent it to the view!
you should change your “onGet()” method to:

public void OnGet()
     {
         ProductModel productModel = new ProductModel();
         Products = productModel.findAll();
         return View(Products); 
     }

and also add something like below line at top of razor file:
 @model IEnumerable<Product>

then Model exactly refers to IEnumerable<Product> and finally you can use Model instead of Model.Products in your Foreach instruction. something like this:
     @foreach (var product in Model)
      {
        //...
      }

good luck


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x