4

I have a custom collection that has own properties.

 public interface IPagedList<T>: IList<T>
 {
     int TotalCount { get; }
 }

And I have a class that implemented IPagedList interface.

 public class PagedList<T> : List<T>, IPagedList<T>
 {
        public PagedList(IQueryable<T> source){
        AddRange(source);
        }

    public int TotalCount { get; private set; }
 }

When I used PagedList<T> class in my web api application, the TotalCount property does not serialized.

public class EmpolyeeController : ApiController
{
    public IHttpActionResult Get()
    {
        IPagedList<Employee> response = new PagedList<Employee>(Database.GetEmplyees());

        return Ok(response);
    }

}

The response is like this:

[
    {
        "Id": "1230a373-af54-4960-951e-143e75313b25",
        "Name": "Deric"
    }
]

But I want to see TotalCount property in json response.

enter image description here

The property in Raw View as you can see in screencast.

(I think this is a Raw View of IList serialization problem of json.net. How can I add middleware Raw View serailization)

barteloma
  • 6,403
  • 14
  • 79
  • 173
  • How do you serialize? Do you use JsonConvert.SerializeObject? – Harald Coppoolse Oct 26 '17 at 13:05
  • Serialization done by web api action nethod. I do not use any serialization tool – barteloma Oct 26 '17 at 13:07
  • Interesting. I wonder how you get a json response, without using jsonconverter – Harald Coppoolse Oct 26 '17 at 13:21
  • Web api uses implicitly jsonconverter – barteloma Oct 26 '17 at 13:32
  • You're returning an `IPagedList`, not a `PagedList` (I mean, yeah, polymorphism). Does it work if you assign to a concrete type? Truly, though, what benefit are you going to gain by returning the interface from your controller anyway? Controllers don't get invoked by other classes (outside of ASP.NET). – Kenneth K. Oct 26 '17 at 13:35
  • I tried concreate PagedList and I see property on breakpoint as RawView like updated image post – barteloma Oct 26 '17 at 13:36
  • So how do you want response to look like exactly? I understand you want to include totalCount, but what is the final format of response? – Evk Oct 26 '17 at 14:33

1 Answers1

0

Not realy perfect, but you could treat it as Object via JsonObject Attribute:

[JsonObject]
public class PagedList<T> : List<T>, IPagedList<T>
{
    public PagedList(IQueryable<T> source)
    {
        AddRange(source);
    }

    public IEnumerable<T> Data => this.ToList();

    public int TotalCount { get; private set; }
}

The key part is public IEnumerable<T> Data => this.ToList(); which still returns the IEnumerable. I tried only this, but this does not seem to work (recursion). That's because I call ToList().

Result:

{
    "Data": [
        {
            "Foo": "Foo",
            "Bar": "Bar"
        }
    ],
    "TotalCount": 0,
    "Capacity": 4,
    "Count": 1
}

As an alternative, you could use a custom JsonConverter.

You should also ask your self, why do you need to extend List in first case?

The imho better aproach would be transfering your data into a specific response model:

MyResponseModel<T>
{
     public int TotalCount { get; set; }
     public IEnumerable<T> Data { get; set; }
}

A service should then be responsible in providing it.

Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
  • Yes it will work but it is a XY Problem solution - https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – Ipsit Gaur Oct 26 '17 at 14:20
  • PagedList includes a data from IList<> and you set a new property to store collection data. – barteloma Oct 27 '17 at 05:56