InvalidOperationException在强类型视图中呈现ViewComponent

dan*_*ial 4 asp.net-core-mvc .net-core asp.net-core asp.net-core-1.1

最近更新的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'.)
Run Code Online (Sandbox Code Playgroud)

Index.cshtml呈现LoginViewComponent:

@model App.Models.HomeViewModel
<html>
   @Component.InvokeAsync("LoginViewComponent")
</html>
Run Code Online (Sandbox Code Playgroud)

查看/主页/ Index.cshtml

ViewComponent LoginViewComponent/Default.cshtml只是一个显示模型信息的类:

@model App.Components.LoginViewCompoent
<body>
    <div>@Html.DisplayFor(v=>v.LoginName)</div>
</body>
Run Code Online (Sandbox Code Playgroud)

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

Default.cshtml中删除@model指令时,它呈现正常.

是不是ViewComponent假设与包装它的父视图分开并且不可知?从异常看,似乎需要在HomeViewModel类中声明LoginViewComponent ViewComponent 才能呈现它.

在asp.net核心github上找不到任何关于此的更改说明.

对此的评论和帮助将不胜感激.

Ale*_*x.H 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;
}
Run Code Online (Sandbox Code Playgroud)

在我的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));
}
Run Code Online (Sandbox Code Playgroud)

最后,在我的组件视图(.cshtml)中,我有以下代码:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model ViewComponentModel<MyViewDataType>
Run Code Online (Sandbox Code Playgroud)

现在,您可以在视图内部使用此对象执行任何操作,并使用您的真实模型,只需调用即可@Model.Data.

这样,我们永远不会将null对象传递给ViewComponent,也不会从View中"继承"对象类型.

希望它有所帮助!