Chatra
Chatra

Reputation: 3139

How should I return two lists of objects from one Controller Action?

I am having two different list coming from same object. I want to get those two at same time as separate list or join those two same list when returning JSON object.

Here is my code.

List<User> userEntity = users.Where(s => s.Id == Id).ToList();

var GetUserNames = userEntity.SelectMany(s => s.Names.Select(u =>
    new
    {
        Name = u.Name,
        Id = u.Id
    })).ToList();

var GetProfile = userEntity.SelectMany(s => s.Profile.Select(u =>
    new
    {
        Name = u.Name,
        Id = u.Id
    })).ToList();

return Json(GetUserNames, JsonRequestBehavior.AllowGet);

Upvotes: 4

Views: 16279

Answers (2)

Tetsujin no Oni
Tetsujin no Oni

Reputation: 7375

I would prefer to do this differently: the returned items are different types. Rather than returning a bare JSON list with a type discriminator, return a multiproperty JSON object:

return Json(new 
{ 
    Names = GetUserNames, 
    Profiles = GetProfile 
}, JsonRequestBehavior.AllowGet);

Your returned JSON will have the {Name, Id} objects separated into their types, in sketch form:

{ 
  Names: [
   {Name:"UserName", Id:"3"}, 
   {Name:"OtherUser", Id: "4"}
  ],
  Profiles: [
   {Name:"Normal", Id:"1"}, 
   {Name:"Admin", Id: "99"}
  ]
}

In most JSON.Net client side parsing scenarios (i.e. consuming a WebAPI from a WPF smart client), you automatic mapping (such as from RestSharp) would allow you to deserialize this into a class of the form

public class NameId
{
     public int Id {get; set;}
     public string Name {get; set;}
}

public class UserNamesResponse
{
     public List<NameId> Names {get; set;}
     public List<NameId> Profiles {get; set;}
}

This may be more convenient and clearer to work with than an interleaved list which must be filtered into separate lists for binding anyway.... (or fed through filtering type converters at a performance penalty in the UI binding layer...)

Upvotes: 9

hutchonoid
hutchonoid

Reputation: 33326

You could use GetUserNames.Concat(GetProfile).

List<User> userEntity = users.Where(s => s.Id == Id).ToList();

var GetUserNames = userEntity.SelectMany(s => s.Names.Select(u =>
    new
    {
        Name = u.Name,
        Id = u.Id
    })).ToList();

var GetProfile = userEntity.SelectMany(s => s.Profile.Select(u =>
  new
  {
      Name = u.Name,
      Id = u.Id
  })).ToList();

return Json(GetUserNames.Concat(GetProfile) , JsonRequestBehavior.AllowGet);

Enumerable.Concat Method

Update as per comments

Create a class and enum:

public class NameId
{
    public string  Name {get;set;}
    public string  Id {get;set;}
    public ThisType Type { get; set; }
}

public enum ThisType
{
   Username,
   Profile
}

Then return that instead:

List<User> userEntity = users.Where(s => s.Id == Id).ToList();

var GetUserNames = userEntity.SelectMany(s => s.Names.Select(u =>
    new NameId
    {
        Name = u.Name,
        Id = u.Id,
        Type = ThisType.Username
    })).ToList();

var GetProfile = userEntity.SelectMany(s => s.Profile.Select(u =>
  new NameId
  {
      Name = u.Name,
      Id = u.Id,
      Type = ThisType.Profile
  })).ToList();

return Json(GetUserNames.Concat(GetProfile) , JsonRequestBehavior.AllowGet);

Upvotes: 3

Related Questions