Blazor Server中动态对象转Dictionary遇RuntimeBinderException异常
问题分析与解决方案
核心错误原因
- 异步调用未等待:
cybsAuth.RunAsyncJson()是异步方法(从方法名的Async后缀推断),但你直接赋值给dynamic变量时没有用await,导致jsonObject实际是Task对象,而非预期的动态结果对象。这是Blazor Server中报错的关键(控制台可能用了同步方法或正确await了)。 - 误用JsonSerializer.Deserialize:
Deserialize方法的作用是将JSON格式的字符串/字节流转换为对象,而不是将已存在的动态对象(如ExpandoObject)转换为Dictionary。你已经有了内存中的对象,不需要反序列化操作。
修正后的代码
namespace BlazorWebAssembly.Server.Endpoints { public static class CybsAuthEndpoint { static SaveAuthData saveAuthData = new SaveAuthData(); private static string Id = string.Empty; // 把async void改成async Task,避免异步操作失控 public static async Task MapCybsCall(this WebApplication app) { ICallForCybsAuth cybsAuth = new CallForCybsAuth(); // 异步方法必须await,拿到实际的结果对象 dynamic jsonObject = await cybsAuth.RunAsyncJson(); var options = new JsonSerializerOptions { WriteIndented = true, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; var jsonString = JsonSerializer.Serialize(jsonObject, options); Console.WriteLine(jsonString); // 正确将ExpandoObject转换为Dictionary // 方式1:转换为Dictionary<string, object>(保留原值类型) var dict = (Dictionary<string, object>)jsonObject; // 方式2:如果所有值都是字符串,转换为Dictionary<string, string> // var dict = ((IDictionary<string, object>)jsonObject) // .ToDictionary(kv => kv.Key, kv => kv.Value?.ToString() ?? string.Empty); app.MapGet("/cybersource", () => Results.Ok(jsonObject)); } } }
额外说明
- 永远避免在Blazor或ASP.NET Core中使用
async void,除非是事件处理器。异步方法应该返回Task或Task<T>,否则可能导致未捕获的异常和资源泄漏。 ExpandoObject本身实现了IDictionary<string, object>接口,因此可以直接强制转换为Dictionary类型,无需通过JSON序列化/反序列化绕路,这样性能更高且避免类型转换错误。
内容的提问来源于stack exchange,提问作者Adam Williams
相关产品推荐
相关产品推荐

