Nick
Nick

Reputation: 3965

ASP.NET MVC - Object reference not set to an instance of an object

I have recently taken over support of an ASP.NET MVC project, and am trying to work through some of the errors, one in particular has me stumped though.

We have a 'New' page to add new items, with the following code running when the page is posted:

[HttpPost]
public ActionResult New(RecordView i)
{
    if(ModelState.IsValid)
    {
        repository.AddRecord(i.DogIncident);

        return View("Index");
    }
    return View("Index");
}

However, when it tries to load the Index view, I get the following error: "Object reference not set to an instance of an object." and it points to the following block of code at the top of a file called RecordsView.cshtml:

@for (var i = 0; i < Model.Records.Count; i++)

The record does add correctly though, it just doesn't load the listings page correctly, and since this is just a "nice to have" I thought I'd simplify things by changing it so that it either returns some text which generates an error as it's expecting a boolean returned.

Any ideas on how to fix this please? I'm stumped.

Thanks!

Upvotes: 2

Views: 63019

Answers (7)

user14105450
user14105450

Reputation: 1

May be this is your answer...!Just look

   [HttpPost]

   public ActionResult New(RecordView)

   {
      if(ModelState.IsValid)

    {  
       repositry.AddRecord(i.DogIncident);

       return RedirectToAction("Index");
    }
  }

Upvotes: 0

Muhammad Mustafa
Muhammad Mustafa

Reputation: 171

i think you have collections are not instantiated, the error may be in models not in view models. this because when ever you have a collection you need to instantiate inside of constructor of that entity.

Upvotes: 0

ElliotSchmelliot
ElliotSchmelliot

Reputation: 8362

You mentioned that the record adds correctly, so you must be passing a valid record model into your view from some other action than the one provided.

If @for (var i = 0; i < Model.Records.Count; i++) is the cause of this error, my guess is that the model exists, but the Records property has not been set. One immediate work around would be checking the existence of this property before accessing it. For example:

if (Model.Records != null) {
    for (var i = 0; i < Model.Records.Count; i++) .....
}

Upvotes: 1

Murali Murugesan
Murali Murugesan

Reputation: 22619

Basically you may are trying to achieve PRG(Post/Redirect/Get) modal.

I guess, the problem is you are not sending the model for your GET request.

Post--> Save --> Redirect --> Load Data -->Assign to View in Index -->Access in view

//POST & REDIRECT

[HttpPost]
public ActionResult New(RecordView i)
{
    if(ModelState.IsValid)
    {
        repository.AddRecord(i.DogIncident);

        return RedirectToAction("Index");
    }
}

//GET

public ActionResult Index()
{
 var model=new MyViewModel();

 model.Records=repository.GetRecords(i.DogIncident);

 return View(model); //Assign to View in Index
}

Index.cshtml

 @model MyViewModel

 @for (var i = 0; i < Model.Records.Count; i++)

Upvotes: 2

John H
John H

Reputation: 14655

The flow of your code here doesn't look right:

[HttpPost]
public ActionResult New(RecordView i)
{
    if(ModelState.IsValid)
    {
        repository.AddRecord(i.DogIncident);

        return View("Index");
    }
    return View("Index");
}

From your description above, it sounds as though you're POSTing from your New view, to this New action, which should then redirect, when successful, to your Index action. Currently, the above code is not doing that, and it also fails to redisplay the form if the model isn't valid. It should probably look more like this:

[HttpPost]
public ActionResult New(RecordView i)
{
    if(ModelState.IsValid)
    {
        repository.AddRecord(i.DogIncident);

        return RedirectToAction("Index");
    }

    // Redisplay the `New` view, passing the model
    // back to it in order to repopulate the form
    return View(i);
}

The important distinction between return View(...) and return RedirectToAction(...) is that the latter will run the action and return the associated view. The former will simply return the view. That has implications in that if the Index action builds a model, and passes it to the Index view, none of that will happen if you simply return the view.

You could of course do something like:

return View("Index", new YourModelType());

but that isn't going to work if, as discussed above, your Index action performs some other data construction for your model, such as building drop down lists, which new YourModelType() wouldn't do.

Also, when data that is sent to a POST action is valid, you should be redirecting to another action (as I've done above), rather than simply returning a view, in order to conform with the Post-Redirect-Get pattern, which prevents some types of duplicate form submissions.

Upvotes: 4

Sergey Litvinov
Sergey Litvinov

Reputation: 7458

You display Index view, and seems that it requires some Model - Model.Records. And you don't pass it in this HttpPost action.

If you have action for that Index page, then you can just do

[HttpPost]
public ActionResult New(RecordView i)
{
    if(ModelState.IsValid)
    {
        repository.AddRecord(i.DogIncident);

        return RedirectToAction("Index");
    }
    return View(i);
}

It will just redirect a user to Index view, after creation of new RecordView item

Upvotes: 2

Matt Millican
Matt Millican

Reputation: 4054

If Records is a list, make sure your ViewModel has a constructor:

public class RecordView
{
    public List<Record> Records { get; set; }

    public RecordView()
    {
        Records = new List<Record>();
    }
}

Upvotes: 1

Related Questions