null 모델의 renderpartial이 잘못된 유형을 전달합니다.


198

페이지가 있습니다 :

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

그리고 그것에 :

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

다음은 DTO 객체입니다.

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

여기 부분이 있습니다.

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

Model.Tasks가 null이 아닌 경우 모든 것이 제대로 작동합니다. 그러나 null 일 때 :

사전에 전달 된 모델 항목은 'DTOSearchResults'유형이지만이 사전에는 'System.Collections.Generic.IEnumerable`1 [Task]'유형의 모델 항목이 필요합니다.

어떤 과부하를 사용 해야하는지 알지 못했기 때문에 명시 적으로하기 위해이 작업을 수행했지만 (아래 참조) 여전히 동일한 문제가 발생합니다!

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

null을 확인하거나 null을 전달하지 않아도이 문제를 해결할 수 있지만 그게 요점이 아닙니다. 왜 이런 일이 발생합니까?

답변:


349

Andrew 당신이 얻는 문제는 전달하는 모델이 null 일 때 호출 (보기) 모델을 부분보기로 사용하는 RenderPartial 메서드의 결과라고 생각합니다.

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

도움이 되나요?


16
여전히 사람들의 시간을 절약합니다. 나는 이것을 머리 위로 뽑고 있었다.
James Gregory

3
왜 그들은 null 모델을 지원하고 Model 페이지를 전달하지만 오버로드로 처리 할 수 ​​없었습니다. @ Html.Render ( "donkeys")는 @ Html.Render ( "donkeys", couldbenull)와 다릅니다
Phil Strong

19
나는 이것이 매우 반 직관적이라는 것을 알기 때문에 "문제"를 추가했다면, 동의한다면 그것에 투표하십시오 : aspnet.codeplex.com/workitem/8872
pbz

3
이 솔루션을 사용하면 기본 모델의 ViewData가 부분보기에서 손실되어 부분보기의 ValidationSummary가 작동하지 않는다는 것을 알았습니다. 이 문제를 해결하기 위해 여기에 주어진 대답을 stackoverflow.com/a/12037580/649497 을 사용했습니다.
BruceHill

5
기존의 ViewData를 따라야합니다 : new ViewDataDictionary (ViewData)
ScottE

48

@ myandmycode의 대답은 좋지만 약간 더 짧은 것입니다.

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

이것은 ViewDataDictionary모델을 보유하는 것이기 때문에 작동 하며 모델을 생성자 매개 변수로 허용 할 수 있습니다. 이것은 기본적으로 "전체"뷰 데이터 딕셔너리를 전달하는데, 물론 가능한 null 모델 만 포함합니다.


2
@ jcmcbeth : 음, 아니, 그렇지 않습니다 ...이 정확한 코드를 null과 함께 성공적으로 사용했습니다.
구성자

1
@jcmcbeth : 사용하고 new ViewDataDictionary(null)있습니까? 다른 오버로드를 선택하기 때문에 ViewDataDictionary매개 변수 가있는 오버로드 가 null을 허용하지 않을 것입니다.
구성자

1
ViewBag 속성을 사용하면 잘못된 생성자가 호출되는 것처럼 보입니다. 동적 유형을 취하고 그것이 객체에 대한 ViewDataDictionary라고 가정하는 방법은 나에게는 의미가 없지만 그것이하는 일처럼 보입니다. 올바른 생성자를 선택하려면 객체로 캐스팅해야합니다.
Joel McBeth

1
@jcmcbeth : 동적 유형을 통해 호출하면 실제 값을 제공 한 것과 동일하게 사용됩니다. 값이 null인 경우 호출과 동일하므로 new ViewDataDictionary(null)가장 특정한 과부하가 호출됩니다.
구성자

1
이런 식으로 사용하면 dictionairy 오류가 사라집니다. Html.RenderPartial("TaskList", new ViewDataDictionary(model: Model.Tasks))null 인 경우 잘못된 생성자를 사용하고 있습니다.
Filip Cornelissen

26

전달하는 모델의 속성이 null 인 경우 MVC가 의도적으로 "부모"모델로 되돌아갑니다. 분명히 MVC 엔진은 null 모델 값을 이전 값을 사용하려는 의도로 해석합니다.

ASP.NET MVC, 강력한 형식의 뷰, 부분 뷰 파라미터 결함에 대한 자세한 내용은 여기를 참조하십시오.


1
실제로 문제를 설명하려고 시도한 결과, 이상한 행동으로 취급하지 않고
YavgenyP

그러나 이것은 나에게 일어나고 있었고 위의 방법으로 문제를 해결하지 못했습니다. 실제 오류에 대해 조금 더 많은 정보를 제공했습니다.
Canvas

20

부분 뷰에서 이전 ViewData를 풀지 않으려면 다음을 시도하십시오.

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

1
이것은 질문에 대답하지 않는 것 같습니다.
존 손더스

6
+1 실제로 작동합니다. 그것은 기본적으로 여기에 제시된 것과 같은 아이디어 이지만 stackoverflow.com/a/713921/649497 그 대답의 문제를 극복했습니다. 즉 빈 생성자로 ViewDataDictionary를 인스턴스화하면 ViewData가 누락됩니다. 먼저 승인 된 솔루션 으로이 문제를 해결 한 다음 ValidationSummary가 부분보기에서 작동하지 않는 것으로 나타났습니다. 이 솔루션은 나를 위해 그것을 해결했습니다. 이 답변은 문제를 해결하고 부분보기에서 ViewData를 보존하기 위해 더 많은 인식이 필요합니다.
브루스 힐

1
@Franc P 이것은 실제로 ViewBag 값을 잃지 않고 작동했기 때문에 null 모델을 전달했습니다. 감사.
Zaker

Partials에서 ViewBag 액세스가 필요한 경우 정답입니다!
Daniel Lorenz

12

해결책은 다음과 같이 HtmlHelper를 만드는 것입니다.

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>(...)전과 일치Partial(...) 매우 편리하고 컴파일 모호성 오류입니다.

개인적으로 나는 행동을 이해하기가 어렵다는 것을 알았습니다. 이것을 디자인 선택으로 상상하기가 어렵습니까?


1
이것이 내가 결국 한 일입니다. asp.net mvc에는 많은 디자인 선택 / 동작이 없으므로 의미가 있습니다. 그것을 버린 이후. 상점 다른 사람에게 도움이, 그래서 일이
앤드류 불락

그러나 좋은 것은 사용자에게는 불분명합니다. 동료가 자신의 프로젝트에서 사용하는 것에 익숙하다고 가정 해 보겠습니다. 그런 다음이 과부하와 voilla를 추가하는 것을 완전히 잊어 버렸습니다. 우리는 충분히 테스트하지 않았기 때문에 프로덕션에서 예외가 발생하기 시작합니다. 다른 이름은 beter imho입니다.
Jaap

11

이것이 답변되었지만, 나는 이것을 가로 질러 와서 문제를 해결하는 대신 내 프로젝트 에서이 문제를 해결하기로 결정했습니다 new ViewDataDictionary().

https://github.com/q42jaap/PartialMagic.Mvc/blob/master/PartialMagic.Mvc/PartialExtensions.cs 확장 프로그램 세트를 만들었습니다.
모델이 null 인 경우 나 또한 몇 가지 방법을 추가 한 부분을 호출하지 않습니다 이렇게하면 많은 if 문이 절약됩니다.

Razor 용으로 만들었지 만 두 스타일 중 일부는 aspx 스타일 뷰 (HelperResult를 사용하는 뷰가 호환되지 않을 수도 있음)와 함께 작동해야합니다.

확장 방법은 다음과 같습니다.

@* 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>모델에 있으며, 폐기 된 는 Razor 람다로 호출하여 일부 결과를 일부 HTML로 랩핑 할 수 있습니다.

원한다면 자유롭게 사용하십시오.


1
MVC5에서 여전히 유용 : 2014 년 6 월 25 일. 감사.
Jason

1

이것에 대한 나의 해결책은 다음과 같습니다.


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


이것은 더러운 해결책입니다. 부분보기에서 list에 값이 있는지 여부와 null인지 확인하는 대신 null 모델을 확인할 수 있어야합니다.
madd
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.