如何更改 Asp.Net Core 中某些操作的序列化方法(Typed,None)?

Posted

技术标签:

【中文标题】如何更改 Asp.Net Core 中某些操作的序列化方法(Typed,None)?【英文标题】:How can I change Serialization approach (Typed,None) for some actions in Asp.Net Core? 【发布时间】:2019-11-26 00:39:58 【问题描述】:

我有 asp.net core 2.2 web 应用程序。应用程序包含命令和查询操作,命令操作必须返回类型化的 json 响应:


   $type:"A.B.Customer, x.dll ",
   id: 11231,
   name: "Erwin .."

查询操作必须返回非类型化响应:


  id: 34234,
  name: "Erwin .. "

我们可以在启动时为 Json 响应选择一种输出格式器。

 services.AddMvc().AddJsonOptions(o =>
                
    SerializerSettings.TypeNameHandling=Newtonsoft.Json.TypeNameHandling.Objects
   // SerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.None

那么如何通过操作更改相同响应类型(应用程序/json)的输出格式器?

【问题讨论】:

【参考方案1】:

有多种方法可以做到这一点。

一种是直接调用 JSON.NET 方法并将您的设置传递给它。

JsonSerializerSettings settings = new JsonSerializerSettings

    TypeNameHandling = TypeNameHandling.Objects
;

return base.Content(JsonConvert.SerializeObject(query, settings), "application/json");

或者,返回JsonResult

JsonSerializerSettings settings = new JsonSerializerSettings

    TypeNameHandling = TypeNameHandling.Objects
;

return new JsonResult(query, settings);

注意第二个例子。在 .NET Core 3.0 中,JSON.NET 不再硬连线到 ASP.NET Core 中,并且 ASP.NET Core 不提供 JSON.NET 并使用新的 System.Text.Json 类基跨度。

在 ASP.NET Core 2.x 中,JsonResult 接受 JsonSerializerSettings 作为第二个参数。 从 ASP.NET Core 3.x 开始,JsonResult 接受 object,并且根据所使用的序列化程序,需要不同的类型。

这意味着,如果您在代码中使用第二个示例,则在迁移到 ASP.NET Core 3.0 时(起初)会中断,因为它不再依赖于 JSON.NET。您可以通过将 Newtonsoft.Json 包添加到您的项目并添加来轻松地将 JSON.NET 添加回它

servics.AddNewtonsoftJson();

在您的 ConfigureServices 方法中,再次使用 JSON.NET。但是,如果将来您决定离开 JSON.NET 并使用 System.Text.Json 或任何其他 Json 序列化程序,则必须更改所有使用它的地方。

随意将其更改为扩展方法,创建自己的动作结果类,继承自 JsonResult 等。

public class TypelessJsonResult : JsonResult

    public TypelessJsonResult(object value) : base(value)
    
        SerializerSettings.TypeNameHandling = TypeNameHandling.None;
    

并将控制器的操作代码减少到

return new TypelessJsonResult(query);

【讨论】:

要更改的action太多了,所以我会尝试为这个需求准备ActionFilter/ResultFilter,感谢@Tseng的详细回复 @ozz:我很好奇:当您使用(键入)命令时,为什么会有多个端点? (这就是可以说“改变太多动作”的唯一原因)。当您使用命令时,它基本上是 RPC 并且仅命令类型就足以通过它们的完整限定名称来区分命令。完全限定类型的需要是您有一个基类和一个接受该基类型的操作。如果每个操作都接受最具体的类型名称,您将只有多个操作,但是,您不需要 $type 参数作为 JSON 反序列化器提示。没有? 我认为我歪曲了问题,我没有使用 $type 信息作为命令调度程序。我为我的实体创建了通用的创建、编辑、显示页面(前端:Vue+Vuetify)。我想知道服务器端这个创建和编辑页面的类型信息。所以我为他们使用了类型化的序列化-反序列化。另一方面,我还为 ViewModel 对象创建了通用/动态显示。目前对它们没有“类型信息”要求:) 如果我尝试进行抽象,1- 命令(创建/更新 - 我需要类型化反序列化),2- 查询,2a - 查询命令(新/编辑页面 - 我需要类型化序列化) 2b - 只是查询(查看页面 - 现在不需要输入序列化)感谢您的帮助,问题现在已经解决了 :)

以上是关于如何更改 Asp.Net Core 中某些操作的序列化方法(Typed,None)?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 ASP.NET Core 3 中的中间 Web API 传递未更改的 HTTP 响应?

ASP.NET Core 会话超时

如何在 ASP.NET Core 中更改 Swagger 的基本 url

如何更改 asp.net core 1 中的令牌响应?

迁移到 ASP.Net Core 3 后如何更改此查询

Asp.Net Core Web API 应用程序:如何更改监听地址?