InvalidOperationException 在强类型视图中渲染 ViewComponent [英] InvalidOperationException rendering ViewComponent in Strongly-Typed View

查看:23
本文介绍了InvalidOperationException 在强类型视图中渲染 ViewComponent的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近更新的 dotnet core 1.0.1 到 1.1 和 MVC 中的 ViewComponent 开始失败,出现以下异常:

Recently updated dotnet core 1.0.1 to 1.1 and ViewComponent in MVC starts failing with the below exception:

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>

Views/Home/Index.cshtml

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

The ViewComponent LoginViewComponent/Default.cshtml is just a class that displays it's model's info:

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

Views/Shared/Components/LoginViewComponent/Default.cshtml

当从 Default.cshtml 中删除 @model 指令时,它呈现良好.

It renders fine when the @model directives is removed from Default.cshtml.

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

Isn't ViewComponent suppose to be separated and agnostic from the parent view that is wrapping it? From the exception it seems that it would be require to declare the LoginViewComponent ViewComponent in HomeViewModel class in order to render it.

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

Couldn't find any change note on this on asp.net core github.

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

Comment and help on this would be greatly appreciated.

推荐答案

我遇到了同样的错误,我团队中有人将 Microsoft.AspNetCore.Mvc 版本从 1.0.0 更新到 1.1.0 和我在强类型视图中的一些组件开始抛出

I've came across the same error, someone in my team updated Microsoft.AspNetCore.Mvc version from 1.0.0 to 1.1.0 and some of the components I had in Strongly-Type views started throwing

InvalidOperationException:传入 ViewDataDictionary 的模型项的类型为 'My.StronglyView.ObjectType',但此 ViewDataDictionary 实例需要类型为 'My.ViewComponent.ObjectType' 的模型项.

InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'My.StronglyView.ObjectType', but this ViewDataDictionary instance requires a model item of type 'My.ViewComponent.ObjectType'.

我不确定此更改是否是有意为之,但这绝对不是我们所期望的.

I am not sure if this change was intentional, but it is definitely not what we would expect.

我没有时间研究这种重大"更改的原因,但我想出了一个解决方案.

I haven't got the time to research about the reasons of this 'breaking' change but I came with a solution.

事实是,如果你将一个空对象传递给你的 ViewComponent.View() 方法,我们就会得到这个异常.任何通过它的非空对象都会更新 ViewData.ModelExplorer 并且正确的对象类型会被注册,避免这个异常.

Thing is, if you pass a null object to your ViewComponent.View() method, we get this exception. Any non-null object passed through it, would update the ViewData.ModelExplorer and the correct object-type would have been registered, avoiding this exception.

使用 Tester-Doer 模式,与 .Net Framework 的某些类中使用的模式相同,我们现在可以将非空对象传递给 ViewComponent 并根据需要使用它及其包装的对象.

Using Tester-Doer pattern, same pattern used in some classes of .Net Framework, We can now pass a non-null object to the ViewComponent and use it and its wrapped object as We need.

我所做的是,我创建了一个接口 IViewComponentModel 作为 class ViewComponentModel 如下:

What I did was, I created a interface IViewComponentModel<T> as class ViewComponentModel<T> as below:

// 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(myModel));

In my ViewComponent class implementation, I return 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) 中,我有以下代码:

And finally, in my Component View (.cshtml) I have the code below:

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

现在你可以对视图中的这个对象做任何你想做的事情并使用你的真实模型,只需调用 @Model.Data 和瞧.

Now you can do whatever you want with this object inside of the view and to use your real model, just call @Model.Data and voilà.

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

In this way, We will never pass a null object to the ViewComponent and it won't 'inherit' the object type from the View.

希望有帮助!

这篇关于InvalidOperationException 在强类型视图中渲染 ViewComponent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆