3

最近更新的dotnet的核心1.0.1到1.1和ViewComponent在MVC開始與下面的異常失敗的渲染ViewComponent:出現InvalidOperationException在強類型的視圖

InvalidOperationException: One or more errors occurred. (The model item passed into the ViewDataDictionary is of type 'App.Models.HomeViewModel', but this ViewDataDictionary instance requires a model item of type 'App.Components.LoginViewComponent'.) 

Index.cshtml呈現LoginViewComponent

@model App.Models.HomeViewModel 
<html> 
    @Component.InvokeAsync("LoginViewComponent") 
</html> 

查看/主頁/ Index.cshtml

的ViewComponent LoginViewComponent/Default.cshtml只是顯示它的模型的信息類:

@model App.Components.LoginViewCompoent 
<body> 
    <div>@Html.DisplayFor(v=>v.LoginName)</div> 
</body> 

查看/共享/組件/ LoginViewComponent/Default.cshtml

它使得罰款時, @model指令從Default.cshtml中刪除。

是不是ViewComponent假設是從包裝它的父視圖分離和不可知論?從例外情況看,它似乎需要聲明LoginViewComponent ViewComponent在HomeViewModel類爲了呈現它。

在asp.net core github上找不到任何有關此變化的註釋。

對此的評論和幫助將不勝感激。

+0

沒有你UDPATE依賴關係? (mvc 1.1.0 etc ...) –

+0

@ maua從火星是的,所有_Microsoft.AspNetCore。*參考_是在版本1.1.0 – danial

+0

這看起來很奇怪:'@model App.Components.LoginViewCompoent',它是模型還是組件? –

回答

4

我經歷了同樣的錯誤來了,有人在我的團隊從更新1.0.0 Microsoft.AspNetCore.Mvc版本1.1.0和一些我有分量的強型的觀點開始嘔吐

InvalidOperationException異常:傳遞給ViewDataDictionary的模型項類型爲'My.StronglyView.ObjectType',但此ViewDataDictionary實例需要'My.ViewComponent.ObjectType'類型的模型項。

我不確定這種改變是有意的,但它絕對不是我們所期望的。

我還沒有時間研究這種「突破」變化的原因,但我帶來了一個解決方案。

事情是,如果你傳遞一個空對象給你的ViewComponent.View()方法,我們會得到這個異常。任何通過它的非空對象都會更新ViewData。ModelExplorer和正確的對象類型將被註冊,避免這種例外。

使用Tester-Doer模式,在.Net Framework的某些類中使用相同的模式,我們現在可以將一個非空對象傳遞給ViewComponent,並根據需要使用它和它的包裝對象。

我所做的就是,我創建了一個接口IViewComponentModel<T>爲如下ViewComponentModel<T>類:

// Interface for ViewComponentModel 
public interface IViewComponentModel<T> 
    where T : class 
{ 
    T Data { get; } 
    bool HasData(); 
} 

// ViewComponentModel class for the Strongly-Type View Component 
public class ViewComponentModel<T> : IViewComponentModel<T> 
    where T : class 
{ 
    public T Data { get; private set; } 

    public ViewComponentModel(T data) 
    { 
     Data = data; 
    } 

    public bool HasData() => Data != null; 
} 

在我ViewComponent類實現,我回到View(new ViewComponentModel<AnyReferenceType>(myModel));

public async Task<IViewComponentResult> InvokeAsync() 
{ 
    var myViewData = _myService.GetSomeObjectForMyViewComponent(); 
    var model = new ViewComponentModel<MyViewDataType>(myViewData); 

    return await Task.FromResult(View(model)); 
} 

最後,在我的組件視圖(.cshtml)我的代碼如下:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 
@model ViewComponentModel<MyViewDataType> 

現在,您可以在視圖內使用此對象做任何事情,並使用您的真實模型,只需撥打@Model.Data即可。

通過這種方式,我們永遠不會將空對象傳遞給ViewComponent,也不會從View繼承對象類型。

希望它有幫助!

+0

Yea ..在發行說明中找不到任何信息。但很酷..我會試試看。感謝Alex – danial

0

默認情況下,它會嘗試在「父視圖」的模式通過,不知道你會叫什麼,嘗試更新這樣的代碼

@Component.InvokeAsync("LoginViewComponent", new App.Components.LoginViewComponent()) 

,使局部視圖可以有什麼需求,以提供它的內容。

+0

嗯,這並沒有工作,但我認爲解決方法是通過ViewComponent InvokeAsync方法傳入實例化的ViewModel實例。非常感謝 – danial

0

簡單的解決方案是,在ViewComponent類檢查空的視圖模型,如果視圖模型爲空,則返回空內容結果如下:

public async Task<IViewComponentResult> InvokeAsync() 
{ 
    var vm = some query for ViewModel; 

    if(vm != null) 
    { 
     return View(vm); 
    } 

    return Content(""); 
}