1

I have this method in my web api:

[HttpGet("GetPerson/{id}")]
[Authorize(Roles = "Administrators")]
public async Task<(Person, List<ContactData>)> GetPerson(int id = 0)
{                
    Data.ThePerson person = new Data.ThePerson();
    List<ContactData> cDatas = person.contactDatas.Where(it => it.ContactId == id).ToList();
    var p = person.persons.FirstOrDefault(p => p.Id == id);
    return (p, cDatas);        
}

But the method returns (, ) in the client! How to correct this?

Client:

public async Task<(Person, List<ContactData>)> GetPerson(int id)
{
    var tuple = await Http.GetFromJsonAsync<(Person, List<ContactData>)>($"api/account/GetPerson/{id}");
    return tuple;
}

The server and client methods work when it only returns a Person object but converting it to tuple returns (, ). also I can see in the server that correct tuple builds and returns but in the client it is (, ).

3
  • Please edit your question to include the actual HTTP request and HTTP response (headers and bodies) you send/get when you use the GetPerson() service call. Also check other questions like stackoverflow.com/questions/58961133/… and stackoverflow.com/questions/50005989/… Commented Dec 18, 2023 at 9:12
  • Just to clarify Data.ThePerson person = new Data.ThePerson();; the constructor of ThePerson returns an object, which contains a collection "persons", that presumably includes all the persons in the repository? This seems remarkably inefficient, as well as being unnatural nomenclature (a noun in the singular housing a collection of itself in the plural). Why do you not have a constructor that simply takes an id? Commented Dec 18, 2023 at 9:51
  • The backend is not yet designed I use static data for now. Commented Dec 18, 2023 at 9:55

2 Answers 2

1

The issue might be related to serialization and deserialization of the tuple when returning it from the API.

You can use a simple class to hold both the Person and List<ContactData> as properties. Use this class as the return type for your API method instead of a tuple.

public class PersonData
{
    public Person Person { get; set; }
    public List<ContactData> ContactData { get; set; }
}

Modify your API method to return the PersonData class:

[HttpGet("GetPerson/{id}")]
[Authorize(Roles = "Administrators")]
public async Task<PersonData> GetPerson(int id = 0)
{                
    Data.ThePerson person = new Data.ThePerson();
    List<ContactData> cDatas = person.contactDatas.Where(it => it.ContactId == id).ToList();
    var p = person.persons.FirstOrDefault(p => p.Id == id);

    return new PersonData
    {
        Person = p,
        ContactData = cDatas
    };
}

Update your client method to handle the PersonData class:

public async Task<PersonData> GetPerson(int id)
{
    return await Http.GetFromJsonAsync<PersonData>($"api/account/GetPerson/{id}");
}
Sign up to request clarification or add additional context in comments.

Comments

0

As far as I see (at least in .NET 9), you can achieve your goal indirecty as well, without defining extra classes, simply by using anonymous types.
You should only alter the method signature and the return statement, for example:

public async Task<IActionResult> GetPerson(int id = 0)
{                
    Data.ThePerson person = new Data.ThePerson();
    List<ContactData> cDatas = person.contactDatas.Where(it => it.ContactId == id).ToList();
    var p = person.persons.FirstOrDefault(p => p.Id == id);
    return new { Person = p, ContactDataList = cDatas};         
}

Of course, it is only a workaround, and definitely not a solution for your original problem.
Some background, why returning tuple types does not work: They are only syntax sugar provided by the compiler, and converted into classes having properties like Item1, Item2, as described here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.