1

I am using MVC3, Razor, C#.

I have a some Razor code which include some LINQ. It tries to get a value from a List. Sometimes the List is null. At present the application is raising a null exception due to this ie "myCustomers" is null.

The code:

Model.myCustomers.First().Name

Basically "myCustomers" is defined as:

public List<Customer> myCustomers

And populated by a "LINQ to Entity" Query.

If "myCustomers" is null, how can I ensure the razor code does not crash. I do not want to write lots of "if (Name!=null)" type blocks for each property. I cannot iterate through all the properties due to layout design issues. So I need to alter:

Model.myCustomers.First().Name

in some way.

Hopefully this question is not too confusing !

many thanks in advance.

EDIT 1

I like the logic with not returning nulls, but empty lists. I tried using something like

return this._myCustomers ?? Enumerable.Empty<Customers>().ToList(); 

It would be ideal to have someway to test this in the one line of LINQ in the Razor page for being empty rather than in an "IF" block.

EDIT 2

    public static TValue SafeGet<TObject, TValue>(
        this TObject obj,
        Func<TObject, TValue> propertyAccessor)
    {
        return obj == null ? default(TValue) : propertyAccessor(obj);
    }

So:

   Model.myCustomers.FirstOrDefault().SafeGet(m=>m.Name)
SamJolly
  • 6,347
  • 13
  • 59
  • 125

3 Answers3

2

Collection or enumerable should never return null value for best practice.

Once you make sure that myCustomers is not null, you will only need to check myCustomers's first item is not null.

var customer = Model.myCustomers.FirstOrDefault();
if (customer != null)
{
   var name = customer.Name;
}
Community
  • 1
  • 1
Win
  • 61,100
  • 13
  • 102
  • 181
  • I like the logic here, and have added EDIT 1 with code. Just trying to test this "empy" code in the one line rather than an "if" block. Is this not possible? Many thanks. – SamJolly Oct 03 '13 at 22:20
  • `return this._myCustomers ?? new List();` is also fine. – Win Oct 03 '13 at 22:29
  • OK, thanks for this. Yes I discovered this. How could I use my one liner in the Razor view which could check for empty lists that this would produce. If found then perhaps write out nothing. I was rather hoping to not use an "if" block, but rather something more succinct? – SamJolly Oct 03 '13 at 22:32
  • 1
    I used an extension method that I forgot I had, but originally sourced from SO, so I have posted it under EDIT2. Interestingly, since I was writing a Razor View, there was the option of just creating 2 block of HTML, one with to process when records present and the other when records absent. So clearly a choice between clever LINQ or copy/paste HTML although the later is simple it does seem more duplicated and less eloquent. Thanks again. Learnt much from this question – SamJolly Oct 03 '13 at 23:13
1

I cannot iterate through all the properties due to layout design issues.

I'm not exactly clear on what this means, but could you not do something like this?

@if (Model.myCustomers == null || !Model.myCustomers.Any())
{
    <p>No customer found.</p>
}
@else
{
    [ put the markup for each property here ]
}
devuxer
  • 41,681
  • 47
  • 180
  • 292
  • Thanks for this. This did give me the idea of copying and pasting 2 bits of HTML, one for records present, and the other when absent. However the code could get a bit duplicated. Thanks again. – SamJolly Oct 03 '13 at 23:14
1

If your collection is not null, then in your razon view you can use

 Model.myCustomers.Any() ? Model.myCustomers.First().Name : string.Empty;

If for some reason you can not avoid your collection to be null, I guess you can do something like this.

 Model.myCustomers == null ? string.Empty : Model.myCustomers.Any() 
       ? Model.myCustomers.First().Name : string.Empty;
Esteban Elverdin
  • 3,552
  • 1
  • 17
  • 21
  • Thanks for this. Totally get the logic. I ended up going with an extension method which makes it more succinct. Thanks again. – SamJolly Oct 03 '13 at 23:15