-1

I'm new to C# MVC so please be patient. I'm having some trouble displaying output for the ViewBag. The application is a Fantasy Football webpage so I have three tables (right now, more to come) one for the basic player info (dbo.Player), one for player background (dbo.PlayerBackground), and one is just a definition table for the team (dbo.Team).

In one of my pages I have a name search and search by position and want to return information across these three tables.

public ActionResult Index()
{
    var players = (from p in db.Players
                   join pb in db.PlayerBackgrounds on p.playerId equals pb.playerID
                   join t in db.Teams on p.teamAbbre equals t.teamAbbre
                   select new { playerID = p.playerId, playerName = p.name, position = p.position,
                                height = pb.height, weight = pb.weight, college = pb.college, dob = pb.dob,
                                imageUrl = pb.imageUrl, years = pb.years,
                                teamName = t.name
                                }).ToList();

    ViewBag.data = players;
    return View();
}

The query works fine but in index.cshtml I keep getting errors.

@foreach (var player in ViewBag.data)
{
    <tr class="success ui-dragable playerRow"  style="display: none;">
        <td>
            <input type="checkbox" />
        </td>
        <td>
            @Html.ActionLink( (string)player.playerName, "Details", new { id = player.playerID }, new { @class = "detailsLink" })
        </td>
        <td>
            @player.teamName
        </td>
        <td>
            @player.position
        </td>....

From the research I've done, this seems like it should work. I've tried it both with and without the (string) cast. Without the cast it gives me red squiggly saying I should cast and when I do I get:

Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'playerName'

As I step through, I can watch player and it has the various properties just as it should. Any idea what I'm doing wrong?

ekad
  • 14,436
  • 26
  • 44
  • 46
nurdyguy
  • 2,876
  • 3
  • 25
  • 32

1 Answers1

1

The problem is that you are using an anonymous object. I can't really take the credit for that finding though, the answer I found was right here (Go give him an up-vote). Refer to it for complete details.

Essentially, the short of the story is that Anonymous objects are emitted as internal by the compiler. This causes problems when trying to use them as Razor views because they are compiled into a separate assembly by the ASP.Net runtime (internal only allows access in the same assembly).

So, the solution is to define a view model:

public class PlayerViewModel
{
    // Replace with the actual type of playerId
    public int playerId { get; set; }
    // etc...
}

And use it in your controller:

public ActionResult Index()
{
    var players = (from p in db.Players
                   join pb in db.PlayerBackgrounds on p.playerId equals pb.playerID
                   join t in db.Teams on p.teamAbbre equals t.teamAbbre
                   select new PlayerViewModel { playerID = p.playerId, ... }).ToList();

    return View(players); // Use the strongly-typed model property for your view
                          // instead of ViewBag.data (It's recommended)
}

And finally in your view:

@* At the beginning of your view *@
@model IEnumerable<PlayerViewModel>
...
@foreach (var player in @Model)
    {

        <tr class="success ui-dragable playerRow"  style="display: none;">
            <td>
                <input type="checkbox" />
            </td>
            <td>
                @Html.ActionLink(player.playerName, "Details", new { id = player.playerID }, new { @class = "detailsLink" })
            </td>
            <td>
                @player.teamName
            </td>
            <td>
                @player.position
            </td>....
Community
  • 1
  • 1
AtinSkrita
  • 1,373
  • 12
  • 13
  • Thanks Atin. I just found this post as well, http://stackoverflow.com/questions/5207382/get-data-from-two-tablesjoin-with-linq-and-return-result-into-view, which helped a lot. I was originally using a viewmodel but ran into problems getting the sql to work well. I still don't understand why my code wasn't working because I followed exactly what several other posters did. Oh well, viewmodel is def the way to go. – nurdyguy May 31 '15 at 22:05