0

I am trying to resolve the error 'List ActiveOrder02 does not contain a definition for Client' that appears when I put the mouse over '.Client' on the line @Html.DisplayNameFor(model => model.ActiveOrders02.Client) in the following View:

@model MVCDemo2.ViewModels.Order02VM

<table class="table">
<tr><th>@Html.DisplayNameFor(model => model.ActiveOrders02.Client)</th></tr>

@foreach (var item in Model.ActiveOrders02)
{
    <tr>
        <td>@Html.DisplayFor(modelItem => item.Client)</td>
    </tr>
}

For info here are the Controller and the ViewModel:

using MVCDemo2.Models;
using MVCDemo2.ViewModels;
using System.Linq;
using System.Web.Mvc;

namespace MVCDemo2.Controllers
{
public class Order02Controller : Controller
{
    private InventoryContainer db02 = new InventoryContainer();
    // GET: Order02
    public ActionResult Index()
    {
        //Create instance of the (View)Model
        var o = new Order02VM();
        //Retrieves DATA from the DB
        var resultSet02 = db02.SampleDbTable;
        // Push the retrieved DATA into the (View)Model
        o.ActiveOrders02 = resultSet02.Select(x => new ActiveOrder02
        {
            ID = x.tableId,
            Client = x.tableClient
        }).ToList();
//EDIT caused by answer of @David
        return View(o);
//IT WAS:            return View(o.ActiveOrders02.ToList());
    }
}
}

Here follows the ViewModel:

using System.Collections.Generic;

namespace MVCDemo2.ViewModels
{
public class Order02VM
{
    public List<ActiveOrder02> ActiveOrders02 { get; set; }
}

public class ActiveOrder02
{
    public decimal ID { get; set; }
    public string Client { get; set; }
}
}

EDIT: What I'm after is by DisplayNameFor to present the name of column tableClient from SampleDbTable as a Header of column Client in the Index view.

Thank you!

2
  • Think about why model.ActiveOrders02.Client won't work. It wouldn't work in C#, therefore it wouldn't work in Razor. A List<ActiveOrder02> doesn't have a property called Client. The Client property is on the items in the list, not the list itself. So it's not clear what you're trying to do. If the Client property makes more sense on the Order02VM, then move it there. Or it it's defined in the correct place, then change how you're accessing it. model.ActiveOrders02.First().Client for example. Commented Apr 3, 2017 at 12:18
  • Thanks for your comment!, By DisplayNameFor(model => model.ActiveOrders02.Client I am trying to set the HEADER of the table for this column by taking this header from the header of the column from the SampleDbTable. Commented Apr 3, 2017 at 13:02

3 Answers 3

2

Because model.ActiveOrders02 is of type List<ActiveOrder02>, not of type ActiveOrder02.

It looks like you just want to get the display meta-data of the property, not a value of a particular instance. There's a somewhat unintuitive way to do that:

@Html.DisplayNameFor(model => model.ActiveOrders02.First().Client)

Note the use of .First() on the list. One might intuitively think that this would be error-prone, because if the list is empty it would throw an exception. However, ASP.NET isn't actually going to use that to iterate over the list. This expression is being used by the framework to identify the property into which the framework will reflect to get meta-data about that property.

In most cases, putting something like that on a list would require that the list never be empty. In this particular case, however, it should work just fine.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, David! What I get as a result of your suggestion is the following Error: The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[MVCDemo2.ViewModels.ActiveOrder02]', but this dictionary requires a model item of type 'MVCDemo2.ViewModels.Order02VM'. I'm still not clear how to obtain the name of the column from the name of the respective column (tableClient) from the SampleDbTable
@Angel: That's a separate issue. You declare the view's model type as: @model MVCDemo2.ViewModels.Order02VM, but then you pass it: return View(o.ActiveOrders02.ToList()); Did you just mean to pass it the object itself?: return View(o); That seems to be what the view code is expecting. You have to give the view an instance of the type it expects. So either change the controller to provide that type or change the view to expect the type you're giving it.
I meant return View(o) but while trying different options I messed with it and forgot to correct it. When I change it to return View(o) and use in the View 'model=>model.ActiveOrders02.First().Client' there is no such error and the result is 'Client' while what I am after is to be 'tableClient' Thanks!
Hi, David, I ended up using your suggestion in the View + the following data annotation in the ViewModel: [Display(Name = "tableClient")] This way there is no error and I get as Header name the name of the respective db column. Thank you!
2

From your code it is clear that ActiveOrders02 is a list of objects of type ActiveOrder02. Client is a property in an element(ActiveOrder02) in ActiveOrders02. If you want the Client value in the first item in ActiveOrders02 you can go for

@Html.DisplayNameFor(model => model.ActiveOrders02[0].Client)

Of course you need to check if ActiveOrders02 is empty or not before doing this.

1 Comment

Your answer was very helpful to understand where I am going wrong in the world of Model - View - Controller :) I will upvote it shortly. Thank you!
1

You instruct the view that @model is MVCDemo2.ViewModels.Order02VM, but in the controller you set o.ActiveOrders02 to List<MVCDemo2.ViewModels.Order02VM>:

o.ActiveOrders02 = resultSet02.Select(x => new ActiveOrder02
{
    ID = x.tableId,
    Client = x.tableClient
}).ToList(); // <--

Then you return View(o.ActiveOrders02.ToList());, essentially calling .ToList() on o.ActiveOrders02, which already is a List<MVCDemo2.ViewModels.Order02VM>.

So, you can:

  • return a single instance of Order02VM to the view rather than a list with one item, or...
  • return the list to the view, set the view's @model to List<MVCDemo2.ViewModels.Order02VM> and take the first Order02VM instance from the list (using .First(), list index 0, etc) and go from there.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.