Home > Blockchain >  Wep api .NET C#: how can I select only a few attribute from a model using a GET method?
Wep api .NET C#: how can I select only a few attribute from a model using a GET method?

Time:10-05

I'm trying to have a GET method that selects only some attributes from this model:

namespace Sims.Models
{
    public partial class User
    {
        public User()
        {
            DataUsages = new HashSet<DataUsage>();
        }

        public long IdUser { get; set; }
        public int UserProfessionId { get; set; }
        public int UserProfessionFieldId { get; set; }
        public string? UserName { get; set; }
        public string? UserMail { get; set; }
        public string? UserCompany { get; set; }
        public byte[]? UserPicture { get; set; }

        public virtual Profession UserProfession { get; set; } = null!;
        public virtual ProfessionField UserProfessionField { get; set; } = null!;
        public virtual ICollection<DataUsage> DataUsages { get; set; }
    }
}

Among these attributes, I would like to get the IdUser, the UserName, the UserMail, the UserCompany, the Profession (another model from which I would like to have only the id, IdProfession, and the name, ProfessionName) and the ProfessionField (same than for Profession).

I'm not interested in getting the UserProfessionId, UserProfessionFieldId,the UserPicture or the DataUsage.

From Profession, I would like to get only the id and the name. Here's the model:

namespace Sims.Models
{
    public partial class Profession
    {
        public Profession()
        {
            ProfessionFields = new HashSet<ProfessionField>();
            Users = new HashSet<User>();
        }

        public int IdProfession { get; set; }
        public string ProfessionName { get; set; } = null!;

        public virtual ICollection<ProfessionField> ProfessionFields { get; set; }
        public virtual ICollection<User> Users { get; set; }
    }
}

Now this is the get method that I want to improve:

        // GET: api/Users
        [HttpGet]
        public async Task<ActionResult<IEnumerable<User>>> GetUsers()
        {
            return await _context.Users
                //.Include(u => u.UserProfession)
                .Select(u => new User {
                    IdUser = u.IdUser,
                    UserName =u.UserName,
                    UserMail = u.UserMail,
                    UserCompany = u.UserCompany,
                    UserProfessionField = u.UserProfessionField
                })
                .ToListAsync();
        }

And this is the current result:

[
  {
    "idUser": 1,
    "userProfessionId": 0,
    "userProfessionFieldId": 0,
    "userName": "user_test",
    "userMail": "[email protected]",
    "userCompany": "TestCompany",
    "userPicture": null,
    "userProfession": null,
    "userProfessionField": {
      "idProfessionField": 1,
      "professionFieldName": "Sports",
      "professionId": 1,
      "profession": null,
      "users": []
    },
    "dataUsages": [
      {
        "idDataUsage": 1,
        "openDataId": 1,
        "dateOfUsage": "2020-01-19T19:55:33",
        "dataFormatId": 18,
        "languageId": 1,
        "isDownloaded": 0,
        "usedBy": 1,
        "dataFormat": null,
        "language": null,
        "openData": null,
        "usedByNavigation": null
      }
    ]
  },
  {
    "idUser": 2,
    "userProfessionId": 0,
    "userProfessionFieldId": 0,
    "userName": "roger_federer",
    "userMail": null,
    "userCompany": null,
    "userPicture": null,
    "userProfession": null,
    "userProfessionField": {
      "idProfessionField": 1,
      "professionFieldName": "Sports",
      "professionId": 1,
      "profession": null,
      "users": []
    },
    "dataUsages": [
      {
        "idDataUsage": 2,
        "openDataId": 1,
        "dateOfUsage": "2020-09-02T13:43:10",
        "dataFormatId": 18,
        "languageId": 2,
        "isDownloaded": 0,
        "usedBy": 2,
        "dataFormat": null,
        "language": null,
        "openData": null,
        "usedByNavigation": null
      }
    ]
  },
  {
    "idUser": 3,
    "userProfessionId": 0,
    "userProfessionFieldId": 0,
    "userName": null,
    "userMail": null,
    "userCompany": null,
    "userPicture": null,
    "userProfession": null,
    "userProfessionField": {
      "idProfessionField": 4,
      "professionFieldName": "API dev",
      "professionId": 3,
      "profession": null,
      "users": []
    },
    "dataUsages": [
      {
        "idDataUsage": 3,
        "openDataId": 2,
        "dateOfUsage": "2022-08-10T07:08:02",
        "dataFormatId": 10,
        "languageId": 1,
        "isDownloaded": 1,
        "usedBy": 3,
        "dataFormat": null,
        "language": null,
        "openData": null,
        "usedByNavigation": null
      }
    ]
  }
]

Thanks for reading !

CodePudding user response:

Create small DTO (Data Transfer Object) objects that include only the attributes you want to get.

 public partial class UserDto
{
    public long IdUser { get; set; }
    public string? UserName { get; set; }
    public string? UserMail { get; set; }
    public string? UserCompany { get; set; }

    public virtual ProfessionDto UserProfession { get; set; } = null!;
    public virtual ProfessionFieldDto UserProfessionField { get; set; } = null!;
}

public partial class ProfessionDto
{
    public int IdProfession { get; set; }
    public string ProfessionName { get; set; } = null!;
}

public partial class ProfessionFieldDto // idk why its same but here you are
{
    public int IdProfession { get; set; }
    public string ProfessionName { get; set; } = null!;
}

Then you can fill them and return them. You can use AutoMapper for filling them, or fill them by yourself. :-).

Using automapper:

    // GET: api/Users
    [HttpGet]
    public async Task<ActionResult<IEnumerable<UserDto>>> GetUsers()
    {
        return _mapper.Map<IEnumerable<UserDto>>(_context.Users.ToListAsync());
}

By yourself:

// GET: api/Users
    [HttpGet]
    public async Task<ActionResult<IEnumerable<UserDto>>> GetUsers()
    {
        var users = _context.Users.ToList();
        var userDtos = new List<UserDto>();
        foreach(var user in users){
               userDtos.Add(new UserDto{Id = user.id..., Name = user.name...}
        }
        return userDtos;
}

CodePudding user response:

You're returning your entity model as the result set, either create a model for the returned object containing the properties you want within it and map it using something like AutoMapper, eg.

{
    public partial class PublicUser
    {
        public User()
        {
            DataUsages = new HashSet<DataUsage>();
        }

        public long IdUser { get; set; }
        public string? UserName { get; set; }
        public string? UserMail { get; set; }
        public string? UserCompany { get; set; }

        public virtual ProfessionField UserProfessionField { get; set; } = null!;
    }

Followed by:

        [HttpGet]
        public async Task<ActionResult<IEnumerable<PublicUser>>> GetUsers()
        {
            return yourMapper.Map<IEnumerable<PublicUser>>(await _context.Users
                .Include(u => u.UserProfession)
                .Select(u => new User {
                    IdUser = u.IdUser,
                    UserName =u.UserName,
                    UserMail = u.UserMail,
                    UserCompany = u.UserCompany,
                    UserProfessionField = u.UserProfessionField
                })
                .ToListAsync());
        }
;

Or alternatively if you're locked into using that model, you can consider ignoring null values within your json configuration, and then avoid sending the null values that way, eg.

services.AddControllers().AddNewtonsoftJson(x =>
            {
                x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                x.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            });

Hope that helps :)

  • Related