How to deserialize Graphql Response - serialization

Hi I have a graphql Response after Mutating
{{
"carCreate": {
"car": {
"id": "TestId"
}
}
}}
I want to Desealize it I am using The following Code
var graphQlClient = new GraphQLHttpClient(AppConfig.GraphQlUrl, new NewtonsoftJsonSerializer());
I have tried to resolve with the following code
var response = await graphQlClient.SendMutationAsync<CarCreate>(request);
My Created Model is :
public class Car
{
public string Id { get; set; }
}
public class CarCreate
{
public Car Car { get; set; }
}

Your class should be something like this,
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
public class Car
{
public string id { get; set; }
}
public class CarCreate
{
public Car car { get; set; }
}
public class Root
{
public CarCreate carCreate { get; set; }
}

Related

Getting navigation properties of your entity when you return a CreatedAtRouteResult

Request:
namespace mediere_API.Requests
{
public class LocalitateRequest
{
public string Nume { get; set; }
public int JudetId { get; set; }
}
}
DTO
namespace mediere_API.Dtos
{
public class LocalitateDTO
{
public int Id { get; set; }
public string Nume { get; set; }
public JudetDTO Judet { get; set; }
}
}
Entity
using mediere_API.Dtos;
using System.ComponentModel.DataAnnotations;
namespace mediere_API.DataLayer.Entities
{
public class Localitate : BaseEntity
{
[Required]
public string Nume { get; set; }
[Required]
public int JudetId { get; set; }
public virtual Judet judet { get; set; }
public Localitate() { }
}
}
Processor method
async Task<ActionResult> ILocalitatiProcessor.AddLocalitate(LocalitateRequest localitateRequest)
{
var record = _mapper.Map<Localitate>(localitateRequest);
_unitOfWork.Localitati.Insert(record);
if (await _unitOfWork.SaveChangesAsync() == false)
{
return new BadRequestResult();
}
return new CreatedAtRouteResult("GetByIdLocalitate", new {Id = record.Id}, _mapper.Map<LocalitateDTO>(record));
}
So, I have these pieces of code.
The way I'm using my front-end, I need to have the navigation properties filled in when I get the response on the POST request.
Right now I get:
{
"id": 12777,
"nume": "test",
"judet": null
}
On the get requests it works properly, but with CreatedAtRouteResult it doesn't, and I know why, but I don't know how should I fix it.
Record doesn't have the navigation properties filled in because it is a mapping of localitateRequest (which doesn't have the navigation properties) to Localitate.
So, how should I approach this problem?
Thanks.

How to Map DTO class to "Model" class In generic Repository

I use DTO class in API layer and I struggle to map DTO class to "model" class in generic Repository.cs in core layer.
Repository.cs :
namespace DTOMap.Core.Repository.Generic
{
public class Repository<T> : IRepository<T> where T : class
{
private DTOMapContext _context;
private DbSet<T> _table;
private IMapper _mapper;
public Repository(DTOMapContext context)
{
_context = context;
_table = _context.Set<T>();
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<MyMapper>();
});
_mapper = config.CreateMapper();
}
public T Add(T obj)
{
// Here how to use My Mapper to save a book or an author generically
// Sth like :
// temp = _table.Add(_mapper.Map<T>(obj)); Here I want to map Dto to model to save in the db
// return = (_mapper.Map<T>(temp)); Here I want to map Model to DTO to collect it in API
// but I can't have a reference to TDTO
throw new NotImplementedException();
}
}
}
I show you the other classes that I find useful (I only implement Add function for this example and I am a beginner in .Net) :
Author.cs
namespace DTOMap.Core.Models
{
[Table("Author")]
internal class Author
{
[Key]
public int id { get; set; }
[Required, MaxLength(255)]
public string firstName { get; set; }
[Required,MaxLength(255)]
public string lastName { get; set; }
}
}
Book.cs
namespace DTOMap.Core.Models
{
[Table("Book")]
internal class Book
{
[Key]
public int id { get; set; }
[Required,MaxLength(255)]
public string name { get; set; }
[Required]
public int authorId { get; set; }
[Required]
public Author author { get; set; }
}
}
AuthorDTO.cs
namespace DTOMap.Domain.DTO
{
public class AuthorDTO
{
public int id { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
}
}
BookDTO.cs
namespace DTOMap.Domain.DTO
{
public class BookDTO
{
public int id { get; set; }
public string name { get; set; }
public int authorId { get; set; }
public AuthorDTO author { get; set; }
}
}
IRepository.cs
namespace DTOMap.Domain.Interface
{
public interface IRepository<T>
{
T Add(T obj);
}
}
MyMapper.cs
namespace DTOMap.Core
{
public class MyMapper : Profile
{
public MyMapper()
{
CreateMap<Book, BookDTO>();
CreateMap<BookDTO, Book>();
CreateMap<Author, AuthorDTO>();
CreateMap<AuthorDTO, Author>();
}
}
}
program.cs
... Some Fcts
builder.Services.AddTransient<IRepository<BookDTO>, BookRepository>();
builder.Services.AddTransient<IRepository<AuthorDTO>, AuthorRepository>();
... Some Fcts
If you need any other information, please ask me.

How to update an existing entity that has a nested list of entities?

I'm trying to update an entity using entity framework but, everytime I try to do it, it raises an error saying that a nested entity the main class contains cannot be tracked.
These are my classes:
public abstract class BaseEntity
{
public int Id { get; set; }
}
public class Dashboard : BaseEntity
{
public int Order { get; set; }
public string Title { get; set; }
public bool Enabled { get; set; }
public virtual ICollection<Submenu> Submenu { get; set; }
}
public class Submenu : BaseEntity
{
public int Order { get; set; }
public bool Enabled { get; set; }
public string Title { get; set; }
public string Image { get; set; }
public string Descriptions { get; set; }
public virtual ICollection<Action> Actions { get; set; }
public int DashboardId { get; set; }
public virtual Dashboard Dashboard { get; set; }
}
public class Action : BaseEntity
{
public string Type { get; set; }
public string Label { get; set; }
public string Url { get; set; }
public string Extension { get; set; }
public virtual Submenu Submenu { get; set; }
public int SubmenuId { get; set; }
}
The one I am using to update is Dashboard, which contains the rest of the classes.
I'm trying to do it using a generic service layer and a generic repository that are defined this way:
public class GenericService<T> : IGenericService<T> where T : BaseEntity
{
private readonly IBaseRepository<T> baseRepository;
public GenericService(IBaseRepository<T> baseRepository)
{
this.baseRepository = baseRepository;
}
public async Task Update(T entity, T attachedEntity)
{
await baseRepository.Update(entity, attachedEntity);
}
}
public class BaseRepository<T> : IBaseRepository<T> where T : BaseEntity
{
private readonly PortalContext dataContext;
private DbSet<T> DbSet { get; set; }
public BaseRepository(PortalContext context)
{
dataContext = context;
DbSet = dataContext.Set<T>();
}
public async Task Update(T entity, T attachedEntity)
{
dataContext.Entry(attachedEntity).State = EntityState.Detached;
DbSet.Attach(entity);
dataContext.Entry(entity).State = EntityState.Modified;
await dataContext.SaveChangesAsync();
}
}
And, at last but no least, this is the way I am configuring everything at Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<PortalContext>(
options => options.UseSqlServer(Configuration.GetConnectionString("PortalContext"))
);
services.AddTransient(typeof(IGenericService<>), typeof(GenericService<>));
services.AddTransient(typeof(IBaseRepository<>), typeof(BaseRepository<>));
services.AddTransient<Func<string, ClaimsPrincipal, IRoleCheck>>((serviceProvider) =>
{
return (controllerName, claimsPrincipal) =>
new RoleCheck(serviceProvider.GetRequiredService<IGenericService<Dossier>>(),
serviceProvider.GetRequiredService<IGenericService<DossierTemplate>>(),
serviceProvider.GetRequiredService<IGenericService<Dashboard>>(),
controllerName, claimsPrincipal);
});
}
What the application first does is calling the RoleCheck class to retrieve and filter the required entities and, after that, the user can update them.
When I call the update function at the controller
public async Task<ActionResult<Dashboard>> Put(int id, [FromBody] Dashboard dashboard)
{
var currentDashboard = await service.Get(id);
if (currentDashboard == null)
{
return NotFound();
}
await service.Update(dashboard, currentDashboard);
return Ok();
}
I always receive the next error at the repository:
error
Is there something I am doing wrong? I have been stuck with this for a week now...
Thanks in advance and sorry for the long text, but I wanted it to be clear.
I could finally solve it by adding .AsNoTracking() at the Get() method of my repository:
public async Task<T> Get(int id, Func<IQueryable<T>, IIncludableQueryable<T, object>> includes)
{
IQueryable <T> query = DbSet.AsNoTracking();
if (includes != null)
{
query = includes(query);
}
return await query.FirstOrDefaultAsync(m => m.Id == id);
}

Automapper not mapping dependent entity with get request

When I call the object model variable ,straight from the database, I receive all the needed data about the dependent entity: MenuItem.
When i use an automapper it displays the mapped MenuItem object as null.
Automapping for getAll and getAllById works.
Principle Entity: ItemCategory
DependentEntity: MenuItem
Please help.
Mapping Profile:
public class MappingProfile: Profile
{
public MappingProfile()
{
CreateMap<ItemCategory, ItemCategoryDto>();
CreateMap<ItemType, ItemTypeDto>();
CreateMap<ItemStatus, ItemStatusDto>();
CreateMap<MenuItem, MenuItemDto>();
//CreateMap<ItemCategory, ItemCategoryDto>();
//CreateMap<ItemType, ItemTypeDto>();
//CreateMap<ItemStatus, ItemStatusDto>();
}
}
ItemCategory Model class:
public partial class ItemCategory
{
public ItemCategory()
{
MenuItem = new HashSet<MenuItem>();
}
public Guid Id { get; set; }
public string Description { get; set; }
public virtual ICollection<MenuItem> MenuItem { get; set; }
}
MenuItem Model Class:
public partial class MenuItem
{
public MenuItem()
{
Menu = new HashSet<Menu>();
MenuItemAllergy = new HashSet<MenuItemAllergy>();
MenuItemIngredient = new HashSet<MenuItemIngredient>();
MenuItemPrice = new HashSet<MenuItemPrice>();
MenuItemSpecial = new HashSet<MenuItemSpecial>();
OrderMenuItem = new HashSet<OrderMenuItem>();
}
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public Guid ItemCategoryId { get; set; }
public Guid ItemTypeId { get; set; }
public Guid ItemStatusId { get; set; }
public virtual ItemCategory ItemCategory { get; set; }
public virtual ItemStatus ItemStatus { get; set; }
public virtual ItemType ItemType { get; set; }
public virtual ICollection<Menu> Menu { get; set; }
public virtual ICollection<MenuItemAllergy> MenuItemAllergy { get; set; }
public virtual ICollection<MenuItemIngredient> MenuItemIngredient { get; set; }
public virtual ICollection<MenuItemPrice> MenuItemPrice { get; set; }
public virtual ICollection<MenuItemSpecial> MenuItemSpecial { get; set; }
public virtual ICollection<OrderMenuItem> OrderMenuItem { get; set; }
}
ItemCategoryDTO:
public class ItemCategoryDto
{
public Guid Id { get; set; }
public string Description { get; set; }
public IEnumerable<MenuItemDto> MenuItems { get; set; }
}
MenuItemDTO:
public class MenuItemDto
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
ItemCategory Interface:
public interface IItemCategory: IRepositoryBase<ItemCategory>
{
IEnumerable<ItemCategory> GetAllItemCategories();
ItemCategory GetItemCategoryById(Guid categoryId);
ItemCategory GetItemCategoryWithDetails(Guid categoryId);
}
ItemCategory Repository:
public class ItemCategoryRepository: RepositoryBase<ItemCategory>, IItemCategory
{
public ItemCategoryRepository(eWaiterTestContext repositoryContext)
: base(repositoryContext)
{
}
public IEnumerable<ItemCategory> GetAllItemCategories()
{
return FindAll()
.OrderBy(ic => ic.Description)
.ToList();
}
//Can Add Find By description same way
public ItemCategory GetItemCategoryById(Guid categoryId)
{
return FindByCondition(x => x.Id.Equals(categoryId))
.FirstOrDefault();
}
public ItemCategory GetItemCategoryWithDetails(Guid categoryId)
{
return FindByCondition(x => x.Id.Equals(categoryId))
.Include(z=>z.MenuItem)
.FirstOrDefault();
}
}
ItemCategory Controller to return ItemCategory with related menuItems:
[HttpGet("{id}/menuItem")]
public IActionResult GetItemCategoryWithDetails(Guid id)
{
try
{
var category = _repository.ItemCategory.GetItemCategoryWithDetails(id);
if (category == null)
{
_logger.LogError($"Category with id: {id}, hasn't been found in db.");
return NotFound();
}
else
{
_logger.LogInfo($"Returned owner with details for id: {id}");
var result = _mapper.Map<ItemCategoryDto>(category);
return Ok(result);
}
}
catch (Exception ex)
{
_logger.LogError($"Something went wrong inside GetItemCategoryWithDetails action:
straight from the database{ex.Message}");
return StatusCode(500, "Internal server error");
}
}
Names of the properties must be the same, but you just skipped 's' for ItemCategory model
ItemCategory Model class:
public partial class ItemCategory {
public virtual ICollection<MenuItem> MenuItem { get; set; }
}
ItemCategoryDto Model class:
public partial class ItemCategoryDto {
public virtual ICollection<MenuItem> MenuItems { get; set; }
}
Or you can just setup AutoMapper like this :)
public class CategoryMapper: Profile
{
public CategoryMapper()
{
CreateMap<ItemCategory, ItemCategoryDto>()
.ForMember(x => x.MenuItems, x => x.MapFrom(src => src.MenuItem));
}
}
and inject it in Startup.cs
var mappingConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new GemlemMapper());
});
IMapper mapper = mappingConfig.CreateMapper();
services.AddSingleton(mapper);
Hope it will help, also be aware that's all properties which you need to use should be Included by the Include().

ASP.Net core web API encode string to base64

I am new to .Net Core development. I have a model:
public class CoreGoal
{
[Key]
public long CoreGoalId { get; set; }
public string Title { get; set; }
public string Effect { get; set; }
public string Target_Audience { get; set; }
public string Infrastructure { get; set; }
public virtual ICollection<Image> Images { get; set; }
public CoreGoal()
{
}
}
And Image model is as following:
public class Image
{
[Key]
public long ImagelId { get; set; }
public string Base64 { get; set; }
[ForeignKey("CoreGoalId")]
public long CoreGoalId { get; set; }
public Image()
{
}
}
I am using Repository pattern. My repository:
public interface ICoreGoalRepository
{
void CreateCoreGoal(CoreGoal coreGoal);
}
public class CoreGoalRepository : ICoreGoalRepository
{
private readonly WebAPIDataContext _db;
public CoreGoalRepository(WebAPIDataContext db)
{
_db = db;
}
//Find specific
public CoreGoal Find(long key)
{
return _db.CoreGoals.FirstOrDefault(t => t.CoreGoalId == key);
}
//Add new
public void CreateCoreGoal(CoreGoal coreGoal)
{
_db.CoreGoals.Add(coreGoal);
_db.SaveChanges();
}
}
And controller:
[Route("api/[controller]")]
public class CoreGoalController : Controller
{
private readonly ICoreGoalRepository _coreGoalRepository;
//Controller
public CoreGoalController(ICoreGoalRepository coreGoalRepository) {
_coreGoalRepository = coreGoalRepository;
}
[HttpGet("{id}", Name = "GetCoreGoal")]
public IActionResult GetById(long id)
{
var item = _coreGoalRepository.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
//Create
[HttpPost]
public IActionResult Create([FromBody] CoreGoal item)
{
if (item == null)
{
return BadRequest();
}
_coreGoalRepository.CreateCoreGoal(item);
return CreatedAtRoute("GetCoreGoal", new { id = item.CoreGoalId }, item);
}
}
On POST request for CoreGoal- While creating a new CoreGoal, I would like to convert Image model's Base64 attribute from string to byte[]. I found this (https://adrientorris.github.io/aspnet-core/manage-base64-encoding.html) blogpost, but I am not sure where Am I supposed to write this piece of code.
Can someone help me?
Initially you should chage you database model to save you binary image to db (also, it's still not good idea, but let leave it for a now):
public class Image
{
[Key]
public long ImagelId { get; set; }
[NotMapped]
public string Base64 { get; set; }
public byte[] Binary {get; set;}
[ForeignKey("CoreGoalId")]
public long CoreGoalId { get; set; }
public Image()
{
}
}
next you just should convert your image inside controller:
[HttpPost]
public IActionResult Create([FromBody] CoreGoal item)
{
if (item == null)
{
return BadRequest();
}
item.Binary = Convert.FromBase64String(item.Base64);
_coreGoalRepository.CreateCoreGoal(item);
return CreatedAtRoute("GetCoreGoal", new { id = item.CoreGoalId }, item);
}
BTW:you code still not good. It's not necessary to use Repository pattern with EF core (https://www.thereformedprogrammer.net/is-the-repository-pattern-useful-with-entity-framework-core/). And you should introduce two model layers: public layer and model layer. You shouldn't expose EF Core contract to outside.