ASP.NET Core Razor Pages仓储异步Get方法ArgumentException异常求助
实体创建成功保存到数据库后,跳转到详情页时抛出ArgumentException异常,多次参照教程重写代码、更换仓储模式实现、修改实体ID类型(从Guid改为int)均无改善。
相关代码
ReadRepository.cs 查询方法
public async Task<T> GetByIdAsync(string id) => await Table.FindAsync(Guid.Parse(id));
ShowDraw.cshtml.cs
private readonly IDrawReadRepository _drawReadRepository; public ShowDrawModel(IDrawReadRepository drawReadRepository) { _drawReadRepository = drawReadRepository; } public Draw Draw { get; set; } public async Task OnGet(string id) { Draw = await _drawReadRepository.GetByIdAsync(id); if (Draw == null) { RedirectToPage("../Content/Error/UserNotFound"); } }
CreateDraw.cshtml.cs(创建实体后跳转逻辑)
public async Task<IActionResult> OnPostAsync() { Draw draw; if (_signInManager.IsSignedIn(User)) { var user = _userManager.GetUserAsync(User).Result; if (user != null) { draw = CreateDraw(user); } else { return RedirectToPage("/Error/UserNotFound"); } } else { draw = CreateDraw(null); } await _drawWriteRepository.AddAsync(draw); await _drawWriteRepository.SaveAsync(); return RedirectToPage("../User/ShowDraw", new { id = draw.Id.ToString() }); }
抛出的异常信息
An unhandled exception occurred while processing the request.
ArgumentException: Expression of type 'System.Collections.Generic.ICollection1[System.String]' cannot be used for parameter of type 'System.Collections.Generic.IList1[System.String]' of method 'System.Collections.Generic.IList1[System.String] PopulateList[String](System.Collections.Generic.IList1[System.String], System.Collections.Generic.IList`1[System.String])' (Parameter 'arg0')
System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, string methodParamName, string argumentParamName, int index)ArgumentException: Expression of type 'System.Collections.Generic.ICollection
1[System.String]' cannot be used for parameter of type 'System.Collections.Generic.IList1[System.String]' of method 'System.Collections.Generic.IList1[System.String] PopulateList[String](System.Collections.Generic.IList1[System.String], System.Collections.Generic.IList`1[System.String])' (Parameter 'arg0')
System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, string methodParamName, string argumentParamName, int index)
System.Linq.Expressions.Expression.Call(MethodInfo method, Expression arg0, Expression arg1)
Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSource.g__CreateMemberAssignment|14_0(Expression parameter, MemberInfo memberInfo, IPropertyBase property, Expression value)
Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSource.AddInitializeExpressions(HashSet properties, ParameterBindingInfo bindingInfo, Expression instanceVariable, List blockExpressions)
Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSource.CreateMaterializeExpression(List blockExpressions, ParameterExpression instanceVariable, Expression constructorExpression, HashSet properties, ParameterBindingInfo bindingInfo)
Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSource.CreateMaterializeExpression(EntityMaterializerSourceParameters parameters, Expression materializationContextExpression)
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor+EntityMaterializerInjectingExpressionVisitor.CreateFullMaterializeExpression(ITypeBase concreteTypeBase, ValueTuple<Type, ParameterExpression, ParameterExpression, ParameterExpression> materializeExpressionContext)
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor+EntityMaterializerInjectingExpressionVisitor.MaterializeEntity(StructuralTypeShaperExpression shaper, ParameterExpression materializationContextVariable, ParameterExpression concreteEntityTypeVariable, ParameterExpression instanceVariable, ParameterExpression entryVariable)
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor+EntityMaterializerInjectingExpressionVisitor.ProcessEntityShaper(StructuralTypeShaperExpression shaper)
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor+EntityMaterializerInjectingExpressionVisitor.VisitExtension(Expression extensionExpression)
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor+EntityMaterializerInjectingExpressionVisitor.Inject(Expression expression)
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.InjectEntityMaterializers(Expression expression)
Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor+ShaperProcessingExpressionVisitor.VisitExtension(Expression extensionExpression)
Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor+ShaperProcessingExpressionVisitor.ProcessShaper(Expression shaperExpression, out RelationalCommandCache relationalCommandCache, out IReadOnlyList readerColumns, out LambdaExpression relatedDataLoaders, ref int collectionId)
Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor(Expression query)
Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery(Expression query, bool async)
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore(IDatabase database, Expression query, IModel model, bool async)
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<>c__DisplayClass12_0.b__0()
Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery(object cacheKey, Func<Func<QueryContext, TResult>> compiler)
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync(Expression query, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync(Expression expression, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync<TSource, TResult>(MethodInfo operatorMethodInfo, IQueryable source, Expression expression, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync<TSource, TResult>(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expression, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.FirstOrDefaultAsync(IQueryable source, Expression<Func<TSource, bool>> predicate, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Internal.EntityFinder.FindAsync(object[] keyValues, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Internal.InternalDbSet.FindAsync(object[] keyValues)
xxx.Persistence.Repositories.ReadRepository.GetByIdAsync(string id) in ReadRepository.cs
public async Task GetByIdAsync(string id) => await Table.FindAsync(Guid.Parse(id));
xxx.Pages.User.ShowDrawModel.OnGet(string id)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory+NonGenericTaskHandlerMethod.Execute(object receiver, object[] arguments)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
已尝试方案
- 将实体ID类型从Guid改为int,异常仍出现
- 参照教程使用3种不同仓储模式实现,问题未解决
原因分析与解决方案
原因
异常核心提示ICollection<string>无法转换为IList<string>,这是EF Core在实体化Draw对象时,尝试调用内部PopulateList方法填充集合属性,但该方法要求参数为IList<T>类型,而你的Draw实体中存在类型为ICollection<string>的集合属性,导致类型不匹配。
解决方案
- 修改实体集合属性类型
检查Draw实体类,将所有ICollection<string>类型的属性改为IList<string>。例如:
// 原代码 public ICollection<string> Tags { get; set; } // 修改后 public IList<string> Tags { get; set; } = new List<string>();
- 配置EF Core集合转换(可选,不修改实体类型时使用)
如果不想修改实体属性类型,可以在DbContext的OnModelCreating方法中,为该集合属性配置转换逻辑,确保EF Core使用List<string>实例填充:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Draw>() .Property(d => d.Tags) .HasConversion( v => string.Join(',', v), v => v.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList() ); }
注:此方式适用于存储字符串分割的集合,根据你的实际存储方式调整转换逻辑。
- 修复ShowDraw页跳转逻辑(次要问题)
当前ShowDraw.cshtml.cs的OnGet方法中,RedirectToPage没有返回值,导致即使Draw为null也不会执行跳转,需修改为:
public async Task<IActionResult> OnGet(string id) { Draw = await _drawReadRepository.GetByIdAsync(id); if (Draw == null) { return RedirectToPage("../Content/Error/UserNotFound"); } return Page(); }
内容的提问来源于stack exchange,提问作者dorvazgon

