2010-03-17 15 views
6

Ho un oggetto che contiene modelli per la mia app Web ASP.NET MVC. Il modello che viene passato nella vista ha sotto modelli per "gadget" su quella particolare vista. Ognuno di questi sub-modelli viene passato a una vista parziale (gadget).Passaggio dell'oggetto figlio null dall'oggetto padre a una vista parziale

Il problema è quando ho un modello nullo nel modello di vista. Vedi l'esempio qui sotto.

Vista Modello:

public class FooBarHolder() 
{ 
    public FooBar1 FooBar1 { get; set; } 
    public FooBar2 FooBar2 { get; set; } 
} 

Passiamo FooBarHolder nella vista e dentro la vista che effettuare chiamate come

<% Html.RenderPartial("Foo", Model.FooBar1); %> 
<% Html.RenderPartial("Foo2", Model.FooBar2); %> 

ora dicono per esempio che Model.FooBar2 era nullo. Quello che sto sperimentando dalla vista parziale fortemente tipizzata è un errore che dice "Questa vista prevedeva un modello di tipo FooBar2 ma ha ottenuto un modello di tipo FooBarHolder."

Perché questo sta accadendo invece di passare solo un null?

risposta

7

Ecco come funziona il metodo RenderPartial (so che avrebbe dovuto essere documentato, bloggato, ecc., Anch'io lo trovo un po 'strano). Se non si specifica un modello o si passa null, verrà utilizzato il modello della pagina padre. Per evitare questo si potrebbe usare l'operatore nulla coalescenza:

<% Html.RenderPartial("Foo", Model.FooBar1 ?? new Foo()); %> 

E se siete davvero curioso di sapere come questo è implementato c'è un estratto le parti rilevanti del codice sorgente di ASP.NET MVC 2:

// Renders the partial view with an empty view data and the given model 
public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, object model) { 
    htmlHelper.RenderPartialInternal(partialViewName, htmlHelper.ViewData, model, htmlHelper.ViewContext.Writer, ViewEngines.Engines); 
} 

internal virtual void RenderPartialInternal(string partialViewName, ViewDataDictionary viewData, object model, TextWriter writer, ViewEngineCollection viewEngineCollection) { 
    if (String.IsNullOrEmpty(partialViewName)) { 
     throw new ArgumentException(MvcResources.Common_NullOrEmpty, "partialViewName"); 
    } 

    ViewDataDictionary newViewData = null; 

    if (model == null) { 
     if (viewData == null) { 
      newViewData = new ViewDataDictionary(ViewData); 
     } 
     else { 
      newViewData = new ViewDataDictionary(viewData); 
     } 
    } 
    else { 
     if (viewData == null) { 
      newViewData = new ViewDataDictionary(model); 
     } 
     else { 
      newViewData = new ViewDataDictionary(viewData) { Model = model }; 
     } 
    } 

    ViewContext newViewContext = new ViewContext(ViewContext, ViewContext.View, newViewData, ViewContext.TempData, writer); 
    IView view = FindPartialView(newViewContext, partialViewName, viewEngineCollection); 
    view.Render(newViewContext, writer); 
} 

Nota come viene gestito il caso del modello null.

+0

grazie per questa chiara spiegazione, sarebbe rimasto bloccato per ore se non fosse stato per te! Nel tuo caso crei un nuovo Foo() difficile, e se volessi REALMENTE passare null lì? –

1

La mia soluzione per questo strano "feature" (o bug forse?) È:

<% Html.RenderPartial(
    "Foo2", 
    new ViewDataDictionary(ViewData) { Model = Model.FooBar2 } 
); %> 
+1

Hai provato questo? Non funziona per le viste fortemente tipizzate qui ... –

2

Per evitare di passare il modello del genitore quando modello del bambino è nullo, usare questo trucco:

@Html.Partial("Child", null, new ViewDataDictionary<ChildType>(childInstance/*this can be null*/)) 

Credit where due...

Problemi correlati