66

When I try to render a partial view whose model type is specified as:

@model dynamic

by using the following code:

@{Html.RenderPartial("PartialView", Model.UserProfile);}

I get the following exception:

'System.Web.Mvc.HtmlHelper<dynamic>' has no applicable method named 'RenderPartial' 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.

However, the same code in a .aspx file works flawlessly. Any thoughts?

Diego
  • 5,024
  • 6
  • 38
  • 47

7 Answers7

55

Just found the answer, it appears that the view where I was placing the RenderPartial code had a dynamic model, and thus, MVC couldn't choose the correct method to use. Casting the model in the RenderPartial call to the correct type fixed the issue.

source: Using Html.RenderPartial() in ascx files

Community
  • 1
  • 1
Diego
  • 5,024
  • 6
  • 38
  • 47
  • 12
    Right, the main reason this doesn't work is that C# does not support calling an extension method (which is what `Html.RenderPartial()` is) when any of the arguments is of a dynamic type. You have to either call the extension method statically or cast the argument to a non-dynamic type. – Eilon Nov 08 '10 at 01:22
26

Instead of casting the model in the RenderPartial call, and since you're using razor, you can modify the first line in your view from

@model dynamic

to

@model YourNamespace.YourModelType

This has the advantage of working on every @Html.Partial call you have in the view, and also gives you intellisense for the properties.

juan
  • 80,295
  • 52
  • 162
  • 195
  • 5
    +1 as seems more sensible to me than Diego's suggestion - for reasons noted above. i.e. if you know what type you are dealing with, then deal with that type ! – MemeDeveloper Aug 02 '11 at 04:15
  • doesn't make sense. If I want to use a dynamic model I would like that the helpers help me. Dynamic model in most cases is simpler and more productive since you don't have to declare the classes. – ema Feb 29 '12 at 16:24
  • 2
    @ema - using dynamic models also leads to sloppier, poorly thought-out code. ViewModels are almost always a better idea than dynamic models. Unless you like finding compile errors at run-time! – Josh M. May 02 '14 at 23:01
  • @JoshM. This also happens when using `ViewBag` (aka dynamic model) which is suitable for passing around "client-side" variables, one-time use, etc. that really don't require the use or maintenance of a whole new ViewModel class. – Matt Borja Jan 15 '16 at 22:34
  • @MattBorja Indeed. Dynamic stuff leaves room for error but can be really useful when used sparingly. – Josh M. Jan 16 '16 at 02:07
18

Can also be called as

@Html.Partial("_PartialView", (ModelClass)View.Data)
Tom
  • 12,591
  • 13
  • 72
  • 112
  • This has the downside that it generates a temporary (and potentially large) `MvcHtmlString` on the fly, rather than just writing to the output directly. – Drew Noakes Feb 10 '11 at 10:13
  • I found that I needed to cast my model like this, even though my model wasn't declared as a `dynamic`. It was probably because my model was a list. – levininja Jan 08 '15 at 21:58
8

There's another reason that this can be thrown, even if you're not using dynamic/ExpandoObject. If you are doing a loop, like this:

@foreach (var folder in ViewBag.RootFolder.ChildFolders.ToList())
{
    @Html.Partial("ContentFolderTreeViewItems", folder)
}

In that case, the "var" instead of the type declaration will throw the same error, despite the fact that RootFolder is of type "Folder. By changing the var to the actual type, the problem goes away.

@foreach (ContentFolder folder in ViewBag.RootFolder.ChildFolders.ToList())
{
    @Html.Partial("ContentFolderTreeViewItems", folder)
}
J Wynia
  • 10,464
  • 4
  • 40
  • 38
4

Here's a way to pass a dynamic object to a view (or partial view)

Add the following class anywhere in your solution (use System namespace, so its ready to use without having to add any references) -

    namespace System
    {
        public static class ExpandoHelper
        {
            public static ExpandoObject ToExpando(this object anonymousObject)
            {
                IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
                IDictionary<string, object> expando = new ExpandoObject();
                foreach (var item in anonymousDictionary)
                    expando.Add(item);
                return (ExpandoObject)expando;
            }

        }
    }

When you send the model to the view, convert it to Expando :

    return View(new {x=4, y=6}.ToExpando());

Cheers

Segev -CJ- Shmueli
  • 1,535
  • 14
  • 15
2

I had the same problem & in my case this is what I did

@Html.Partial("~/Views/Cabinets/_List.cshtml", (List<Shop>)ViewBag.cabinets)

and in Partial view

@foreach (Shop cabinet in Model)
{
    //...
}
alexandre-rousseau
  • 2,321
  • 26
  • 33
0

I was playing around with C# code an I accidentally found the solution to your problem haha

This is the code for the Principal view:

`@model dynamic 
 @Html.Partial("_Partial", Model as IDictionary<string, object>)`

Then in the Partial view:

`@model dynamic 
 @if (Model != null) { 
   foreach (var item in Model) 
   { 
    <div>@item.text</div> 
   } 
  }`

It worked for me, I hope this will help you too!!

Alan
  • 1