Using .NET Core MVC response displays NULL value of one of property

Viewed 365

Using .Net Core 3.1 MVC pattern, I have been developing a back-end system. There are two tables, one is "TranslationInfo", another one is "TranslationContent". TranslationInfo has many TranslationContent, so I configured the Dbcontext like this.

TranslationInfo

    public class TranslationInfo
    {
        [Key]
        public int Index { get; set; }
        public DateTime InsertedDate { get; set; }
        public DateTime UpdatedDate { get; set; }
    }

TranslationContent

   public class TranslationContent
    {
        [Key]
        public int Code { get; set; }
        public string English { get; set; }
        public string French { get; set; }
        public string Status { get; set; }
        public string Message { get; set; }

        [ForeignKey("Index")]
        public TranslationInfo TranslationInfo { get; set; }
    }

Everything is alright except for getting a list of TranslationContent based on TranslationInfo.Index or not. The result displays the list of TranslationContent w/o TranslationInfo even though it enables to retrieve the result based on TranslationInfo.Index.

Result of 'https://localhost:44311/contentsList/3'

[
    {
        "code": 1,
        "english": "string",
        "french": "string",
        "status": "",
        "message": "",
        "translationInfo": null
    },
    {
        "code": 2,
        "english": "string",
        "french": "string",
        "status": "string",
        "message": "string",
        "translationInfo": null
    },
    {
        "code": 4,
        "english": "cvzxvc",
        "french": "asdfasdfas",
        "status": "Passed",
        "message": null,
        "translationInfo": null
    },
    {
        "code": 10,
        "english": "string",
        "french": "string",
        "status": "string",
        "message": "string",
        "translationInfo": null
    }
]

Here is Application area.

ITranslationService.cs

  public interface ITranslationServices
    {
        List<TranslationInfo> GetTranslationInfos();

        TranslationInfo GetTranslationInfo(int index);
        TranslationInfo CreateTranslationInfo(TranslationInfo translationInfo);

        TranslationInfo EditTranslationInfo(TranslationInfo translationInfo);
        List<TranslationContent> GetTranslationContents();
        List<TranslationContent> GetTranslationContentsByIndex(int index);

        TranslationContent GetTranslationContent(int code);
        TranslationContent CreateTranslationContent(TranslationContent translationContent);

        TranslationContent EditTranslationContent(TranslationContent translationContent);
    }

TranslationService.cs

using Excel.DB;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Excel.Core
{
    public class TranslationService : ITranslationServices
    {
        private readonly AppDbContext _context;

        public TranslationService(AppDbContext context)
        {
            _context = context;
        }



        /*     Translation Info Area */
        public List<TranslationInfo> GetTranslationInfos()
        {
            return _context.TranslationInfos.ToList();
        }
        public TranslationInfo GetTranslationInfo(int index)
        {
            return _context.TranslationInfos.First(t => t.Index == index);
        }

        public TranslationInfo CreateTranslationInfo(TranslationInfo translationInfo)
        {
            translationInfo.InsertedDate = DateTime.UtcNow;
            translationInfo.UpdatedDate = DateTime.UtcNow;

            _context.Add(translationInfo);
            _context.SaveChanges();
            return translationInfo;
        }

        public TranslationInfo EditTranslationInfo(TranslationInfo translationInfo)
        {
            var dbTranslationInfo = _context.TranslationInfos.First(t => t.Index == translationInfo.Index);
            // update process will be added.

            dbTranslationInfo.UpdatedDate = DateTime.UtcNow;
            _context.SaveChanges();
            return dbTranslationInfo;

        }


        /*     Translation Content Area */
        public List<TranslationContent> GetTranslationContents()
        {
            return _context.TranslationContents.ToList();
        }
        public List<TranslationContent> GetTranslationContentsByIndex(int index)
        {
            return _context.TranslationContents.Where(t => t.TranslationInfo.Index == index).ToList();
        }

        public TranslationContent GetTranslationContent(int code)
        {
            return (TranslationContent)_context.TranslationContents.First(t => t.Code == code);
        }

        public TranslationContent CreateTranslationContent(TranslationContent translationContent)
        {
            var dbTranslationInfo = _context.TranslationInfos.First(t => t.Index == translationContent.TranslationInfo.Index);

            if (dbTranslationInfo == null)
            {
                throw new Exception("Cannot find translation info");
            }

            translationContent.TranslationInfo = dbTranslationInfo;

            _context.Add(translationContent);
            _context.SaveChanges();
            return (TranslationContent)translationContent;
        }

        public TranslationContent EditTranslationContent(TranslationContent translationContent)
        {
            var dbTranslationContent = _context.TranslationContents.First(t => t.Code == translationContent.Code);
            // update process will be added.

            dbTranslationContent.English = translationContent.English;
            dbTranslationContent.French = translationContent.French;
            dbTranslationContent.Message = translationContent.Message;
            dbTranslationContent.Status = translationContent.Status;
            dbTranslationContent.TranslationInfo = translationContent.TranslationInfo;
            _context.SaveChanges();
            return dbTranslationContent;
        }
    }
}

Here is API(Controller) area TranslationController

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Excel.Core;
using Excel.DB;

namespace Excel.API.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class TranslationController : ControllerBase
    {
        private readonly ITranslationServices _translationServices;

        public TranslationController(ITranslationServices translationServices)
        {
            _translationServices = translationServices;
        }

        [HttpGet("/infos")]
        public IActionResult GetTranslationInfos()
        {
            return Ok(_translationServices.GetTranslationInfos());
        }

        [HttpGet("/info/{index}", Name = "GetTranslationInfo")]
        public IActionResult GetTranslationInfo(int index)
        {
            return Ok(_translationServices.GetTranslationInfo(index));
        }

        [HttpPost("/info")]
        public IActionResult CreateTranslationInfo(TranslationInfo translationInfo)
        {
            var newTranslationInfo = _translationServices.CreateTranslationInfo(translationInfo);
            return CreatedAtRoute("GetTranslationInfo", new { newTranslationInfo.Index }, newTranslationInfo);
        }

        [HttpPut("/info")]
        public IActionResult EditTranslationInfo(TranslationInfo translationInfo)
        {
            return Ok(_translationServices.EditTranslationInfo(translationInfo));
        }

        [HttpGet("/contents",Name = "GetTranslationContents")]
        public IActionResult GetTranslationContents()
        {
            return Ok(_translationServices.GetTranslationContents());
        }

        [HttpGet("/contentsList/{index}", Name = "GetTranslationContentsByIndex")]
        public IActionResult GetTranslationContentsByIndex(int index)
        {
            return Ok(_translationServices.GetTranslationContentsByIndex(index));
        }

        [HttpGet("/content/{code}", Name = "GetTranslationContent")]
        public IActionResult GetTranslationContent(int code)
        {
            return Ok(_translationServices.GetTranslationContent(code));
        }

        [HttpPost("/content")]
        public IActionResult CreateTranslationContent(TranslationContent translationContent)
        {
            var newTranslationContent = _translationServices.CreateTranslationContent(translationContent);
            return CreatedAtRoute("GetTranslationContent", new { newTranslationContent.Code }, newTranslationContent);
        }

        [HttpPut("/content")]
        public IActionResult EditTranslationContent(TranslationContent translationContent)
        {
            return Ok(_translationServices.EditTranslationContent(translationContent));
        }
    }
}

Can you let me know how I can get the TranslationInfo when getting the list of TranslationContent?

1 Answers

Oh, that seems to be an easy one:

You have to have the TranslationInfo included in your request. The TranslationContext is the table you are asking for, so EFCore, which you are using, is cutting all other tables out.

Change this:

 public List<TranslationContent> GetTranslationContentsByIndex(int index)
 {
            return _context.TranslationContents.Where(t => t.TranslationInfo.Index == index).ToList();
 }

to this:

 public List<TranslationContent> GetTranslationContentsByIndex(int index)
 {
            return _context.TranslationContents.Where(t => t.TranslationInfo.Index == index).Include(x => x.TranslationInfo).ToList();
 }

Or you could do it the other way around:

 public List<TranslationInfo> GetTranslationContentsByIndex(int index)
 {
            return _context.TranslationInfo.Where(t => t.Index == index).Include(x => x.TranslationContent).ToList();
 }
Related