简体   繁体   中英

How to return an object with a collection instead of just the collection from a Web API?

At the moment, in my controller's service method GetSubAccounts(accountId) , I have this:

Account account = await context.Accounts.SingleOrDefaultAsync(x => x.Id == accountId);
IQueryable<Account> subAccounts = context.Accounts.Include(x => x.AccountCodes).AsNoTracking();

return await mapper.ProjectTo<SubAccountViewModel>(subAccounts, null, x => x.SubAccounts)
    .Where(x => x.PersonId == account.PersonId && x.AccountId != null).ToListAsync();

My SubAccountViewModel is as follows: (note that it has a collection of itself)

public class SubAccountViewModel : Base.AccountViewModel
{
    public virtual ICollection<AccountCodeViewModel> AccountCodes { get; set; }

    public virtual ICollection<SubAccountViewModel> SubAccounts { get; set; }
}

My mapping profile is:

internal class SubAccountMappingProfile : Profile
{
    public SubAccountMappingProfile()
    {
        CreateMap<Account, SubAccountViewModel>()
            .ForMember(x => x.AccountCodes, options => options.ExplicitExpansion())
            .ForMember(x => x.SubAccounts, options => options.ExplicitExpansion())
            .ReverseMap();
    }
}

And this is the JSON I'm getting as a result:

[
    {
        "id":"c236718f-9d91-4eea-91ee-66760a716343",
        "personId":"06d3857d-6a49-4e1c-b63c-7edc83d30cbd",
        "accountId":null,
        "username":"test same person",
        "email":"testsameperson@gmail.com",
        "birthDate":"2021-01-02",
        "subaccounts":null
    }
]

The problem:

I'm getting a top-level array of subaccounts for the accountId parameter I pass to the method. Fine. (There's just one, but nevermind that.)

What I do want is the main account at top-level, with the array of subaccounts as part of it.

Ie

{
    "id":"f61fedc2-eb60-4ba9-9d17-8d41b9cae9f1",
    "personId":"06d3857d-6a49-4e1c-b63c-7edc83d30cbd",
    "accountId":"f61fedc2-eb60-4ba9-9d17-8d41b9cae9f1",
    "username":"test person",
    "email":"testperson@gmail.com",
    "birthDate":"2021-01-01",
    "subaccounts":[
        {
            "id":"c236718f-9d91-4eea-91ee-66760a716343",
            "personId":"06d3857d-6a49-4e1c-b63c-7edc83d30cbd",
            "accountId":"f61fedc2-eb60-4ba9-9d17-8d41b9cae9f1",
            "username":"test same person",
            "email":"testsameperson@gmail.com",
            "birthDate":"2021-01-02",
            "subaccounts":null
        }
    ]
}

How do I do it?

The problem was one of logic.

To start with, my service method (and my API controller) was returning Task<IEnumerable<SubAccountViewModel>> , when it should return Task<SubAccountViewModel> .

Then my solution was:

Account account = await context.Accounts.SingleOrDefaultAsync(x => x.Id == accountId);
            
IQueryable<Account> accounts = context.Accounts.AsNoTracking();

SubAccountViewModel subAccountViewModel = await mapper.ProjectTo<SubAccountViewModel>(accounts, null, x => x.AccountCodes)
.SingleOrDefaultAsync(x => x.Id == accountId);

subAccountViewModel.SubAccounts = await mapper.ProjectTo<SubAccountViewModel>(accounts, null, x => x.AccountCodes, x => x.SubAccounts)
    .Where(x => x.PersonId == account.PersonId && x.AccountId != null).ToListAsync();

return subAccountViewModel;

This returns the resultset I wanted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM