124

I want to have DropDownListFor in MVC

@foreach (var item in Model)
{
    @Html.DropDownListFor(modelItem => item.TitleIds, new SelectList(ViewBag.TitleNames as System.Collections.IEnumerable, "TitleId", "Title.TitleText"), "No: " + ViewBag.MagNo, new { id = "TitleIds" })   
}

in Controller

public ActionResult ArticleList(int id)
{
    ArticleWriter_ViewModel viewModel = new ArticleWriter_ViewModel();
    Func<IQueryable<NumberTitle>, IOrderedQueryable<NumberTitle>> orderByFunc = null;
    Expression<Func<NumberTitle, bool>> filterExpr = null;
    if (id > 0)
    {
        filterExpr = p => p.MagazineId.Equals(id);
    }
    var wholeTitles = unitOfWork.NumberTitleRepository.Get(filterExpr,  orderByFunc, "Magazine,Title").ToList();          

    ViewBag.MagNo = wholeTitles[0].Magazine.MagNo.ToString();
    ViewBag.MagId = wholeTitles[0].Magazine.Id;
    ViewBag.TitleNames = wholeTitles;

    return View("../Panel/Magazine/ArticleList", "_BasicLayout", viewModel);
}

but I get this error

'System.Web.Mvc.HtmlHelper<System.Collections.Generic.IEnumerable<Cinemavaadabiat.ViewModel.ArticleWriter_ViewModel>>' has no applicable method named 'DropDownListFor' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.

I can't understand the error, what should I check for it?

meJustAndrew
  • 6,011
  • 8
  • 50
  • 76
nnmmss
  • 2,850
  • 7
  • 39
  • 67

3 Answers3

215

You are using dynamic types in extension methods, which is not supported.

Cast the dynamic types to actual types, and it will work.

From what I see now, I'd say:

(string) ViewBag.MagNo

Which would result in

@foreach (var item in Model)
{
    @Html.DropDownListFor(modelItem => item.TitleIds, 
       new SelectList(ViewBag.TitleNames as System.Collections.IEnumerable, 
       "TitleId", "Title.TitleText"), 
       "No: " + (string) ViewBag.MagNo, 
       new { id = "TitleIds" })   
}
bas
  • 13,550
  • 20
  • 69
  • 146
  • 2
    it says Cannot convert type 'string' to 'int' – nnmmss Jan 05 '14 at 13:44
  • 3
    @nnmmss then ViewBag.MagNo is not an int, but a string. Cast it to a string and you should be golden – bas Jan 05 '14 at 13:45
  • This answer doesn't really address the real issue -- the code works in other projects without casting, just not in his -- likely there is some configuration missing and it's causing the compiler to be confused. -- Edit: Looks like @mkaj's answer addresses the actual issue. – BrainSlugs83 Jun 10 '16 at 21:03
  • Can I cast `ViewBag.MagNo` to a `bool?` type? – Dylan Czenski Jun 16 '16 at 23:56
  • I was passing an integer. What I ended up doing (string)ViewBag.MyNumber.ToString(). Just adding ToString() or (string) throws exception. Yah I found that weird too. – SZT Oct 23 '17 at 12:57
47

My fix for this problem was to add:

    @model MyModel

At the top of the partial control. I had forgotten it.

mkaj
  • 3,421
  • 1
  • 31
  • 23
5

To expand on the subject of MVC extension methods (which is how I ran across this question), I like to use Dapper's connection.Query() syntax which will return results as an IEnumerable<dynamic>.

It is also possible to use dynamic objects by:

  • Calling the static method directly, per Jon Skeet's answer:

    @model IEnumerable<dynamic>
    
    @PartialExtensions.Partial(Html, "~/link/to/_partialView.cshtml", Model)
    
  • Wrapping it in a class.

    public class DynamicQueryResult
    {
        public dynamic QueryResults {get; set;}
    }
    

    Then in your MVC View:

    @model Namespace.DynamicQueryResult
    
    @Html.Partial("~/link/to/_partialView.cshtml", Model)
    
Community
  • 1
  • 1
Jason
  • 4,897
  • 2
  • 33
  • 40