最近更新的dotnet核心1.0.1到1.1和MVC中的ViewComponent开始失败,但出现以下异常:
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
从 Default.cshtml 中删除 @model 指令后呈现正常。
ViewComponent是不是要与包装它的父视图分开并且不可知?从例外情况来看,似乎需要在 HomeViewModel 类中声明 LoginViewComponent ViewComponent才能呈现它。
在asp.net核心github上找不到任何关于此的更改说明。
对此的评论和帮助将不胜感激。
答案 0 :(得分:5)
我遇到了同样的错误,我的团队中有人将Microsoft.AspNetCore.Mvc
版本从1.0.0升级到1.1.0,并且我在Strongly-Type视图中的一些组件开始抛出
InvalidOperationException:传递给ViewDataDictionary的模型项的类型为'My.StronglyView.ObjectType',但此ViewDataDictionary实例需要类型为'My.ViewComponent.ObjectType'的模型项强>
我不确定这种改变是否是故意的,但绝对不是我们所期望的。
我没有时间研究这种“突破”变化的原因,但我找到了一个解决方案。
事情是,如果您将null对象传递给ViewComponent.View()
方法,我们会得到此异常。通过它传递的任何非null对象都会更新ViewData.ModelExplorer并且已经注册了正确的对象类型,从而避免了这种异常。
使用Tester-Doer模式,在.Net Framework的某些类中使用相同的模式,我们现在可以将一个非null对象传递给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
和vo。
通过这种方式,我们永远不会将null对象传递给ViewComponent,也不会从View中“继承”对象类型。
希望它有所帮助!
答案 1 :(得分:0)
默认情况下,它会尝试传递&#34;父视图&#34;的模型。 ,不确定你会怎么称呼,尝试更新你的代码
@Component.InvokeAsync("LoginViewComponent", new App.Components.LoginViewComponent())
以便部分视图可以拥有所需内容,以便提供其内容。
答案 2 :(得分:0)
简单的解决方案是,在ViewComponent类中,为视图模型检查null,如果视图模型为null,则返回空内容结果,如下所示:
public async Task<IViewComponentResult> InvokeAsync()
{
var vm = some query for ViewModel;
if(vm != null)
{
return View(vm);
}
return Content("");
}