C
C#15mo ago
neSHa

❔ i cant return object in JSON correctly in asp.net core web app

i cant serialize object correctly, so im creating asp.net core web app, and i have model structured kie this: public class Card { [Key] public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public double Price { get; set; } public double Price2 { get; set; } public double Price3 { get; set; } public double Price4 { get; set; } public double MorePrices { get; set; } [ValidateNever] public string Image { get; set; } public int Amount { get; set; } [ValidateNever] public int? CardId { get; set; } [ForeignKey("CardId")] [ValidateNever] public Card Parent { get; set; } [ValidateNever] public int TypeId { get; set; } [ForeignKey("TypeId")] [ValidateNever] public Type Type { get; set; } [ValidateNever] public DateTime Created_at { get; set; } [ValidateNever] public DateTime Updated_at { get; set; } [ValidateNever] [NotMapped] public List<Card>? Appendices { get; set; } } and i have API that pull this this item from db, and populate appendices with items that have CardId equals to id of this exec item. Now api returns that object in JSON, and i got completly unreadable JSON format, i use JSON formatter on chrome but it wont format it as other objects without Appendices. i tried fetching it but it wont. What i am doing wrong?
48 Replies
Angius
Angius15mo ago
Describe "unreadable" Nothing here seems particularly hard to serialize
neSHa
neSHa15mo ago
readable:
neSHa
neSHa15mo ago
and this:
neSHa
neSHa15mo ago
unreadable
neSHa
neSHa15mo ago
also got this:
neSHa
neSHa15mo ago
under that same page as unreadable
Angius
Angius15mo ago
Ah, you have cyclic objects there, a card can reference a card, potentially even itself
neSHa
neSHa15mo ago
ahh
Angius
Angius15mo ago
Also, there's the issue of depth
neSHa
neSHa15mo ago
i got it, one can refference another and so on
Angius
Angius15mo ago
If you have a tree of 835 cards with their parents, that'll be an issue As it says, the maximum depth is 32 If it's an API result, I'd honestly just return the parent ID, not the whole card The frontend can then fetch that parent by its ID, if needed
neSHa
neSHa15mo ago
im creating 2 app one using react one clear backend here is api
Angius
Angius15mo ago
Well, yes
neSHa
neSHa15mo ago
[HttpGet] [AllowAnonymous] public async Task<IActionResult> Proizvodi(int? id) { if (id == null id == 0) { var mainItems = _unitOfWork.Card.GetAll(x => x.CardId == 0 x.CardId == null, tracked: false, included: "Type,Parent"); return Json(mainItems); } var item = await _unitOfWork.Card.FirstOrDefaultAsync(x => x.Id == id,included:"Type,Parent"); if(item == null) { return NotFound(); } if(item.Type.Name == "Proizvod") { item.Appendices = _unitOfWork.Card.GetAll(x => x.CardId == item.Id).ToList(); return Json( item ); } var items = _unitOfWork.Card.GetAll(x => x.CardId == id, included: "Type,Parent"); return Json(items); }
Angius
Angius15mo ago
That changes nothing in what I said $code
MODiX
MODiX15mo ago
To post C# code type the following: ```cs // code here ``` Get an example by typing $codegif in chat If your code is too long, post it to: https://paste.mod.gg/
Angius
Angius15mo ago
_unitOfWork 💀 I hope you're not using generic repositories
neSHa
neSHa15mo ago
kheem, yes
Angius
Angius15mo ago
Oof Ouch My bones
neSHa
neSHa15mo ago
Im just beginner :((
Angius
Angius15mo ago
DbContext is the unit of work and a generic repository
neSHa
neSHa15mo ago
here is unitOfWork and see it
Angius
Angius15mo ago
It's much easier to not have abstraction over abstraction over abstraction over abstraction And just use EF directly
neSHa
neSHa15mo ago
using DataAccess.Context; using DataAccess.Repository.IRepository; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DataAccess.Repository { public class UnitOfWork : IUnitOFWork { private readonly ApplicationDbDontext _db; public ICardRepsitory Card { get; private set; } public ITypeRepository Type { get; private set; } public IApplicationUserRepository ApplicationUser { get; private set; } public UnitOfWork(ApplicationDbDontext db) { _db = db; Card = new CardRepository(_db); Type = new TypeRepository(_db); ApplicationUser = new ApplicationUserRepository(_db); } public async Task SaveAsync() { await _db.SaveChangesAsync(); } } } direcly
Angius
Angius15mo ago
Yeah those are just passthrough methods
neSHa
neSHa15mo ago
yes
Angius
Angius15mo ago
So they make no sense There's no point You basically recreated a DbContext with DbSets in it
neSHa
neSHa15mo ago
yea and just past through, so it always one DbContext, but because of DI if i do that manually in every controller i request one DbContext it will give me same think
Angius
Angius15mo ago
With some magic strings and direct .Include()s from the look of it, to boot
neSHa
neSHa15mo ago
oke idk why i complicate that stuff yes
Angius
Angius15mo ago
Yeah I don't know either lol
neSHa
neSHa15mo ago
but why people use it then? maybe when doing crud, just cutting code, but that can done manually in controller no?
Angius
Angius15mo ago
Mostly because they were born in the 60s, learned that pattern from a 90-year-old COBOL programmer when they were 23, and haven't learned anything new since the 80s And nowadays, just cargo cult Someone said "generic repo good" and people started mimicking it like seagulls from Finding Nemo
neSHa
neSHa15mo ago
ahhaahahaha Ahh make sense but probably generic repo is good for larger app i mean it can cut lot of code and write it once
Angius
Angius15mo ago
It cuts zero code Use non-generic repositories if you must But a generic repo is just a passthrough
var items = _unitOfWork.Card.GetAll(x => x.CardId == id, included: "Type,Parent");
var items = _unitOfWork.Card.GetAll(x => x.CardId == id, included: "Type,Parent");
should be
var items = await _cardRepo.GetAllWithTypesAndParentsById(id);
var items = await _cardRepo.GetAllWithTypesAndParentsById(id);
for example Or some different name for this method
var items = _unitOfWork.Card.GetAll(x => x.CardId == id, included: "Type,Parent");
var items = _unitOfWork.Card.GetAll(x => x.CardId == id, included: "Type,Parent");
is just recreating
var items = _context.Cards.Where(c => c.Id == id)
.Include(c => c.Type)
.Include(c => c.Parent)
.ToList();
var items = _context.Cards.Where(c => c.Id == id)
.Include(c => c.Type)
.Include(c => c.Parent)
.ToList();
but is more prone to errors
neSHa
neSHa15mo ago
and if i need more complex query just to overload method in generic repo?
Angius
Angius15mo ago
There should be no generic repo There should be a CardsRepository
neSHa
neSHa15mo ago
it just make more complex when i start thinking
Angius
Angius15mo ago
And it should have a method like
public async Task<List<Card>> GetAllCardsByIdWithParentAndType(int id)
{
return await _context.Cards.Where(c => c.Id == id)
.Include(c => c.Type)
.Include(c => c.Parent)
.ToListAsync();
}
public async Task<List<Card>> GetAllCardsByIdWithParentAndType(int id)
{
return await _context.Cards.Where(c => c.Id == id)
.Include(c => c.Type)
.Include(c => c.Parent)
.ToListAsync();
}
neSHa
neSHa15mo ago
i get it, thanks. I will transform this app now
Angius
Angius15mo ago
(while you're at it, make that stuff asynchronous) (and prefer .Select()ing into DTO classes over .Include()s)
neSHa
neSHa15mo ago
I will do it now. Thanks a lot some error when closing, it wont close 😦
Angius
Angius15mo ago
$close
MODiX
MODiX15mo ago
Use the /close command to mark a forum thread as answered
Angius
Angius15mo ago
Or you can just keep it open should you have other questions
neSHa
neSHa15mo ago
Angius
Angius15mo ago
huh
Accord
Accord15mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.