1

I have an entity called Lookup who has a complex Type Description with two string English and French. There has arise a time where no value will be store into the lookup. Now other entities have lookups as properties so we could have foo.Lookup.Description.English for example.

I'm trying to use a Web Grid to display the information being selected.

Originally my controller looked like

    public ViewResult Index()
    {
        var foos = db.Foos;

        return View(foo.ToList());
    }

and my view looked like

@model IEnumerable<Foo>

@{
    ViewBag.Title = "Index";
}

<h2>Stay Manager</h2>

@{
    var grid = new WebGrid(Model, defaultSort: "sortMe", rowsPerPage: 3);
    grid.GetHtml(htmlAttributes: new { id = "DataTable" });
}

@grid.GetHtml(columns: grid.Columns(
        grid.Column("Lookup.Description.English", "Column Header")
))

My issue is that Lookup can at times be null and ill will get an error saying the the Column Lookup.Description.English does not exist.

I found a solution but not a very elegant one and was hoping that there was a better a way. My solution was to change my controller action to

    public ViewResult Index()
    {
        var foos = db.Foos;

        foreach (Foo currentFoo in Foos.Where(s => s.Lookup == null))
        {                
            Foo.Lookup = new Lookup();
            Foo.Lookup.Description.English = "";
            Foo.Lookup.Description.French = "";             
        }

        return View(foos.ToList());
    }

Any suggestions on how to get the Web Grid to work better with null-able complex types?

tereško
  • 58,060
  • 25
  • 98
  • 150
Blast_dan
  • 1,135
  • 9
  • 18

1 Answers1

4

Not at all that familair with webgrid, but would the following be a solution for you? I made the following simple model:

public class Foo
{
    public string Name { get; set; }
    public Lookup Lookup { get; set; }
}

public class Lookup
{
    public string Name { get; set; }
    public Description Description { get; set; }
}

public class Description
{
    public string English { get; set; }
    public string French { get; set; }
}

controller action (i don't have a db, so I mocked some data):

public ViewResult Index()
{
    //var foos = db.Foos;

    var foos = new List<Foo>();

    foos.Add(new Foo { Name = "Foo1" });
    foos.Add(new Foo
    {
        Name = "Foo2",
        Lookup = new Lookup
        {
            Name = "Lookup2",
            Description = new Description
            {
                English = "englishFoo2",
                French = "frenchFoo2"
            }
        }
    });
    foos.Add(new Foo
    {
        Name = "Foo3",
        Lookup = new Lookup
        {
            Name = "Lookup3",
            Description = new Description
            {
                //English = "englishFoo3",
                French = "frenchFoo3"
            }
        }
    });
    foos.Add(new Foo { Name = "Foo4" });
    foos.Add(new Foo
    {
        Name = "Foo5",
        Lookup = new Lookup
        {
            Description = new Description
            {
                English = "englishFoo5",
                French = "frenchFoo5"
            }
        }
    });
    foos.Add(new Foo { 
        Name = "Foo6",
        Lookup = new Lookup
        {
            Name = "Lookup6"
        }
    }); 


    return View(foos);
}

So, I now have Foos with or without Lookups (with or without Description).

The view is as follows:

@model IEnumerable<Foo>

@{
    var grid = new WebGrid(Model, defaultSort: "sortMe", rowsPerPage: 10);
    grid.GetHtml(htmlAttributes: new { id = "DataTable" });
}
@grid.GetHtml(
columns: grid.Columns(
    grid.Column(
        columnName: "Name",
        header: "Foo"
    ),
    grid.Column(
        columnName: "Lookup.Name",
        header: "Lookup",
        format: @<span>@if (item.Lookup != null)
                       { @item.Lookup.Name }
        </span>
    ),
    grid.Column(
        columnName: "Lookup.Description.English",
        header: "Description.English",
        format: @<span>@if (item.Lookup != null && item.Lookup.Description != null)
                       { @item.Lookup.Description.English }
        </span>
    ),
    grid.Column(
        columnName: "Lookup.Description.French",
        header: "Description.French",
        format: @<span>@if (item.Lookup != null && item.Lookup.Description != null)
                       { @item.Lookup.Description.French }
        </span>
    )
)
)

which works just fine for me (Asp.Net MVC 3), it procudes the following html:
[snip]

<tr>
    <td>Foo4</td>
    <td><span></span></td>
    <td><span></span></td>
    <td><span></span></td>
</tr>
<tr>
    <td>Foo5</td>
    <td><span></span></td>
    <td><span>englishFoo5 </span></td>
    <td><span>frenchFoo5 </span></td>
</tr>
<tr>
    <td>Foo6</td>
    <td><span>Lookup6</span></td>
    <td><span></span></td>
    <td><span></span></td>
</tr>

[/snip]

Major Byte
  • 4,101
  • 3
  • 26
  • 33
  • Thanks but no go. The model when working with a grid is an Ienumerable. The web grid doesn't allow you to give individual logic for each row. I think im stuck with my current situations.. – Blast_dan Sep 06 '11 at 13:45
  • Do you mean that the actual view your are using has its model defined as IEnumerable instead of IEnumerable (or whatever entity you want)? – Major Byte Sep 06 '11 at 16:52
  • No its IEnumerable but since its a collection you cant access properties of an individual Foo until one is selected. The web grid doesn't give "Row Specific" properties of the item to test against. sorry if that's confusing. – Blast_dan Sep 06 '11 at 17:16
  • I updated my answer, with a working example, in a new fresh Asp.net MVC 3 project – Major Byte Sep 06 '11 at 18:38