renderpartial con modello null viene passato il tipo sbagliato

Ho una pagina:

<%@ Page Inherits="System.Web.Mvc.View" %> 

E su di esso, il seguente:

  

Ecco l’object DTO:

 public class DTOSearchResults { public string SearchTerm { get; set; } public IEnumerable Tasks { get; set; } 

ed ecco il parziale:

 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable>" %> 

Quando Model.Tasks non è nullo, tutto funziona correttamente. Tuttavia quando è nullo ottengo:

    L’elemento del modello passato nel dizionario è di tipo “DTOSearchResults”, ma questo dizionario richiede un elemento del modello di tipo “System.Collections.Generic.IEnumerable`1 [Task]”.

    Ho capito che non si deve sapere quale sovraccarico usare, quindi ho fatto questo (vedi sotto) per essere esplicito, ma ho ancora lo stesso problema!

      

    So che posso aggirare questo verificando per null, o nemmeno passando null, ma non è questo il punto. Perché sta succedendo?

    Andrew penso che il problema che stai ottenendo sia il risultato del metodo RenderPartial che usa il modello di chiamata (vista) per la vista parziale quando il modello che passi è nullo .. puoi aggirare questo strano comportamento facendo:

     <% Html.RenderPartial("TaskList", Model.Tasks, new ViewDataDictionary()); %> 

    Questo aiuta?

    La risposta di @ myandmycode è buona, ma sarebbe leggermente più breve

     <% Html.RenderPartial("TaskList", new ViewDataDictionary(Model.Tasks)); %> 

    Ciò funziona perché ViewDataDictionary è la cosa che contiene il modello e può accettare un modello come parametro costruttore. Questo fondamentalmente passa ad un “intero” dizionario di dati di visualizzazione, che ovviamente contiene solo il modello eventualmente null.

    Sembra che quando la proprietà del modello che stai trasmettendo sia null MVC ritorna intenzionalmente al modello “genitore”. Apparentemente il motore MVC interpreta un valore del modello nullo come intento a usare il precedente.

    Leggermente più dettagli qui: ASP.NET MVC, viste fortemente tipizzate, parametri di vista parziale glitch

    Se non vuoi perdere il ViewData precedente nella vista parziale, puoi provare:

     <% Html.RenderPartial("TaskList", Model.Tasks, new ViewDataDictionary(ViewData){Model = null});%> 

    Una soluzione sarebbe quella di creare un HtmlHelper in questo modo:

     public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName, T model) { ViewDataDictionary viewData = new ViewDataDictionary(htmlHelper.ViewData) { Model = model }; return PartialExtensions.Partial(htmlHelper, partialViewName, model, viewData); } 

    Il Partial(...) corrispondente prima del Partial(...) così conveniente e senza errori di ambiguità durante la compilazione.

    Personalmente trovo difficile capire il comportamento – sembra difficile immaginarlo come scelta di design?

    Anche se questo è stato risolto, ho trovato questo e ho deciso di voler risolvere questo problema per il mio progetto invece di new ViewDataDictionary() con il new ViewDataDictionary() .

    Ho creato una serie di metodi di estensione: https://github.com/q42jaap/PartialMagic.Mvc/blob/master/PartialMagic.Mvc/PartialExtensions.cs
    Ho anche aggiunto alcuni metodi che non chiamano il partial se il modello è nullo, questo salverà molte affermazioni if.

    Li ho creati per Razor, ma un paio di essi dovrebbero funzionare anche con viste in stile aspx (quelli che usano HelperResult probabilmente non sono compatibili).

    I metodi di estensione hanno questo aspetto:

     @* calls the partial with Model = null *@ @Html.PartialOrNull("PartialName", null) @* does not call the partial if the model is null *@ @Html.PartialOrDiscard("PartialName", null) 

    Esistono anche metodi per i modelli IEnumerable e quelli degli scarti possono anche essere chiamati con un lambda Razor che consente di avvolgere il risultato parziale con un html.

    Sentiti libero di usarli se vuoi.

    La mia soluzione a questo è:

    <% Html.RenderPartial("TaskList", Model.Tasks ?? new List()); %>
    <% Html.RenderPartial("TaskList", Model.Tasks ?? new List()); %>