null model ile renderpartial yanlış tipte geçti


198

Benim bir sayfam var:

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

Ve üzerinde, aşağıdakiler:

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

İşte DTO nesnesi:

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

ve işte kısmi:

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

Model.Tasks boş olmadığında, her şey yolunda gider. Ancak boş olduğunda:

Sözlüğe aktarılan model öğesi 'DTOSearchResults' türündedir ancak bu sözlük için 'System.Collections.Generic.IEnumerable`1 [Görev]' türünde bir model öğesi gerekir.

Hangi aşırı yükü kullanması gerektiğini bilmemeliydim, bu yüzden bunu açıklamak için yaptım (aşağıya bakın), ama yine de aynı sorunu alıyorum!

<% Html.RenderPartial("TaskList", (object)Model.Tasks, null); %>

Ben null olup olmadığını kontrol, hatta null geçerek bu çalışabilir biliyorum, ama mesele bu değil. Bu neden oluyor?

Yanıtlar:


349

Andrew Sanırım karşılaştığınız sorun, RenderPartial metodunun bir sonucu olarak arama (view) 'ın modelini kısmi görünüme kullanarak geçtiğiniz model null olduğunda .. bu garip davranışı bu şekilde başlatabilirsiniz:

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

Bu yardımcı olur mu?


16
Hala insanlara zaman kazandırıyor. Saçlarımı bunun üzerinden çekiyordum.
James Gregory

3
Neden null modeli ve sayfaların Modelini geçmesini desteklediklerini anladım, ancak aşırı yükleyerek bunu başaramadılar. @ Html.Render ("eşek") @ Html.Render ("eşek", couldbenull) 'den farklı
Phil Strong

19
Bunu çok mantıksız
pbz

3
Ben bu çözüm ile kısmi görünüm benim ValidationSummary işe yaramadı çünkü birincil modelin ViewData kısmi görünümünde kayboldu. Burada verilen cevabı bu sorunu çözmek için stackoverflow.com/a/12037580/649497 kullandım.
BruceHill

5
Mevcut ViewData boyunca geçmelisiniz: new ViewDataDictionary (ViewData)
Scott

48

@ myandmycode'un cevabı iyi, ama biraz daha kısa bir cevap

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

Bu ViewDataDictionary, modeli tutan şey olduğu için çalışır ve bir yapıcı parametresi olarak bir modeli kabul edebilir. Bu, temelde yalnızca olası null modeli içeren "tam" bir görünüm veri sözlüğü geçirir.


2
@jcmcbeth: Eee, hayır, hayır ... Bu kodu null'larla başarıyla kullandım.
yapılandırıcı

1
@jcmcbeth: Kullanıyor musunuz new ViewDataDictionary(null)? Çünkü bu ViewDataDictionary, muhtemelen null'ları kabul etmeyecek bir parametreyle farklı bir aşırı yük seçer .
yapılandırıcı

1
Bir ViewBag özelliği kullanmanın yanlış yapıcı çağrılmasına neden olduğu anlaşılıyor. Dinamik bir türü nasıl alır ve bir nesne üzerinde bir ViewDataDictionary varsayımı benim için anlamlı değil, ama yaptığı gibi görünüyor. Doğru yapıcıyı seçebilmesi için bir nesneye dökmeniz gerekir.
Joel McBeth

1
@jcmcbeth: Dinamik bir tür üzerinden çağırmak, gerçek değeri vermiş olduğunuz gibi kullanır; değer ise null, arama new ViewDataDictionary(null)ile aynıdır ve bu da en fazla aşırı yüklenmenin çağrılmasına neden olur.
yapılandırıcı

1
bu şekilde kullanırsanız, sözlük hatası gitti. Html.RenderPartial("TaskList", new ViewDataDictionary(model: Model.Tasks))Eğer null ise yanlış yapıcı kullanıyorsunuz.
Filip Cornelissen

26

Geçirdiğiniz Modelin özelliği null olduğunda MVC kasıtlı olarak "ana" Model'e geri döner. Görünüşe göre MVC motoru, boş bir model değerini öncekini kullanma niyeti olarak yorumlar.

Biraz daha fazla ayrıntı burada: ASP.NET MVC, güçlü yazılan görünümler, kısmi görünüm parametreleri aksaklığı


1
Sorunu açıklamaya çalıştığınız için +1 ve bu sadece garip bir davranış olarak ele
alınmıyor

Evet, bu benim başıma geliyordu ve yukarıdakiler düzeltmedi, gerçek hatam hakkında biraz daha bilgi verdi.
Tuval

20

Kısmi görünümde önceki ViewData öğenizi kaybetmek istemiyorsanız şunları deneyebilirsiniz:

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

1
Bu soruya cevap vermiyor gibi görünüyor.
John Saunders

6
+1 Aslında işe yarıyor. Temel olarak burada sunulan fikir aynı stackoverflow.com/a/713921/649497 ancak bu cevapla ilgili bir sorunun üstesinden gelir ve bu, ViewDataDictionary boş bir kurucu ile başlatırsanız ViewData'nın kaybolacağıdır. Bu sorunu ilk olarak kabul edilen çözümle çözdüm ve sonra ValidationSummary'mın kısmi görünümde çalışmadığını gördüm. Bu çözüm benim için çözdü. Bu yanıt, sorunu çözmek ve ViewData'yı kısmi görünümünüzde korumak için daha fazla tanımaya ihtiyaç duyar.
BruceHill

1
@Franc P, bu aslında ViewBag değerlerini kaybetmeden çalıştı ve bu nedenle boş bir model geçti. Teşekkürler.
Zaker

Partials'ınızda ViewBag erişimine ihtiyacınız varsa bu doğru cevaptır!
Daniel Lorenz

12

Bunun gibi bir HtmlHelper oluşturmak için bir çözüm olacaktır:

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

Partial<T>(...)Önce eşleştirilen Partial(...)kadar rahat ve derleme herhangi bir belirsizlik hatası.

Şahsen davranışı anlamakta zorlanıyorum - bunu tasarım seçimi olarak hayal etmek zor görünüyor mu?


1
sonunda yaptığım şey bu. asp.net mvc'de herhangi bir anlam ifade eden pek çok tasarım seçeneği / davranışı yoktur. o zamandan beri terk etti. tho yararlı, bu yüzden bir +1 var
Andrew Bullock

İyi olan, ancak kullanıcı için belirsiz. Diyelim ki meslektaşımın projesinde ne kullandığına alışkınım, yeni bir işe başlıyorum. O zaman bu aşırı yükü ve villayı eklemeyi tamamen unutma, üretimde istisnalar olmaya başladı çünkü yeterince iyi test etmedik. Farklı bir isim daha iyi imho.
Jaap

11

Bu yanıtlanmış olmasına rağmen, bununla karşılaştım ve projem için bu sorunu onunla çalışmak yerine çözmek istediğime karar verdim new ViewDataDictionary().

Bir dizi uzantı yöntemi oluşturdum: https://github.com/q42jaap/PartialMagic.Mvc/blob/master/PartialMagic.Mvc/PartialExtensions.cs
Ayrıca model null ise kısmi çağırmayan bazı yöntemler ekledim , bu if ifadelerinin çoğunu kurtaracaktır.

Onları Razor için oluşturdum, ancak birkaçı da aspx tarzı görünümlerle çalışmalı (HelperResult'u kullananlar muhtemelen uyumlu değil).

Uzantı yöntemleri şöyle görünür:

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

IEnumerable<object>Modeller için yöntemler de vardır ve ıskarta olanlar da kısmi sonucu bazı html ile sarmanıza izin veren bir Razor lambda ile çağrılabilir.

İsterseniz bunları kullanmaktan çekinmeyin.


1
MVC5 itibariyle hala yararlı: 6/25/2014. Teşekkürler.
Jason

1

Bu benim geçici çözüm:


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


Bu kirli bir çözüm. Kısmi görünümünüzde, listenin herhangi bir değerinin olup olmadığını ve boş olup olmadığını kontrol etmek yerine boş Modeli kontrol edebilmeniz gerekir.
madd
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.