2010-10-28 13 views
60

Quando provo di rendere una vista parziale cui tipo di modello è specificato come:Render vista parziale con il modello dinamico Razor motore di visualizzazione e ASP.NET MVC 3

@model dynamic 

utilizzando il codice seguente:

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

ottengo la seguente eccezione:

'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. 

Tuttavia, lo stesso codice in un file aspx funziona perfettamente. qualche idea?

risposta

53

Appena trovata la risposta, sembra che la vista su cui stavo posizionando il codice RenderPartial avesse un modello dinamico e, quindi, MVC non poteva scegliere il metodo corretto da utilizzare. La trasmissione del modello nella chiamata RenderPartial al tipo corretto ha risolto il problema.

fonte: Using Html.RenderPartial() in ascx files

+12

destro, il motivo principale per questo non funziona è che C# non supporta il richiamo di un metodo di estensione (che è ciò che 'Html.RenderPartial()' è) quando uno qualsiasi degli argomenti è di tipo dinamico. Devi chiamare il metodo di estensione in modo statico o convertire l'argomento in un tipo non dinamico. – Eilon

16

può anche essere chiamato come

@Html.Partial("_PartialView", (ModelClass)View.Data) 
+0

Questo ha il rovescio della medaglia che genera un 'MvcHtmlString 'temporaneo (e potenzialmente grande) al volo, piuttosto che scrivere direttamente sull'output. –

+0

Non funzionerà con RenderPartial? – ajbeaven

+0

Ho scoperto che avevo bisogno di trasmettere il mio modello in questo modo, anche se il mio modello non è stato dichiarato come 'dinamico'. Probabilmente era perché la mia modella era una lista. – levininja

25

Invece di lanciare il modello nella chiamata RenderPartial, e dal momento che si sta utilizzando rasoio, è possibile modificare la prima riga nella visualizzazione da

@model dynamic 

a

@model YourNamespace.YourModelType 

Questo ha il vantaggio di lavorare su ogni chiamata @Html.Partial che si ha nella vista e fornisce anche intellisense per le proprietà.

+5

+1 come mi sembra più ragionevole del suggerimento di Diego - per le ragioni sopra indicate. cioè se sai di che tipo hai a che fare, allora gestisci quel tipo! – MemeDeveloper

+0

non ha senso. Se voglio usare un modello dinamico mi piacerebbe che gli aiutanti mi aiutassero. Il modello dinamico nella maggior parte dei casi è più semplice e più produttivo in quanto non è necessario dichiarare le classi. – ema

+2

@ema - l'uso di modelli dinamici porta anche a un codice più pessimo e scarsamente studiato. I ViewModels sono quasi sempre un'idea migliore dei modelli dinamici. A meno che non ti piaccia trovare errori di compilazione in fase di esecuzione! –

3

Ecco un modo per passare un oggetto dinamico per una visione (o vista parziale)

Aggiungere la seguente classe in qualsiasi punto della soluzione (namespace uso del sistema, per cui il suo pronto per l'uso, senza dover aggiungere alcun riferimento) -

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; 
      } 

     } 
    } 

Quando si invia il modello alla vista, convertirlo in Expando:

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

Acclamazioni

7

C'è un'altra ragione per cui questo può essere lanciato, anche se non stai usando dynamic/ExpandoObject. Se si sta facendo un ciclo, come questo:

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

In questo caso, il "var" al posto della dichiarazione del tipo getteranno lo stesso errore, nonostante il fatto che RootFolder è di tipo Cartella" Cambiando il. var al tipo effettivo, il problema scompare.

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

Ho avuto lo stesso problema & nel mio caso questo è quello che ho fatto

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

e in vista parziale

@foreach (Shop cabinet in Model) 
{ 
    //... 
} 
Problemi correlati