Problem retrieving child table ASPNET Core API

asp.net-core c# entity-framework-core

Question

I've created an API with ASPNET Core 2 that has a BlogPost service. The service handles creating blog posts and tags. The "Tags" are linked to the BlogPosts (as their children, by blogpostid), but i can't find a way to display those tags when i'm retrieving blogposts.

This is what i'm getting at the moment.

{
    "id": 3,
    "title": "Im Just Testing",
    "body": "Esta Bien senor",
    "type": "News",
    "dateCreated": "9/20/2018 12:00:00 AM",
    "author": "Dante",
    "tags": []
}

This is my controller ->

[HttpGet("posts/{id}")]
public IActionResult GetBlogPostById(int id, bool includePostTags = true)
{
    var blogPost = _blogPostService.GetBlogPostById(id, includePostTags);

    if(blogPost == null)
    {
        return NotFound();
    }

    var blogPostDto = _mapper.Map<BlogPostDto>(blogPost);
    return Ok(blogPostDto);
}

This is my BlogPostDTO

public class BlogPostDto
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
    public string Type { get; set; }
    public string DateCreated { get; set; }
    public string Author { get; set; }

    public ICollection<BlogPostTagDto> Tags { get; set; }
        = new List<BlogPostTagDto>();
}

And finally this is my BlogPostTag Entity ->

public class BlogPostTag
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    [MaxLength(50)]
    public string TagName { get; set; }

    [MaxLength(200)]
    public string Description { get; set; }

    [ForeignKey("BlogPostId")]
    public BlogPost BlogPost { get; set; }
    public int BlogPostId { get; set; }
}

And my BlogPostTagDto

public class BlogPostTagDto
{
    public int Id { get; set; }
    [Required(ErrorMessage = "You should provide a Tag Name value.")]
    [MaxLength(50)]
    public string TagName { get; set; }

    [MaxLength(200)]
    public string Description { get; set; }
}

TLDR: The BlogPostTags are created (i checked the DB), but i can't retrieve them in the "Get All Posts" call.

BlogPostService ->

public BlogPost GetBlogPostById(int id, bool includePostTags)
{
    if(includePostTags)
    {
        return _context.BlogPosts.Include(c => c.BlogPostTags).Where(c => c.Id == id).FirstOrDefault();
    }
    return _context.BlogPosts.Where(c => c.Id == id).FirstOrDefault();
}

And DataContext (perhaps it helps) ->

public class DataContext : DbContext
{
    public DataContext(DbContextOptions<DataContext> options) : base(options)
    {
        Database.Migrate();
    }

    public DbSet<User> Users { get; set; }
    public DbSet<BlogPost> BlogPosts { get; set; }
    public DbSet<BlogPostTag> BlogPostTags { get; set; }
}

BloGPost ENTITY

public class BlogPost
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    [MaxLength(100)]
    public string Title { get; set; }

    [Required]
    [MaxLength(500)]
    public string Body { get; set; }
    public string Type { get; set; }
    public string DateCreated { get; set; }
    public string Author { get; set; }

    public ICollection<BlogPostTag> BlogPostTags { get; set; }
        = new List<BlogPostTag>();
}

Added Mapper profile ->

    public AutoMapperProfile()
    {
        CreateMap<User, UserDto>();
        CreateMap<UserDto, User>();
        CreateMap<BlogPost, BlogPostDto>();
        CreateMap<BlogPostDto, BlogPost>();
        CreateMap<BlogPostTag, BlogPostTagForCreationDto>();
        CreateMap<BlogPostTagForCreationDto, BlogPostTag>();
       // CreateMap<BlogPostTagForCreationDto, BlogPostTag>();
    }

SOLVED:

Apparently in my BlogPostDto i had to retrieve "BlogPostTagForCreationDto" instead of the normal Dto.

    public ICollection<BlogPostTagForCreationDto> BlogPostTags { get; set; }
        = new List<BlogPostTagForCreationDto>();

This PLUS changing the name from "Tags" to "BlogPostTags" seems to have fixed my issue. I've got to research more on why this happened.

1
1
9/20/2018 12:44:24 PM

Accepted Answer

After confirming in the comments that the problem is in the difference between the names BlogPostTags and Tags, it's evident that AutoMapper needs to be instructed to map from BlogPostTags to Tags when mapping from a BlogPost to a BlogPostDto. This can be configured inside of your AutoMapperProfile, like this:

public AutoMapperProfile()
{
    // ...

    CreateMap<BlogPost, BlogPostDto>()
        .ForMember(x => x.Tags, opt => opt.MapFrom(x => x.BlogPostTags));
}

All we're doing here is creating an explicit map from BlogPost to BlogPostDto, which allows us to take control of specific properties as they get mapped. In this case, we're simply stating that we want to MapFrom BlogPostTags to Tags, accordingly.

1
9/21/2018 9:13:13 AM

Popular Answer

It looks to me that you are missing a mapping:

CreateMap<BlogPostTag, BlogPostTagDto>();


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow