0

I have the following code in a Controller:

newclass.Brands = db.Brands.OrderByDescending(x => x.Brand1 != "Not classified").ThenBy(x => x.Brand1);

When I create a SelectList using this in the View:

@Html.DropDownList("Brand_id", new SelectList(Model.Brands, "Brand_id", "Brand1"), new {@class="dropdown_edit"})

It works perfectly - it places the list of brands in alphabetical order and the 'Not classified' option at the bottom of the list.

However, when I have this is the Controller:

newclass.Brands = db.Brands;

And this in the View:

@Html.DropDownList("Brand_id", new SelectList(Model.Brands.OrderByDescending(x => x.Brand1 != "Not classified").ThenBy(x => x.Brand1), "Brand_id", "Brand1"), new {@class="dropdown_edit"})

The DropDownList always defaults to the instruction in the ThenBy statement, it's as if the first OrderBy is overwritten by the ThenBy - which shouldn't be the case?

What am I missing?

EDIT: I'm using EF and the newclass is a Viewmodel derived from the EF class Brands. The class definition is:

 public class Class1
{
    public IEnumerable<Brand> Brands { get; set; }
}
  • Is this LinqToSql, or Entity Framework or... ? – Erik Philips Jan 21 '14 at 00:53
  • I have never seen a comparison operator in the OrderBy() fund. Not saying it isn't correct, but maybe EF handles this better than LINQ which is what would be processing this on the view rather than passed back to SQL – Tommy Jan 21 '14 at 04:44
  • Sorry, its using EF (I will edit to update the question). – user2000000 Jan 21 '14 at 15:00

1 Answers1

0

The reason is probably because Brands has not been queried yet when it gets to the View and it lost some of the db context. Views should always receive IEnumerable that are not deferred and already queried from EF, so you should force the execution on the controller:

In the controller:

newclass.Brands = db.Brands.ToList(); // Execute the query, do not use deferred query

Then the view will receive a simple IEnumerable and should do the ordering properly.

.OrderByDescending(x => x.Brand1 != "Not classified") will order with a new boolean field, with true values first. However, be sure that you did not mistyped the equation or the "Not classified" between the controller or the View.

See similar issue with boolean ordering: Linq order by boolean

I see nothing wrong with the code you posted, make sure you didn't mistyped something.

For case insensitive string related issues, you should use:

.OrderByDescending(x => !x.Brand1.Equals("Not classified", System.StringComparison.InvariantCultureIgnoreCase))
Community
  • 1
  • 1
Karhgath
  • 1,809
  • 15
  • 11
  • Forcing the execution on the controller doesn't change the outcome - still end up with the ThenBy statement overriding the OrderBy. – user2000000 Jan 21 '14 at 20:42
  • The order I want is for Brands to be ordered alphabetically from A to Z, with "Not Classified" at the bottom. It works fine when you order in the controller using the code above in the original question, but that exact same code gives you a different outcome in the View. I just want to know why. – user2000000 Jan 21 '14 at 20:58
  • Just updated. I see nothing wrong with the code you posted above, make sure it's not a typo on your side. – Karhgath Jan 21 '14 at 20:59
  • Ok, so it looks like it is a case issue. "Not classified" works as the comparison value in the Controller and by itself (i.e. not with ThenBy) in the View, but doesn't work with ThenBy in the view. I just checked the data and the value is actually "Not Classified" - capital "C". Which is sort of misleading as it should have originally failed in the Controller but didn't. – user2000000 Jan 21 '14 at 21:21
  • Probably the EF Linq provider is case insensitive and the Object LINQ provider is not. For strings, I always use : !x.Brand1.Equals("Not Classified", System.StringComparison.InvariantCultureIgnoreCase), this will ignore casing if you need it. – Karhgath Jan 21 '14 at 21:27