The new ASP.NET Core 3.0 Json serializer is leaving out data - asp.net-core

I'm porting a web application to ASP.NET Core 3, and after a bit of a battle, I'm almost at the finish line. Everything seems to work, but all of a sudden my JSON data returned from the api is missing some levels.
It seems the options.JsonSerializerOptions.MaxDepth is default at 64 levels, so it can be that. Some other places where an option can be playing tricks on me?
This is the code (and a quickview of the value):
And this is the JSON I get in the browser:
So the ParticipantGroups property/collection is completely missing in the generated output.
Any ideas where this happens?
EDIT:
I've added a repo on Github that showcases the issue. Standard ASP.NET Core 3.0 solution, created from the template, with a change to the result returned from the Weatherforecast controller:
https://github.com/steentottrup/systemtextjsonissue

For now I've gone back to using Newtonsoft.Json, with the Microsoft.AspNetCore.Mvc.NewtonsoftJson package. Then when I have some time, I'll try finding out what the solution is, without Newtonsoft.Json.

The problem seems to be an error in the new version 3.0. At least it seems like an error to me.
It seems System.Text.Json will convert the class mentioned in the hierarchy, not the actual class. So if you are using an abstract class in the hierarchy, you're in trouble. The second I removed the base class, and used the actual class I'm returning, the problem goes away it seems.
So this doesn't work:
public class SurveyReportResult {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
public IEnumerable<OrganisationalUnit> OrganisationalUnits { get; set; }
}
public abstract class OrganisationalUnit {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
}
public class OrganisationalUnitWithParticipantGroups : OrganisationalUnit {
public IEnumerable<ParticipantGroup> ParticipantGroups { get; set; }
}
public class ParticipantGroup {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
}
This will only return the properties of the OrganisationalUnit class, not the additional property of the OrganisationalUnitWithParticipantGroups.
This works:
public class SurveyReportResult {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
public IEnumerable<OrganisationalUnitWithParticipantGroups> OrganisationalUnits { get; set; }
}
public class OrganisationalUnitWithParticipantGroups /*: OrganisationalUnit*/ {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
public IEnumerable<ParticipantGroup> ParticipantGroups { get; set; }
}
public class ParticipantGroup {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
}

Related

Podio API - Groupings are missing from Views in C#

I am working with the Podio api in C# and "Groupings" is missing from the View and ViewCreateUpdateRequest model.
When I use the sandbox call the result includes the groupings. So I'm thinking it is missing in the C# nuget package. Is there another way to access groupings for both Get View and Update View?
Sadly they are not maintaining the SDK for C#, but you can download their code from https://github.com/podio/podio-dotnet and update the code yourself.
That's what I did, I change the following
ItemId data type from Integer to Long
Added Groupings in View (Below is my View looks like)
public class View
{
[JsonProperty("view_id")]
public string ViewId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("created_on")]
public DateTime CreatedOn { get; set; }
[JsonProperty("sort_by")]
public string SortBy { get; set; }
[JsonProperty("sort_desc")]
public string SortDesc { get; set; }
[JsonProperty("filters")]
public JArray Filters { get; set; }
[JsonProperty("fields")]
public JObject Fields { get; set; }
[JsonProperty("groupings")]
public JObject Groupings { get; set; }
[JsonProperty("created_by")]
public ByLine CreatedBy { get; set; }
[JsonProperty("layout")]
public string Layout { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("rights")]
public string[] Rights { get; set; }
[JsonProperty("filter_id")]
public string FilterId { get; set; }
[JsonProperty("items")]
public int Items { get; set; }
}
Search for NuGet Package: Podio.Async by acl2

Doubts about EF Core 2.1 Relations

I am working on Entity Framework Core Code First approach and ASP.Net Core 2.1 making 3 tables:
Person class
public class Person
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public PeopleProfessions PeopleProfessions { get; set; }
}
Professions' class
public class Profession
{
public string Id { get; set; }
public string Name{ get; set; }
public PeopleProfessions PeopleProfessions { get; set; }
}
peopleprofessions' class
public class peopleprofessions
{
[ForeignKey("PersonId ")]
public string PersonId { get; set; }
public ICollection<Person> People { get; set; }
[ForeignKey("ProfessionId")]
public string ProfessionId{ get; set; }
public ICollection<Profession> Professions { get; set; }
}
On my Context:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<peopleprofessions>().HasKey(up => new { up.PersonId, up.ProfessionId });
}
Bearing this in mind:
People can have multiple professions.
The professions table is only for reading stored data like "Accountant".
I have doubts about how I can make table 3 only contain the foreigners and that it can meet the needs that I just mentioned.
I have tried to make the relationship appropriately but I also noticed that in tables 1 and 2 it requests both Id of the table people's professions.
I don't know if I am lost or if I am looking wrong or if there is an alternative to that situation. Thanks for any help you can give me.
You have the use of Collections on the navigation items a bit backwards. For your primary entities (Person and Profession), they should have collections, since it's one-to-many. But for the PeopleProfessions, each record is a single link to a specific entity, so no collection there just a direct object reference.
public class Person
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<PeopleProfessions> PeopleProfessions { get; set; }
}
public class Profession
{
public string Id { get; set; }
public string Name{ get; set; }
public ICollection<PeopleProfessions> PeopleProfessions { get; set; }
}
public class PeopleProfessions
{
public string PersonId { get; set; }
public Person Person { get; set; }
public string ProfessionId { get; set; }
public Profession Profession { get; set; }
}
You can, but don't need to specify a ForeignKey attribute because you are following EFs naming conventions(it will figure it out for you). Your OnModelCreating looks correct for the composite key.
You may want to consider removing the plural from PeopleProfessions (just call the class PeopleProfession) since one instance represents a single People-Profession relationship. I typically do this and but the navigation name in the entities remains plural, since it can represent more than one, i.e.
public ICollection<PeopleProfession> PeopleProfessions { get; set; }

Automapper and EF Navigation Properties

With ASP.NET MVC Core and Entity Framework Core I'm trying to create a simple website.
I've defined my Model:
public class Club
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual IEnumerable<Team> Teams { get; set; }
}
public class Team
{
[Key]
public int Id { get; set; }
public int ClubId { get; set; }
[MaxLength(32)]
public string Name { get; set; }
public virtual Club Club { get; set; }
}
As well as the corresponding View Models:
public class ClubViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public virtual IEnumerable<TeamViewModel> Teams { get; set; }
}
public class TeamViewModel
{
public int Id { get; set; }
public int ClubId { get; set; }
public string Name { get; set; }
public virtual ClubViewModel Club { get; set; }
}
I've defined an Automapper Profile with the corresponding mappers:
CreateMap<Club, ClubViewModel>();
CreateMap<ClubViewModel, Club>();
CreateMap<Team, TeamViewModel>();
CreateMap<TeamViewModel, Team>();
I try to load a Club entity, with the navigation property Teams included (_context.Club.Include(c => c.Teams).ToList()). This works as expected, it returns a Club with a list of Teams. But when I try to map this instance to a ClubViewModel, I get an 502.3 error and my debug session is ended immediately.
It seems like I am missing something trivial, but I simply do not see it. There's no information in the Windows Event Log and I can't find any usefull information in the IIS Express logging (%userprofile%\documents\IISExpress)
What is causing the crash?
You can't perform this mapping because it is circular. You'll have to remove this line
public virtual ClubViewModel Club { get; set; }
from your TeamViewModel and the mapping should work as expected.

Saving Data using Entity Framework Code First

I am using ASP.NET MVC Razor Entity Framework Code First C#
Class - A
public class Om_Category
{
[Key]
public int CategoryID { get; set; }
public String CategoryName { get; set; }
public String CategorySanitized { get; set; }
public Boolean IsActive { get; set; }
public DateTime CreationDate { get; set; }
}
Class - B
public class Om_CategorySkills
{
[Key]
public Int32 SkillID { get; set; }
public String Skill { get; set; }
public String SkillSanitized { get; set; }
public DateTime CreationDate { get; set; }
public Boolean IsActive { get; set; }
public Om_Category Category { get; set; }
}
When I try to create the record for table Om_CategorySkills. It says
cannot save the duplicate value in Om_Category table.
This is happening because I am sending the Om_Category class object in Om_CategorySkills class object because there are some fields in Om_Category class that are mandatory.
So I am passing the Om_Category class object also in Om_CategorySkills class object. Is there any way to fix this issue ?
Your navigation properties doesn't seem to be right.. Can you try (I didn't test),
public class Om_Category
{
[Key]
public int CategoryID { get; set; }
public String CategoryName { get; set; }
public String CategorySanitized { get; set; }
public Boolean IsActive { get; set; }
public DateTime CreationDate { get; set; }
public virtual Om_CategorySkills CategorySkills{ get; set; }
}
public class Om_CategorySkills
{
[Key]
public Int32 SkillID { get; set; }
public String Skill { get; set; }
public String SkillSanitized { get; set; }
public DateTime CreationDate { get; set; }
public Boolean IsActive { get; set; }
public int CategoryID {get;set;}
public virtual Om_Category Category { get; set; }
}
I see that your Om_CategorySkills object is lacking an Int32 Om_CategoryId property to be used as foreign key. I would also add a virtual modifier to the navigation property Category, in order to allow for lazy loading.
I think that it may be the case that the category object in your new/edited skill is already in the database, but was not the one retrieved by the context, so the context believes you are trying to save a new category with the Id of an existing one.
You should not try to save a skill object with a category object with no changes. Otherwise, the category object should be the one attached to the context.

Using Complex DataType in EF CodeFirst

this is my Model :
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public string Institute { get; set; }
public string Instructor { get; set; }
public string Duration { get; set; }
public Level Level { get; set; }
public Format Format { get; set; }
public DateTime Released { get; set; }
public string FileSize { get; set; }
public string Desciption { get; set; }
}
public enum Level
{
Beginner,
Intermediate,
Advanced
}
public enum Format
{
Avi,
Hd,
FullHd
}
public class CourseDb:DbContext
{
public DbSet<Course> Courses { get; set; }
}
when I want to Create my new Controller with Scoffolding Using EF Template,
It's not create both Level and Format fields while I am using EF5
what's my problem?
Thanks in your advise
Enum types are currently not supported when scaffolding, which is most likely why the fields are not created.
My advice would be to use a helper method such as : Working with enums in ASP.NET MVC 3
and code it manually.
Update:
Looks like there is ticket logged for the support it here: http://mvcscaffolding.codeplex.com/workitem/10