当核心 api 方法类型为 IEnumerable<dynamic> 且没有 newtonsoft.json 引用时 asp.net 如何返回 dapper 动态查询



当asp.net核心api方法类型为IEnumerable且没有newtonsoft.json引用时,我希望返回dapper动态查询。

如果asp.net核心api方法类型为IEnumerable<dynamic>,并且使用Dapper dynamic query系统将抛出异常System.InvalidCastException: Unable to cast object of type '<GetEnumerator>d__9' to type 'System.Collections.IDictionaryEnumerator'

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using ServerApp.Helper;
using Dapper;
namespace ServerApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class ShDjController : ControllerBase
{
[HttpGet]
public IEnumerable<dynamic> Get()
{
using(var cn = DB.GetConnection()){
return cn.Query(@"select * from table");
}
}
}
}

我知道它可以使用NewtonSoft.Json将数据序列化为json字符串来处理这个问题,但它需要更多的参考,比如下面的代码:

[HttpGet]
public string Get()
{
using(var cn = DB.GetConnection()){
return JsonConvert.SerializeObject(cn.Query(@"select * from table "));
}
}

services.AddControllers().AddNewtonsoftJson();

完整错误日志:

System.InvalidCastException: Unable to cast object of type '<GetEnumerator>d__9' to type 'System.Collections.IDictionaryEnumerator'.
at System.Text.Json.JsonSerializer.HandleDictionary(JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, WriteStack& state)
at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, Object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Csproj

<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>

表演示脚本:

CREATE TABLE Table
([col1] int, [col2] int)
;

INSERT INTO Table
([col1], [col2])
VALUES
(1, 2),
(3, 4),
(5, 6)
;

所以我最近使用了Dapper ORM,这对我的来说非常有效

public string Index()
{
using (var cn = new SqlConnection("Data Source=(local);Initial Catalog=Db;Integrated Security=True"))
{
return JsonConvert.SerializeObject( cn.Query(@"SELECT * FROM Accounts.[User]"));
}
}

我甚至不需要使用JsonConvert.SerializeObject

public IEnumerable<dynamic> Index()
{
using (var cn = new SqlConnection("Data Source=(local);Initial Catalog=InstgramWeb;Integrated Security=True"))
{
return  cn.Query(@"SELECT * FROM Accounts.[User]");
}
}

无论你犯了什么错误,都可能与其他事情有关。也许是一个特定的专栏?(或者可能是版本问题?(

编辑:它适用于.NET Core 3.1,而不适用于.NET酷睿3.0。更新版本可以解决问题,否则我们可以使用Newtonsoft.Json

最新更新