Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

odd nullreference error at foreach when rendering view

This error is so weird I Just can't really figure out what is really wrong!

In UserController I have

public virtual ActionResult Index()
{
    var usersmdl = from u in RepositoryFactory.GetUserRepo().GetAll()
                   select new UserViewModel
                   {
                       ID = u.ID,
                       UserName = u.Username,
                       UserGroupName = u.UserGroupMain.GroupName,
                       BranchName = u.Branch.BranchName,
                       Password = u.Password,
                       Ace = u.ACE,
                       CIF = u.CIF,
                       PF = u.PF
                   };
    if (usersmdl != null)
    {
        return View(usersmdl.AsEnumerable());
    }
    return View();
}

My view is of type @model IEnumerable<UserViewModel> on the top.
This is what happens:

alt text

Where and what exactly IS null!?

I create the users from a fake repository with moq. I also wrote unit tests, which pass, to ensure the right amount of mocked users are returned.

Maybe someone can point me in the right direction here? Top of the stack trace is :

at lambda_method(Closure , User )
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at ASP.Index_cshtml.Execute() 

Is it something to do with linq here? Tell me If I should include the full stack trace.


Edit
<BangsHeadOnWall /> Wow, I cannot believe it was u.UserGroupMain.GroupName thanks @Lunivore.
It was a mockup repo, and I had a unit test to check if the mock repo user had a mock instance of UserGroupMain but I didn't Assert if the wee property GroupName had been set!

Thanks @RPM1984 you're suggestion got the code to break in the controller itself. Plus I learnt something new.

Thanks @Mikael, first time I used the immediate window wow its cool! =D

Guess you live, code and learn!

like image 780
gideon Avatar asked Dec 23 '10 11:12

gideon


3 Answers

Yeah, it got something to do with linq. Linq doesn't execute the query before you use it. So when you loop over it the query is run and for some reason it crashes.

What is GetAll returning? One thing you could do is to place a breakpoint inside Index() and when it breaks write this in the immediate window.

>RepositoryFactory.GetUserRepo().GetAll().ToList()

If you can't find the Immediate window you can open it by writing

>immed

in the findbox(in the top of VS)

If that doesn't crash the problem is probably in the linq inside Index(). From what I can see I would suspect that u.UserGroupMain or u.Branch is null. But hard to tell without more info.

like image 118
Mikael Eliasson Avatar answered Nov 06 '22 09:11

Mikael Eliasson


Change this line:

return View(usersmdl.AsEnumerable());

To this:

return View(usersmdl.ToList());

Why?

From MSDN:

The AsEnumerable(Of TSource)(IEnumerable(Of TSource)) method has no effect other than to change the compile-time type of source from a type that implements IEnumerable(Of T) to IEnumerable(Of T) itself.

In English - Because .AsEnumerable() converts to IEnumerable<T>, but IQueryable<T> already implements IEnumerable<T>, so the query is not being materialized - and is being lazily evaluated in the View when you enumerate the items in the foreach. Classic trick of LINQ deferred execution.

This is why i love Resharper - it will tell you the AsEnumerable() call is redundant - then it will become much more obvious your query is being deferred.

.ToList() will fire the query before it gets to the View, and still implements IEnumerable<T> so your model binding need not change.

like image 40
RPM1984 Avatar answered Nov 06 '22 07:11

RPM1984


Check that the UserGroupMain and Branch you've set up in your users aren't null:

                   UserGroupName = u.UserGroupMain.GroupName,
                   BranchName = u.Branch.BranchName,

If that fixes your problem, Mikael's answer explains why it was happening there and not further up in the query.

like image 1
Lunivore Avatar answered Nov 06 '22 07:11

Lunivore