为 ASP.NET Core 中的所有响应添加属性

Bri*_*ian 4 c# asp.net-core

我有一个具有多个端点的 API。我想向所有端点响应添加一个属性,而不是将其单独添加到每个端点响应模型。

前任:

public class MyClass
{
    public string MyProperty { get; set; } = "Hello";
}

public class MyOtherClass
{
    public string MyOtherProperty { get; set; } = "World";
}

public class MyController : ControllerBase
{
    [HttpPost]
    public async Task<ActionResult<MyClass>> EndpointOne(POSTData data)
    {
        // implementation omitted
    }

    [HttpPost]
    public async Task<ActionResult<MyOtherClass>> EndpointTwo(POSTOtherData otherData)
    {
        // implementation omitted
    }
}
Run Code Online (Sandbox Code Playgroud)

MyClass调用任一端点会返回或 的JSON 表示形式MyOtherClass- 即

{ "MyProperty":"Hello" } or { "MyOtherProperty":"World" }
Run Code Online (Sandbox Code Playgroud)

我想ApiName向 API 中的所有端点添加一个属性(例如 string ),以便上述代码的结果可以是(视情况而定)

{ "MyProperty":"Hello", "ApiName":"My awesome API" } 
Run Code Online (Sandbox Code Playgroud)

或者

{ "MyOtherProperty":"World", "ApiName":"My awesome API" }
Run Code Online (Sandbox Code Playgroud)

有没有办法在返回之前挂钩 JSON 字符串化结果并添加类似的顶级属性?如果是这样,我想我必须将其连接起来startup.cs,所以我一直在寻找app.UseEndpoints(...)方法,但到目前为止还没有找到任何有效的方法。要么没有添加属性,要么用新属性替换了原始结果。

提前致谢!

Dan*_*ica 7

在您的网络 api 中使用 Newtonsoft.Json

在 Startup.cs 中注册自定义合约解析器:

builder.Services.AddControllers()
    .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = CustomContractResolver.Instance);
Run Code Online (Sandbox Code Playgroud)

实施:

public class CustomContractResolver : DefaultContractResolver {
    public static CustomContractResolver Instance { get; } = new CustomContractResolver();

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var properties = base.CreateProperties(type, memberSerialization);
        // add new property
        ...
        properties.Add(newProp);
        return properties;
    }}
Run Code Online (Sandbox Code Playgroud)

查看更多Json.net 向包含特定类型的每个类添加属性


use*_*390 5

您可以添加具有共享属性的基类。应该适用于 XML 和 JSON。

public class MyApiClass
{
    public string ApiName => "MyAwesomeApi";
}

public class MyClass : MyApiClass
{
    public string MyProperty { get; set; } = "Hello";
}

public class MyOtherClass : MyApiClass
{
    public string MyOtherProperty { get; set; } = "World";
}

public class MyController : ControllerBase
{
    [HttpPost]
    public async Task<ActionResult<MyClass>> EndpointOne(POSTData data)
    {
        // implementation omitted
    }

    [HttpPost]
    public async Task<ActionResult<MyOtherClass>> EndpointTwo(POSTOtherData otherData)
    {
        // implementation omitted
    }
}
Run Code Online (Sandbox Code Playgroud)