2

_PaginationPartialView.cshtml:

@model IPagedListViewModel<object>
<p>PartialTest</p>

Index.cshtml:

@model PagedDocumentList
Html.RenderPartial("_PaginationPartialView", Model);

IPagedListViewModel.cs & PagedDocumentList.cs:

 public class PagedDocumentList : IPagedListViewModel<DocumentEntity>
 {
    public PagedDocumentList()
    {
        ListOfItems = new List<DocumentEntity>();
    }

    public int NumberOfPagesAvailable { get; set; }
    public int CurrentPageIndex { get; set; }
    public int PageSize { get; set; }
    public List<DocumentEntity> ListOfItems { get; set; }
 }

 public interface IPagedListViewModel<T>
 {
    int NumberOfPagesAvailable { get; set; }
    int CurrentPageIndex { get; set; }
    int PageSize { get; set; }
    List<T> ListOfItems { get; set; }
 }

I am attempting to pass a concrete type into the partial view however I am getting the following error:

The model item passed into the dictionary is of type 'PagedDocumentList', but this dictionary requires a model item of type 'IPagedListViewModel`1[System.Object]'.

Since PagedDocumentList implements IPagedListViewModel, I expected that I would be able to pass the concrete instance into the partial view and then read the object properties within the partial view. How can I use a single partial view that accepts an interface of generic type?

Workarounds I don't like:

If I update the partial to consume a model of:

@model IPagedListViewModel<DocumentEntity>

Then the partial renders as expected. But I don't want to Type my partial - I want to reuse it with different types.

I can also change the PagedDocumentList as follows:

public class PagedDocumentList
{
    public PagedDocumentList()
    {
        ListOfItems = new List<DocumentEntity>();
    }

    public PaginationDetails PaginationDetails { get; set; }
    public List<DocumentEntity> ListOfItems { get; set; }
}

public class PaginationDetails
{
    public int NumberOfPagesAvailable { get; set; }
    public int CurrentPageIndex { get; set; }
    public int PageSize { get; set; }
}

But then the interface would only enforce the existence of a concrete type, instead of serving as a signature in my partial view. I prefer to have the partial view accept a generic interface so I don't need to create a new class "just to make it work". PaginationDetails isn't really a class - it's a collection of properties that some classes may implement.

Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61
BLAZORLOVER
  • 1,971
  • 2
  • 17
  • 27
  • `PagedDocumentList` is derived from `IPagedListViewModel`, but the view expects `IPagedListViewModel`. What you call a work around is actually how it is suppose to be set `@model IPagedListViewModel` – Nkosi Jan 18 '19 at 01:03
  • I don't understand what's not clear about `But I don't want to Type my partial - I want to reuse it with different types.` @Nkosi – BLAZORLOVER Jan 18 '19 at 01:04
  • 1
    I clearly understand that. I am just telling you that is not how the system was designed for that version of asp.net-mvc. reusable view components were added in core because of that very limitation of the previous version. – Nkosi Jan 18 '19 at 01:05
  • @Nkosi *that* is good to know. So it's a framework limitation until Core. If you would like to create an answer explaining this, I'll mark it as the answer. Would love to see what the MVC Core solution would look like as a bonus! – BLAZORLOVER Jan 18 '19 at 01:09
  • Reference [View components in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-2.2) – Nkosi Jan 18 '19 at 01:11

1 Answers1

0

Hope I understood your question correctly. (please give me reason before downvote lol). I will make some changes. Firstly, your interface suits more like an abstract class. Interfaces (in my understands) have methods (verbs). Methods have implementation.

 public abstract PagedListViewModel
 {
    int NumberOfPagesAvailable { get; set; }
    int CurrentPageIndex { get; set; }
    int PageSize { get; set; }
 }

Your view needs to be strongly typed (like a particular type not generic). So, your child class will be used here.

@model PagedDocumentList
// rest of the code

Now, your partial view:

@model PagedListViewModel
@Html.EditorFor(o=>o.NumberOfPagesAvailable)
@Html.EditorFor(o=>o.PageSize)
Gauravsa
  • 6,330
  • 2
  • 21
  • 30