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.