I have book class that includes authors and also my author class includes books. So when I try to convert book to json string, it gives the referance loop error. So I do that
public IHttpActionResult GetAllForOfficer()
{
Library library = _libraryManager.GetById(ProviderAuthorization.libraryId);
List<Book> books = _bookManager.GetAll().Where(x=>x.Libraries.Contains(library)).ToList();
return Ok(JsonConvert.SerializeObject(books, Formatting.Indented,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}));
}
And this returns output like that
"[\r\n {\r\n \"Authors\": [\r\n {\r\n \"Books\": [],\r\n \"Id\": 4,\r\n \"Name\": \"Texe Marrs\"\r\n }\r\n ],\r\n \"Categories\": [],\r\n \"Comments\": [],\r\n \"Libraries\": [\r\n {\r\n \"Books\": [\r\n {\r\n \"Authors\": [\r\n {\r\n \"Books\": [\r\n {\r\n \"Authors\": [],\r\n \"Categories\": [\r\n {\r\n \"Books\": [],\r\n \"Id\": 5,\r\n \"Name\": \"dede\",\r\n \"ClickCounter\": 0\r\n },\r\n {\r\n \"Books\": [],\r\n \"Id\": 6,\r\n \"Name\": \"asas\",\r\n \"ClickCounter\": 0\r\n }\r\n ],\r\n \"Comments\": [\r\n {\r\n \"User\": {\r\n \"Comments\": [],\r\n
I have book class like this
public int Id { get; set; }
[Required]
[StringLength(10)]
public string ISBN10 { get; set; }
[Required]
[StringLength(13)]
public string ISBN13 { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Publisher { get; set; }
public int? NumberOfPages { get; set; }
public int? Revision { get; set; }
public int? LatestRevision { get; set; }
[StringLength(50)]
public string Language { get; set; }
[Column(TypeName = "date")]
public DateTime? CreateDate { get; set; }
public string Description { get; set; }
[Column(TypeName = "image")]
public byte[] Image { get; set; }
public int ClickCounter { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Comment> Comments { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<UserBook> UserBooks { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Author> Authors { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Category> Categories { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Library> Libraries { get; set; }
My output looks a little bit weird. It should be like "Authors":["Name":"Pete Mark"]. But there are some backslashes. I think I have a problem with converting class to json. How can I fix that ?
Thanks everybody who says I dont actually need any conversion. I solved that problem using data transfer object. I created same classes. And convert it to dto by not equalizing child class's relationship objects (which is typed ICollection).
Here is my book entity.
public int Id { get; set; }
[Required]
[StringLength(10)]
public string ISBN10 { get; set; }
[Required]
[StringLength(13)]
public string ISBN13 { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Publisher { get; set; }
public int? NumberOfPages { get; set; }
public int? Revision { get; set; }
public int? LatestRevision { get; set; }
[StringLength(50)]
public string Language { get; set; }
[Column(TypeName = "date")]
public DateTime? CreateDate { get; set; }
public string Description { get; set; }
[Column(TypeName = "image")]
public byte[] Image { get; set; }
public int ClickCounter { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Comment> Comments { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<UserBook> UserBooks { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Author> Authors { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Category> Categories { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Library> Libraries { get; set; }
And here is BookDto class.
public int Id { get; set; }
public string ISBN10 { get; set; }
public string ISBN13 { get; set; }
public string Name { get; set; }
public string Publisher { get; set; }
public int? NumberOfPages { get; set; }
public int? Revision { get; set; }
public int? LatestRevision { get; set; }
public string Language { get; set; }
public DateTime? CreateDate { get; set; }
public string Description { get; set; }
public byte[] Image { get; set; }
public int ClickCounter { get; set; }
public List<CommentDto> Comments { get; set; }
public List<UserBookDto> UserBooks { get; set; }
public List<AuthorDto> Authors { get; set; }
public List<CategoryDto> Categories { get; set; }
public List<LibraryDto> Libraries { get; set; }
And I have my action here.
public IHttpActionResult GetAllForOfficer()
{
Library library = _libraryManager.GetById(ProviderAuthorization.libraryId);
List<BookDto> booksDto = _bookManager.GetAll().Where(x => x.Libraries.Contains(library)).ToList().ConvertAll<BookDto>(x => new BookDto()
{
Id = x.Id,
Name = x.Name,
ISBN10 = x.ISBN10,
ISBN13 = x.ISBN13,
Authors = x.Authors.ToList().ConvertAll<AuthorDto>(y => new AuthorDto() { Id = y.Id, Name = y.Name }),
Categories = x.Categories.ToList().ConvertAll<CategoryDto>(y => new CategoryDto() { Id = y.Id, Name = y.Name, ClickCounter = y.ClickCounter }),
Comments = x.Comments.ToList().ConvertAll<CommentDto>(y => new CommentDto() { Id = y.Id, BookId = y.BookId, CommentString = y.Comment1, Date = y.Date, Status = y.Status, UserId = y.UserId }),
Libraries = x.Libraries.ToList().ConvertAll<LibraryDto>(y => new LibraryDto() { Id = y.Id, Address = y.Address, Location = y.Location, Name = y.Name, Status = y.Status }),
UserBooks = x.UserBooks.ToList().ConvertAll<UserBookDto>(y => new UserBookDto() { Id = y.Id, Status = y.Status, BookId = y.BookId, BorrowDate = y.BorrowDate, LibraryId = y.LibraryId, UserId = y.UserId, ReturnDate = y.ReturnDate }),
ClickCounter = x.ClickCounter,
CreateDate = x.CreateDate,
Description = x.Description,
Image = x.Image,
Language = x.Language,
LatestRevision = x.LatestRevision,
NumberOfPages = x.NumberOfPages,
Publisher = x.Publisher,
Revision = x.Revision,
});
return Ok(booksDto);
}
Now I have Postman output is like that.
{
"Id": 1,
"ISBN10": "123123",
"ISBN13": "213123",
"Name": "asdasd",
"Publisher": "asdasd",
"NumberOfPages": 2,
"Revision": 2,
"LatestRevision": 2,
"Language": "asd",
"CreateDate": "1010-10-10T00:00:00",
"Description": "asdasd",
"Image": null,
"ClickCounter": 0,
"Comments": [
{
"Id": 3,
"UserId": 1,
"BookId": 1,
"CommentString": "TestComment",
"Date": "2020-10-10T00:00:00",
"Status": 1,
"Book": null,
"User": null
}
],
"UserBooks": [
{
"Id": 2,
"UserId": 1,
"BookId": 1,
"LibraryId": 1,
"BorrowDate": "1010-10-10T00:00:00",
"ReturnDate": null,
"Status": 1,
"Book": null,
"Library": null,
"User": null
}
],
"Authors": [
{
"Id": 1,
"Name": "TestAuthor1",
"Books": null
},
{
"Id": 2,
"Name": "TestAuthor2",
"Books": null
}
],
"Categories": [
{
"Id": 5,
"Name": "TestCategory0",
"ClickCounter": 0,
"Books": null
},
{
"Id": 6,
"Name": "TestCategory1",
"ClickCounter": 0,
"Books": null
}
],
"Libraries": [
{
"Id": 1,
"Name": "asdasd",
"Address": "asdasd",
"Location": "asdasd",
"Status": 1,
"Officers": null,
"UserBooks": null,
"Books": null,
"Users": null
},
{
"Id": 2,
"Name": "asdasd",
"Address": "asdasd",
"Location": "asdasd",
"Status": 2,
"Officers": null,
"UserBooks": null,
"Books": null,
"Users": null
}
]
}
Also the problem could be resolved without using dto classes. Like that
public IHttpActionResult GetAllForOfficer()
{
Library library = _libraryManager.GetById(ProviderAuthorization.libraryId);
List<BookDto> booksDto = _bookManager.GetAll().Where(x => x.Libraries.Contains(library)).ToList().ConvertAll<BookDto>(x => new Book()
{
Id = x.Id,
Name = x.Name,
ISBN10 = x.ISBN10,
ISBN13 = x.ISBN13,
Authors = x.Authors.ToList().ConvertAll<Author>(y => new Author() { Id = y.Id, Name = y.Name }),
Categories = x.Categories.ToList().ConvertAll<Category>(y => new Category() { Id = y.Id, Name = y.Name, ClickCounter = y.ClickCounter }),
Comments = x.Comments.ToList().ConvertAll<Comment>(y => new Comment() { Id = y.Id, BookId = y.BookId, Comment1 = y.Comment1, Date = y.Date, Status = y.Status, UserId = y.UserId }),
Libraries = x.Libraries.ToList().ConvertAll<Library>(y => new Library() { Id = y.Id, Address = y.Address, Location = y.Location, Name = y.Name, Status = y.Status }),
UserBooks = x.UserBooks.ToList().ConvertAll<UserBook>(y => new UserBook() { Id = y.Id, Status = y.Status, BookId = y.BookId, BorrowDate = y.BorrowDate, LibraryId = y.LibraryId, UserId = y.UserId, ReturnDate = y.ReturnDate }),
ClickCounter = x.ClickCounter,
CreateDate = x.CreateDate,
Description = x.Description,
Image = x.Image,
Language = x.Language,
LatestRevision = x.LatestRevision,
NumberOfPages = x.NumberOfPages,
Publisher = x.Publisher,
Revision = x.Revision,
});
return Ok(booksDto);
}
But there is a problem while converting ICollection objects. I convert ICollection to list to use ConvertAll method. But in the end I have to change it to ICollection. So this last code sample is not working. Maybe there is a way but I didnt search about it.