views:

33

answers:

3

I'm learning Linq and MVC2 I'm making progress, but I'm a little stuck on how I should get a page descrption into a View that uses a collection.

In my controller I have the following construct

public ActionResult Group(int id)
{
    var result = (from d in db.ErrorDetails.Where(r => r.ErrorTerminal.ErrorTerminalGroupID == id)
                  orderby d.ErrorTerminal.TerminalNumber ascending, d.ErrorRecordedAt descending
             select d);

    return View(result);
}

and on my view

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>????? how to get a title from the 1st record?????</h2>
<table>
<%
        foreach (var item in Model) {
%>
//code for setup of the rows etc
<% }%>
</table>

How do I get the Title from the Linq query that I made, OR do I need to make a ViewModel to house that?

A: 

Like this:

<%= Html.Encode(Model.First().Title) %>

If there are no items, this will throw an exception.

If you want a title that isn't in the first item, you'll need to use a ViewModel class with a Title property.

SLaks
Downvoted because First() will throw an exception if there are no elements in the collection.
James Dunne
+2  A: 

I'd create a ViewModel to house your title, so that the fact that your title is derived from the first item of your list is seperate to the page code, and your page code only contains presentation logic.

SamStephens
A: 

Please do not pass IEnumerable<T>s to your view. Instead consider using a List<T> and do the first-time enumeration in the controller. I only recommend this pattern for ViewModels because you can catch the exception of the first-time enumeration in your controller code and not let the view rendering die horribly and result in partial HTML output because the controller screwed up and passed the view something it could not fully enumerate over.

That being said, the best approach is to use a ViewModel and have it house properties string Title and List<ErrorDetail> ErrorDetails.

public class GroupErrorDetailsViewModel
{
    public string Title { get; set; }
    // NOTE: assuming db.ErrorDetails is of type Table<ErrorDetail>
    public List<ErrorDetail> ErrorDetails { get; set; }
}

public ActionResult Group(int id)
{
    // FIXME: this direct database query should not really be in the controller
    var result =
        from d in db.ErrorDetails
        where d.ErrorTerminal.ErrorTerminalGroupID == id
        orderby d.ErrorTerminal.TerminalNumber ascending, d.ErrorRecordedAt descending
        select d;

    var resultList = result.ToList();

    var viewModel = new GroupErrorDetailsViewModel
    {
        Title = resultList.Count > 0 ? resultList[0].Title : "Default Title",
        ErrorDetails = resultList
    };

    return View((object)viewModel);
}
James Dunne
I think the logic for determining where the Title comes from would be better encapsulated if it were inside the `GroupErrorDetailsViewModel` class. Also, I think this is a slightly more explicit way to write that line: `Title = resultList.Any() ? resultList.First().Title : "Default Title"`.
Ryan
Oh, and it's probably better to return `IEnumerable<T>` instead of `List<T>` because your view is not going to be modifying the collection, only enumerating it.
Ryan
This is a point of maintenance concern I think. `IEnumerable<T>` can be a lot of things, and what you don't want it to be is some enumerator that can cause failure in your view and render partial HTML. I would leave it as `List<T>`. Under "normal" circumstances I would agree that a more-general `IEnumerable<T>` is a better fit if you don't care about how you get data. Also, the controller doesn't care what the view does with the view model because the controller will never get it back.
James Dunne
I don't believe that logic should belong in view models. They're simply that: models. Having the view execute more logic than it needs increases the surface area of failure.
James Dunne
Grr... makes it hard when you work through the MVC* demos on the Microsoft site and they aren't doing the right thing... I guess maybe i need to pose a new question.. What are the More appropriate demos to be working through to learn MVC*
Paul Farry