2

I'm making webapi using .net core 2.2. And I'm new to .net framework So far I was working with javascript based frameworks like nodejs expressjs.

It's easy to customize JSON response in nodejs. Can you exaplain how to customize the JSON response with .NET Core 2.2 WebApi? Just point me to right direction.

Let me give an example,

C# User Model

public class User {
    int id {get;set;}
    string name {get;set;}
    string username {get;set;}
    string password {get;set;}
}

Default API Get Reponse.

public ActionResult<IEnumerable<User>> GetAll()

Json:

[
    {
        "id":1,
        "name": "John Doe",
        "username": "john",
        "password": "AH7B302Iapxf7EFzZVW0/kJDuf/I3pDPkQ42IxBTakA="
    },
    {   
        "id":2,
        "name": "Jane Doe",
        "username": "jane",
        "password": "AH7B302Iapxf7EFzZVW0/kJDuf/I3pDPkQ42IxBTakA="
    }
]

I need to customize the output like this.

{
    "statuscode": 200,
    "count"     : 2,
    "data"      : 

    [
        {
            "name": "John Doe",
            "username": "john",
        },
        {
            "name": "Jane Doe",
            "username": "jane",
        }
    ]
}
ibubi
  • 2,469
  • 3
  • 29
  • 50
Crizy Sash
  • 127
  • 1
  • 2
  • 11

2 Answers2

4

You can use anonymous objects, which comes in handy if you don't want to define a separate class for each and every result type:

public ActionResult<object> GetAll()
{
    var list = _userRepository.GetAll(); // <-- if this is not (yet) an Array or a List, then force single evaluation by adding .ToArray() or .ToList()
    var model = new
    {
        statuscode = 200,
        count = list.Count, // or .Length if list is an Array
        data = list.Select(x => new { name = x.name, username = x.userName })
    };
    return Ok(model);
}
Peter B
  • 22,460
  • 5
  • 32
  • 69
  • Nice. This is exactly what I'm expecting. Thanks a lot. – Crizy Sash Nov 27 '18 at 12:39
  • Peter, I see that the shape of the response is defined in the controller method. Why should it be defined here? Can't the repository or service shape the response and return it so that the controller can just deliver it? I am under the impression that controllers should have the least logic possible. – chiapa Jan 08 '21 at 09:52
  • @chiapa See here: [Repository, Service or Domain object - where does logic belong?](https://stackoverflow.com/q/2978146/1220550) – Peter B Jan 08 '21 at 10:11
3

I guess you are asking for a generic return object for your api, if it is so, you need to define a return object as follows,

Your return object model, as considering your all entities have a base type IEntity or a BaseEntity.

public class Result<T> where T: IEntity
{
    public int StatusCode { get; set; }
    public int Count { get; set; }
    public IEnumerable<T> Data { get; set; }
}

And a sample action method,

public IActionResult<IEnumerable<User>> GetAll()
{
    var list = _userRepository.GetAll();
    var model = new Result<User>
    {
        StatusCode = 200,
        Count = list.Count,
        Data = list
    };

    return Ok(model);
}
ibubi
  • 2,469
  • 3
  • 29
  • 50
  • change the action return type or update the class to be derived from `IEnumerable` – Nkosi Nov 27 '18 at 12:28
  • Yes, This is what I'm asking. Do I have to define classes for each custom JSON responses? – Crizy Sash Nov 27 '18 at 12:31
  • This will still output all 4 fields for each User object, instead of just `user` + `username`. – Peter B Nov 27 '18 at 12:39
  • @ibubi Thanks this is also helpful. – Crizy Sash Nov 27 '18 at 12:41
  • ibubi, I see that the shape of the response is defined in the controller method. Why should it be defined here? Can't the repository or service shape the response and return it so that the controller can just deliver it? I am under the impression that controllers should have the least logic possible. – chiapa Jan 08 '21 at 10:03
  • @chiapa Of course you can outsource this transformation to the service layer, but I tried to stick to OP implementation. And some APIs with simple CRUD might not need extra layers (abstraction), so this decision is up to the developer according to the heaviness of the logic or processes in the project. – ibubi Jan 08 '21 at 12:05
  • I questioned as in, what is the best option for an API that may change the services it uses, for maintainability. I have been using the controller map the message to a view model, but the message is shaped in the service, which is in turn fed by a repository. If I want to change the service, fine, and the mapping happens exactly the same in the controller with no change. But I have seen people building the objects in the controller which to me leaves them a bit dirtier with some logic there that I would rather keep in the service. – chiapa Jan 13 '21 at 09:14