Search code examples
asp.net-mvcasp.net-core-mvcasp.net-core-2.0asp.net-core-viewcomponent

ASP.NET MVC Core 2. How avoid a component use the same model as the parent view?


I'm creating a view component (filter component) which are invoked from a main view.

the main view requires a list as a model

@model IEnumerable<Filters>

and on its header, its invokes the filters ViewComponent

<vc:my-filter/>

The Default.cshtml component view requires a Filter class

@model Filters

However when filter is null the component model receives the same model from the parent view. and the types are incompatible;

InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[Item]', but this ViewDataDictionary instance requires a model item of type 'Filters'.

I rather not to pass an empty new Filter() to the ViewComponent view model cause the component has some null validations already implemented.

I would like to do not send any model to the view component. How can I do it? I just don't want to it have access to the main page view model.


Solution

  • This is a breaking change in v1.1 of .NET Core not v2.0 and the behavior was discussed here.

    ViewComponent initial ViewDataDictionary is taken from the calling View. In other terms it is either the same as the View ViewDataDictionary or a clone of it. This makes sense to pass main View error infos, etc. to the ViewComponent.

    Now if ViewComponent passes a not null model to the View, the not null model is attached to its ViewDataDictionary, thus causing all Model Metadata to be recomputed to match the new model, so in this case everything works properly.

    However, if the model is null, the ViewComponent ViewDataDictionary remains untouched, and is used to create its View ViedDataDictionary. This, in turn means, that the ViewComponent View receives a ViewDataDictionary cloned from the View that called the ViewComponent.

    The issue is tracked at https://github.com/aspnet/Announcements/issues/221.

    Also, you can use a workaround mentioned in this answer.