This project is read-only.

Method not supported by grid

Dec 17, 2013 at 11:24 AM
Hi

newbie question I am afraid..

In my grid in need to join some entities and return a value for a column. I have this:

columns.Add(u => u.UserProfiles.Where(p => p.PropertyDefinitionID == 107)).Titled("Blocked?").SetWidth(110).Sortable(true);

By when I run the app I get an error:

"Expression 'u => u.UserProfiles.Where(p => (p.PropertyDefinitionID == 107))' not supported by grid"}

I find that I can do this without trouble:

columns.Add(u => u.UserRoles.Count).Titled("#of roles").SetWidth(110).Sortable(true);

Can anyone explain what I am doing wrong or how to get around this?

thanks
Gus
Dec 18, 2013 at 5:35 PM
Hi,

To columns.Add method you need to pass epxression that specifies only property from your model. Grid will sort and filter by this property.

For example:
columns.Add(p => p.PropertyDefinitionID).Titled("Blocked?").SetWidth(110).Sortable(true); 
If you want to render custom content in the grid cell - use RenderValueAs method. Please see - https://gridmvc.codeplex.com/wikipage?title=Render%20button%2c%20checkbox%20etc%20in%20the%20grid%20cell&referringTitle=Documentation
Dec 19, 2013 at 9:31 AM
Edited Dec 19, 2013 at 9:32 AM
hi again

and thanks for the pointer.

I managed to achieve the desired result with a helper like this:
@helper CheckIfBlocked(User user)
{
    
    var blocked = user.UserProfiles.Where(o => o.UserID == user.UserID && o.PropertyDefinitionID == 107);

    var isBlocked= "False";
    foreach (var row in blocked) { isBlocked = row.PropertyValue; }


    if (isBlocked.ToUpper() == "FALSE")
    {
        <text></text>
    }
    else
    {
        <text>Blocked!!</text>
    }
}
And RenderValueAs like this:

 columns.Add(u => u.FirstName)
                .Titled("Status")
                .SetWidth(20)
                .RenderValueAs(u => CheckIfBlocked(u));
Marked as answer by angusbeare2013 on 12/19/2013 at 1:33 AM
Dec 29, 2013 at 11:29 PM
I realised later that this is not a good approach. I learned about view models and so built one of those which included the joined data in the initial query. That way the grid is not joining for each row.
Jan 9, 2014 at 3:00 AM
Hi,

It is not good idea to place business logic in your view. I recommend you to create own view model class like
public class MyGridRow
{
         //... properties

        public bool IsBlocked { get; set; }
}
And determine IsBlocked value in your controller. View will contains rules depending on IsBlocked property:
@helper CheckIfBlocked(MyGridRow row)
{
    if (!row.IsBlocked)
    {
        <text></text>
    }
    else
    {
        <text>Blocked!!</text>
    }
}
Jan 9, 2014 at 3:03 PM
yes, thanks for posting,

I already realised this, hence my comment abve!
Jan 10, 2014 at 3:53 AM
It seems no, because this lines of code:
var blocked = user.UserProfiles.Where(o => o.UserID == user.UserID && o.PropertyDefinitionID == 107);

    var isBlocked= "False";
    foreach (var row in blocked) { isBlocked = row.PropertyValue; }
represent the business logic to determine blocked user - should be placed in your BLL application layer, not in the view.
Jan 10, 2014 at 9:26 AM
Edited Jan 10, 2014 at 9:27 AM
Hi again

don't think I expressed myself well.. I realised this was a poor approach so:

I ditched the above code and created a view model:

public class ShowBlockedUsersViewModel
{
    public int UserId { get; set; }
    public string Username { get; set; }
    public string DisplayName { get; set; }
    public string LastIpAddress { get; set; }
    public string IsBlocked { get; set; }
    public int NPackages { get; set; }
    public int NAds { get; set; }
}
Then (in my User controller) I joined in the _IsBlocked property into the new model with some extra counts like this:
  // get all the users and join in the blocked profile property (107)
            var q = from u in qdb.Users
                    join up in qdb.UserProfiles on u.UserID equals up.UserID
                    join uap in qdb.omv_UserAdPackages on u.UserID equals uap.userID into packages
                    join ua in qdb.omv_UserAds on u.UserID equals ua.userID into ads
                    where up.PropertyDefinitionID == 107 
                    select new ShowBlockedUsersViewModel
                    {
                        UserId = u.UserID,
                        Username = u.Username,
                        DisplayName = u.DisplayName,
                        LastIpAddress = u.LastIPAddress,
                        IsBlocked = up.PropertyValue,
                        NPackages = packages.Count(p => p.Status == 1), // get count of active packages
                        NAds = ads.Count() // count of ads
                    };

            var o = q.OrderBy(x => x.Username); // order the users after the query to avoid that skip issue

            return View(o);
Then all I had to do was use the new View Model "ShowBlockedUsersViewModel" in my view/grid and it worked.

thanks again for your help and what is a great tool. It has saved me loads of time.

Gus