I am new at C# ASP.Net Entity Framework . I am trying to build an API and I want to produce an output like this :
[
{
"userId": 1275,
"username": "dmartin",
"email": "[email protected]",
"firstName": "Dan",
"middleInitial": "",
"lastName": "Martin",
"isApproved": true,
"lastActivityDate": "2012-10-05T12:23:24.253",
"lastLoginDate": "2021-10-27T09:13:56.597",
"lastPasswordChangedDate": "2020-07-29T16:06:41.863",
"creationDate": "2010-04-07T22:51:14",
"Iscinstance":[
{
"iscinstanceId": 236,
"name": "ABA"
}
],
"UserProfile":[
{
"profileName": "",
"address1": "",
"directConnectPhone": "",
"profileEmail": "",
"profile": null
}
]
}
]
A have this classis created with table relationships :
User Table
[DataContract]
public partial class User
{
[DataMember]
public int UserId { get; set; }
[DataMember]
public string Username { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public bool IsApproved { get; set; }
[DataMember]
public DateTime? LastActivityDate { get; set; }
[DataMember]
public DateTime? LastLoginDate { get; set; }
[DataMember]
public DateTime? LastPasswordChangedDate { get; set; }
[DataMember]
public DateTime? CreationDate { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public string MiddleInitial { get; set; }
public virtual UserProfile Profile { get; set; }
public virtual LinkUsersToIscinstance LinkUsersToIscinstances { get; set; }
}
UserProfile Table
[DataContract]
public partial class UserProfile
{
public UserProfile()
{
LinkUsersToIscinstances = new HashSet<LinkUsersToIscinstance>();
Users = new HashSet<User>();
}
[DataMember]
public int ProfileId { get; set; }
[DataMember]
public string ProfileName { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public string DirectConnectPhone { get; set; }
[DataMember]
public string EmergencyContactNumber { get; set; }
[DataMember]
public string Address1 { get; set; }
[DataMember]
public string Address2 { get; set; }
[DataMember]
public string County { get; set; }
[DataMember]
public int State { get; set; }
[DataMember]
public string Zip { get; set; }
[DataMember]
public string EmergencyCell { get; set; }
public virtual ICollection<LinkUsersToIscinstance> LinkUsersToIscinstances { get; set; }
public virtual ICollection<User> Users { get; set; }
}
LinkUsersToIscinstance Table
[DataContract(IsReference = true)]
public partial class LinkUsersToIscinstance
{
public LinkUsersToIscinstance()
{
Users = new HashSet<User>();
}
public int LinkId { get; set; }
[DataMember]
public int IscinstanceId { get; set; }
[DataMember]
public int UserId { get; set; }
public virtual UserProfile Profile { get; set; }
public virtual Iscinstance Iscinstances { get; set; }
public virtual ICollection<User> Users { get; set; }
}
Iscinstance Table
[DataContract]
public partial class Iscinstance
{
public Iscinstance()
{
LinkUsersToIscinstances = new HashSet<LinkUsersToIscinstance>();
}
[DataMember]
public int IscinstanceId { get; set; }
[DataMember]
public string Name { get; set; }
public virtual ICollection<LinkUsersToIscinstance> LinkUsersToIscinstances { get; set; }
}
I also created a custom class but I think a wont be needing it, here it is :
[DataContract]
public class CustomClass
{
[DataMember]
public int IscinstanceId { get; set; }
//[DataMember(Name = "ISCInstanceName")]
[DataMember]
public string? Name { get; set; }
[DataMember]
public int UserId { get; set; }
[DataMember]
public string? Username { get; set; }
[DataMember]
public string? Email { get; set; }
[DataMember]
public string? FirstName { get; set; }
[DataMember]
public string? MiddleInitial { get; set; }
[DataMember]
public string? LastName { get; set; }
[DataMember]
public bool IsApproved { get; set; }
[DataMember]
public DateTime? LastActivityDate { get; set; }
[DataMember]
public DateTime? LastLoginDate { get; set; }
[DataMember]
public DateTime? LastPasswordChangedDate { get; set; }
[DataMember]
public DateTime? CreationDate { get; set; }
[DataMember]
public string? ProfileName { get; internal set; }
[DataMember]
public string? Address1 { get; internal set; }
[DataMember]
public string? DirectConnectPhone { get; internal set; }
[DataMember]
public string? ProfileEmail { get; internal set; }
}
And this is my query :
var customer = await _context.Users
.Where(c => c.UserId == UserId && c.LastActivityDate > date && c.IsApproved == num)
.Include(c => c.Profile)
.Include(c => c.LinkUsersToIscinstances).ThenInclude(c => c.Iscinstances)
.OrderBy(c => c.LinkUsersToIscinstances.Iscinstances.Name).ThenBy(c => c.LastName).ThenBy(c => c.FirstName)
.Select(c => new CustomClass
{
IscinstanceId = c.LinkUsersToIscinstances.Iscinstances.IscinstanceId,
Name = c.LinkUsersToIscinstances.Iscinstances.Name,
UserId = c.UserId,
Username = c.Username,
Email = c.Email,
FirstName= c.FirstName,
MiddleInitial= c.MiddleInitial,
LastName= c.LastName,
IsApproved= c.IsApproved,
LastActivityDate= c.LastActivityDate,
LastLoginDate= c.LastLoginDate,
LastPasswordChangedDate= c.LastPasswordChangedDate,
CreationDate= c.CreationDate,
ProfileName = c.Profile.ProfileName,
ProfileEmail = c.Profile.Email,
DirectConnectPhone = c.Profile.DirectConnectPhone,
Address1 = c.Profile.Address1
})
.ToListAsync();
This is my current output
[
{
"iscinstanceId": 236,
"name": "ABA",
"userId": 1275,
"username": "dmartin",
"email": "[email protected]",
"firstName": "Dan",
"middleInitial": "",
"lastName": "Martin",
"isApproved": true,
"lastActivityDate": "2012-10-05T12:23:24.253",
"lastLoginDate": "2021-10-27T09:13:56.597",
"lastPasswordChangedDate": "2020-07-29T16:06:41.863",
"creationDate": "2010-04-07T22:51:14",
"profileName": "",
"address1": "",
"directConnectPhone": "",
"profileEmail": "",
"profile": null
}
]
Hoping anyone could help me :(
CodePudding user response:
From your backend code, it seems one User
have one UserProfile
and Iscinstance
, but your expected json here is a List object:
"Iscinstance":[
{
"iscinstanceId": 236,
"name": "ABA"
}
],
"UserProfile":[
{
"profileName": "",
"address1": "",
"directConnectPhone": "",
"profileEmail": "",
"profile": null
}
]
If you actually want this type of json, you need change your CustomClass
to:
public class CustomClass
{
public int UserId { get; set; }
public string? Username { get; set; }
public string? Email { get; set; }
public string? FirstName { get; set; }
public string? MiddleInitial { get; set; }
public string? LastName { get; set; }
public bool IsApproved { get; set; }
public DateTime? LastActivityDate { get; set; }
public DateTime? LastLoginDate { get; set; }
public DateTime? LastPasswordChangedDate { get; set; }
public DateTime? CreationDate { get; set; }
public List<dynamic>? Iscinstance { get; set; }
public List<dynamic>? UserProfile { get; set; }
}
Controller:
var customer = await _context.User
.Where(c => c.UserId == UserId && c.LastActivityDate > date && c.IsApproved == num)
.Include(c => c.Profile)
.Include(c => c.LinkUsersToIscinstances).ThenInclude(c => c.Iscinstances)
.OrderBy(c => c.LinkUsersToIscinstances.Iscinstances.Name).ThenBy(c => c.LastName).ThenBy(c => c.FirstName)
.Select(c => new TestModel
{
UserId = c.UserId,
Username = c.Username,
Email = c.Email,
FirstName = c.FirstName,
MiddleInitial = c.MiddleInitial,
LastName = c.LastName,
IsApproved = c.IsApproved,
LastActivityDate = c.LastActivityDate,
LastLoginDate = c.LastLoginDate,
LastPasswordChangedDate = c.LastPasswordChangedDate,
CreationDate = c.CreationDate,
Iscinstance = new List<dynamic>() {
new {
IscinstanceId= c.LinkUsersToIscinstances.Iscinstances.IscinstanceId,
Name = c.LinkUsersToIscinstances.Iscinstances.Name
}
},
UserProfile = new List<dynamic> {
new {
ProfileName = c.Profile.ProfileName,
ProfileEmail = c.Profile.Email,
DirectConnectPhone = c.Profile.DirectConnectPhone,
Address1 = c.Profile.Address1
}
}
})
.ToListAsync();
CodePudding user response:
First, you need some classes to represent the expected json result :
public class UserModel
{
public int UserId { get; set; }
public string? Username { get; set; }
public string? Email { get; set; }
public string? FirstName { get; set; }
public string? MiddleInitial { get; set; }
public string? LastName { get; set; }
public bool IsApproved { get; set; }
public DateTime? LastActivityDate { get; set; }
public DateTime? LastLoginDate { get; set; }
public DateTime? LastPasswordChangedDate { get; set; }
public DateTime? CreationDate { get; set; }
public IEnumerable<IscinstanceModel> Iscinstance { get; set; }
public IEnumerable<UserProfileModel> UserProfile { get; set; }
}
public class IscinstanceModel
{
public int IscinstanceId { get; set; }
public string? Name { get; set; }
}
public class UserProfileModel
{
public string? ProfileName { get; set; }
public string? Address1 { get; set; }
public string? DirectConnectPhone { get; set; }
public string? ProfilEmail { get; set; }
public string? Profile { get; set; }
}
Then you can concert your entities to the api model. But two trouble.
First, the expected json has by user a list of iscinstance, but the entity user has a list of list of iscinstance. SelectMany help to flat to simple list.
Second, the expected json has by user a list of profile, but the entity has one profile. In this case, just encapsulate the profile in a collection.
Finaly :
var customers = await _context.Users
.Where(c => c.UserId == UserId && c.LastActivityDate > date && c.IsApproved == num)
.Include(c => c.Profile)
.Include(c => c.LinkUsersToIscinstances).ThenInclude(c => c.Iscinstances)
.OrderBy(c => c.LinkUsersToIscinstances.Iscinstances.Name).ThenBy(c => c.LastName).ThenBy(c => c.FirstName)
.Select(c => new UserModel
{
UserId = c.UserId,
Username = c.Username,
Email = c.Email,
FirstName = c.FirstName,
MiddleInitial = c.MiddleInitial,
LastName = c.LastName,
IsApproved = c.IsApproved,
LastActivityDate = c.LastActivityDate,
LastLoginDate = c.LastLoginDate,
LastPasswordChangedDate = c.LastPasswordChangedDate,
CreationDate = c.CreationDate,
Iscinstance = c.LinkUsersToIscinstances
.SelectMany(l => l.Iscinstances)
.Select(i =>
new IscinstanceModel {
IscinstanceId = l.IscinstanceId,
Name = l.name
}
),
UserProfile = new [] {
new UserProfileModel{
ProfileName = c.Profile.ProfileName,
Address1 = c.Profile.Address1,
DirectConnectPhone = c.Profile.DirectConnectPhone,
ProfilEmail = c.Profile.ProfilEmail
}
}
})
.ToListAsync();