Reputation: 543
I'm building REST API server in .NET core. I'm testing my code via Postman software. I have a problem with Include()
method that enables me to attach navigation property data. I'm trying to get data in [HttpGet] action and objects that are being returned are wrong.
My code : MODELS
Session model
public class Session
{
[Key]
public int IDSession { get; set; }
[Required]
public DateTime LogInTime { get; set; }
public DateTime LogOutTime { get; set; }
[Required]
public int IDUser { get; set; }
public User User { get; set; }
[Required]
public int IDMachine { get; set; }
public Machine Machine { get; set; }
}
User model
public class User
{
[Key]
public int IDUser { get; set; }
[Required]
public string Forename { get; set; }
[Required]
public string Name { get; set; }
public string AvatarPath { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Password { get; set; }
public User CreatedBy { get; set; }
public DateTime CreatedAt { get; set; }
public List<UserGroup> UsersGroups { get; set; }
public List<Alarm> ExecutedAlarms { get; set; }
public List<Alarm> ResetedAlarms { get; set; }
public List<AccessCard> Cards { get; set; }
public List<AccessCard> UserCardsAdded { get; set; }
public List<User> UsersAdded { get; set; }
public List<Session> Sessions { get; set; }
public List<EventsLog> Events { get; set; }
public List<Reference> References { get; set; }
public List<UserPermission> UsersPermissions { get; set; }
}
Session controller
[Produces("application/json")]
[Route("api/Sessions")]
public class SessionsController : Controller
{
private readonly DBContext _context;
#region CONSTRUCTOR
public SessionsController(DBContext context)
{
_context = context;
}
#endregion
#region HTTP GET
// GET: api/sessions
[HttpGet]
public async Task<IActionResult> GetSessions()
{
var sessions = await _context.Sessions.Include(s => s.User). ToListAsync();
if (sessions.Any())
{
return new ObjectResult(sessions);
}
else
{
return NotFound();
}
}
// GET: api/sessions/1
[HttpGet("{id}", Name = "GetSessionByID")]
public async Task<IActionResult> GetSessionByID(Int32 id)
{
var session = await _context.Sessions.Include(s => s.User).FirstOrDefaultAsync(s => s.IDSession == id);
if (session == null)
{
return NotFound();
}
else
{
return new ObjectResult(session);
}
}
#endregion
}
The idea is that User
model contains List<Session>
collection that he/she created. I want to be able to return users with its sessions
Of course Session
model contains a single User
because every session is related with a specific, single User.
Now, when I need to get all sessions objects in SessionController
with GetSessions()
or GetSessionsByID()
I use POSTMAN [HttpGet] action like this : http://localhost:8080/api/sessions
which returns me wrong data :
A session contains a user and in turn a single user is related with its sessions. It looks like it tries to return me Session
object properly, includes User
object but then it tries to include all sessions for that User. That's not what I want. It looks like some kind of a loop. Sessions shoud be returned with its User objects and that's it. How can I achieve that ? Am I doing some logical mistake in my models ?
Thanks !
Upvotes: 3
Views: 2463
Reputation: 625
I met also this issue recently. So, I've fixed it by adding this script in the Startup.cs file and ConfigureServices method :
services.AddMvc().AddJsonOptions(
options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
So, you suffix services.AddMvc() by this code who means that you have to make JSON.Net to ignore cycles finded to the nested object request. And of course having Newtonsoft.Json package installed to your project and referenced in each concerned file
For much clearer information, see this link at Related Data and Serialization section : https://learn.microsoft.com/en-us/ef/core/querying/related-data
Hope this is helpfull for you
Upvotes: 6