2

I am trying to use a DropDownListFor<> in my LayoutTemple so I don't have access to a model. So what I did was in the @{} block at the top of the page I added FFInfo.DAL.SoloClassesContext db = new FFInfo.DAL.SoloClassesContext(); which calls an instance of the DBContext with the class I want to use. I then placed the List where I wanted using

@Html.DropDownListFor(
m => m.ID,
new SelectList(db.CultureCodes, "ID", "DisplayName"));

but when I run the code I get an error for the line m => m.ID. The error given is:

An expression tree may not contain a dynamic operation

I have never used this type of dropdown and am very new to MVC. Can anyone tell me what I am doing wrong and how to fix it?

Romias
  • 13,783
  • 7
  • 56
  • 85
  • 1
    Having your context in your VIEWS looks like a really, really, really bad idea... keep views stupid as much as you can. Making calls to db is the work of controller. – Raphaël Althaus Oct 13 '13 at 14:14
  • This is NOT a view, this is a LAYOUT TEMPLATE. –  Oct 13 '13 at 15:08

1 Answers1

10

I suggest some changes in your solution:

  1. Instead of DropDownListFor() use just DropDownList()

    @Html.DropDownList("CultureCode", new SelectList(db.CultureCodes, "ID", "DisplayName"))

  2. Instead of accessing your database data in your view... which is very out of the standard and you are coupling the Views (usually HTML) with the database... you should put the query in your controller and put the data in the ViewBag collection.

So, in your Layout, instead of the code I suggested above, you should use:

 @Html.DropDownList("CultureCode", (SelectList)ViewBag.Codes, "Select one...")

In your controller you load it as follow:

 ViewBag.Codes = new SelectList(db.CultureCodes, "ID", "DisplayName");

EDIT: You can do an action filter, to load or inject the CultureCodes in the ViewBag:

public class IncludeCultureCodesAttribute : ActionFilterAttribute
{
        public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var controller = filterContext.Controller;

        // IController is not necessarily a Controller
        if (controller != null)
        {
            var db = new YourContext();
            controller.ViewBag.Codes = new SelectList(db.CultureCodes, "ID", "DisplayName"));;
        }
    }
}

Then, in your Controller actions... you can decorate them with [IncludeCultureCodes]. So, the action with that attribute will load the collection of codes.

But I think is a better approach to load one time the layout (on Home/Index for example) and then use partial views. This way you only reload the layout going back to home... or other full view calls.

RajeshKdev
  • 6,365
  • 6
  • 58
  • 80
Romias
  • 13,783
  • 7
  • 56
  • 85
  • This is done up in a _Layout.cshtml file so there is no Controller, unless your suggesting that I add the call code ever single controller I make to pass up to the Layout file? –  Oct 13 '13 at 15:13