【发布时间】:2021-01-25 11:30:15
【问题描述】:
我正在尝试在 Blazor wasm 中创建一个表单,它允许我将 Recipes 添加到数据库中。我有 3 个域对象:Ingredient、Recipe 和 IngredientRecipe。我正在使用 DTO 概念,并且我有对应于域对象 3 个 DTO 的类:IngredientDto、RecipeDto 和 IngredientRecipeDto。添加Ingredients 的表单可以正常工作。问题是当我尝试创建一个新的Recipe 时。错误消息显示 2 个类中的错误:RecipeMapper 和 RecipeController。我的错误与将域对象映射到 DTO 有关,我不知道如何解决这个问题。请给我一些建议如何修复此问题
完全错误
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: AutoMapper.AutoMapperMappingException: Error mapping types.
Mapping types:
RecipeDto -> Recipe
CookBook.Shared.Data.Dto.RecipeDto -> CookBook.Shared.Entities.Recipe
Type Map configuration:
RecipeDto -> Recipe
CookBook.Shared.Data.Dto.RecipeDto -> CookBook.Shared.Entities.Recipe
Destination Member:
ListOfIngredients
---> AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types:
IngredientRecipeDto -> IngredientRecipe
CookBook.Shared.Data.Dto.IngredientRecipeDto -> CookBook.Shared.Entities.IngredientRecipe
at lambda_method83(Closure , IngredientRecipeDto , IngredientRecipe , ResolutionContext )
at lambda_method82(Closure , Object , Recipe , ResolutionContext )
--- End of inner exception stack trace ---
at lambda_method82(Closure , Object , Recipe , ResolutionContext )
at CookBook.Server.Mappers.RecipeMapper.Map(RecipeDto recipeDto) in C:\Users\48510\source\repos\CookBook\CookBook\Server\Mappers\RecipeMapper.cs:line 32
at CookBook.Server.Controllers.RecipesController.Post(RecipeDto recipeDto) in C:\Users\48510\source\repos\CookBook\CookBook\Server\Controllers\RecipesController.cs:line 58
at lambda_method42(Closure , Object )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
Connection: close
Content-Length: 164
Content-Type: application/json; charset=utf-8
Host: localhost:44332
Referer: https://localhost:44332/recipes/create
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
origin: https://localhost:44332
sec-fetch-site: same-origin
sec-fetch-mode: cors
sec-fetch-dest: empty
System.ApplicationException: AutoMapper.AutoMapperMappingException: Error mapping types.
Mapping types:
RecipeDto -> Recipe
CookBook.Shared.Data.Dto.RecipeDto -> CookBook.Shared.Entities.Recipe
Type Map configuration:
RecipeDto -> Recipe
CookBook.Shared.Data.Dto.RecipeDto -> CookBook.Shared.Entities.Recipe
Destination Member:
ListOfIngredients
---> AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types:
IngredientRecipeDto -> IngredientRecipe
CookBook.Shared.Data.Dto.IngredientRecipeDto -> CookBook.Shared.Entities.IngredientRecipe
at lambda_method83(Closure , IngredientRecipeDto , IngredientRecipe , ResolutionContext )
at lambda_method82(Closure , Object , Recipe , ResolutionContext )
--- End of inner exception stack trace ---
at lambda_method82(Closure , Object , Recipe , ResolutionContext )
at CookBook.Server.Mappers.RecipeMapper.Map(RecipeDto recipeDto) in C:\Users\48510\source\repos\CookBook\CookBook\Server\Mappers\RecipeMapper.cs:line 32
at CookBook.Server.Controllers.RecipesController.Post(RecipeDto recipeDto) in C:\Users\48510\source\repos\CookBook\CookBook\Server\Controllers\RecipesController.cs:line 58
at lambda_method42(Closure , Object )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
Connection: close
Content-Length: 164
Content-Type: application/json; charset=utf-8
Host: localhost:44332
Referer: https://localhost:44332/recipes/create
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
origin: https://localhost:44332
sec-fetch-site: same-origin
sec-fetch-mode: cors
sec-fetch-dest: empty
at CookBook.Client.Repositories.RecipeRepository.CreateRecipe(RecipeDto recipeDto) in C:\Users\48510\source\repos\CookBook\CookBook\Client\Repositories\RecipeRepository.cs:line 30
at CookBook.Client.Pages.Recipe.RecipeTest.SaveRecipe() in C:\Users\48510\source\repos\CookBook\CookBook\Client\Pages\Recipe\RecipeTest.razor:line 121
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync()
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
我的域类
public class Ingredient : BaseEntity
{
public string Name { get; set; }
public int Kcal { get; set; }
public virtual List<IngredientRecipe> IngredientRecipe { get; set; }
}
public class Recipe : BaseEntity
{
public string Name { get; set; }
public virtual List<IngredientRecipe> ListOfIngredients { get; set; }
}
public class IngredientRecipe : BaseEntity
{
public int IngredientId { get; set; }
public int RecipeId { get; set; }
public int Amount { get; set; }
public virtual Ingredient Ingredient { get; set; }
public virtual Recipe Recipe { get; set; }
}
我的 DTO
public class IngredientDto : BaseEntity
{
public string Name { get; set; }
public int Kcal { get; set; }
public List<IngredientRecipe> IngredientRecipe { get; set; }
}
public class RecipeDto : BaseEntity
{
public string Name { get; set; }
public List<IngredientRecipeDto> ListOfIngredients { get; set; } = new List<IngredientRecipeDto>();
}
public class IngredientRecipeDto : BaseEntity
{
public int IngredientId { get; set; }
public int Amount { get; set; }
public IngredientDto Ingredient { get; set; }
public RecipeDto Recipe { get; set; }
}
RecipeMapper,出现错误
public class RecipeMapper
{
private IMapper mapper;
public RecipeMapper()
{
mapper = new MapperConfiguration(config =>
{
config.CreateMap<Recipe, RecipeDto>()
.ForMember(dest => dest.ListOfIngredients, conf => conf.MapFrom(src => src.ListOfIngredients))
.ReverseMap();
}).CreateMapper();
}
public RecipeDto Map(Recipe recipe)
{
return mapper.Map<RecipeDto>(recipe);
}
public Recipe Map(RecipeDto recipeDto)
{
//at this line is error
return mapper.Map<Recipe>(recipeDto);
}
public List<RecipeDto> Map(List<Recipe> recipes)
{
return mapper.Map<List<Recipe>, List<RecipeDto>>(recipes);
}
}
还有RecipeController,Post方法出错
public class RecipesController
{
private readonly AppDbContext context;
private readonly RecipeMapper mapper;
public RecipesController(AppDbContext context, RecipeMapper mapper)
{
this.context = context;
this.mapper = mapper;
}
[HttpGet]
public async Task<ActionResult<List<RecipeDto>>> Get()
{
var ListOfRecipes = await context.Recipes
.Include(x => x.ListOfIngredients)
.ThenInclude(x => x.Ingredient)
.ToListAsync();
var ListOfRecipesDto = mapper.Map(ListOfRecipes);
return ListOfRecipesDto;
}
[HttpGet("{id}")]
public async Task<ActionResult<RecipeDto>> Get(int id)
{
var recipe = await context.Recipes
.Include(x => x.ListOfIngredients)
.ThenInclude(x => x.Ingredient)
.FirstOrDefaultAsync();
var recipeDto = mapper.Map(recipe);
if (recipe == null) { return new NotFoundResult(); }
return recipeDto;
}
[HttpPost]
public async Task<ActionResult<int>> Post(RecipeDto recipeDto)
{
//here is error
var recipe = mapper.Map(recipeDto);
context.Recipes.Add(recipe);
await context.SaveChangesAsync();
return recipe.Id;
}
[HttpDelete("{id}")]
public async Task Delete(int id)
{
var recipeToRemove = context.Recipes.FirstOrDefault(x => x.Id == id);
context.Recipes.Remove(recipeToRemove);
await context.SaveChangesAsync();
}
}
也许问题出在我的表单上,所以我提供了一个 github 链接 https://github.com/szymonJag/CookBook/blob/master/CookBook/Client/Pages/Recipe/RecipeTest.razor
【问题讨论】:
-
是的,我刚刚编辑了帖子
-
您应该改用
ProjectTo。 docs.automapper.org/en/latest/Queryable-Extensions.html
标签: c# asp.net entity-framework automapper blazor