c# - 如何在 asp.net Web API 中过滤掉具有自定义属性的字段?
问题描述
我有一个在我的应用程序中使用的工作模型。我想通过公共 API 公开其中一些数据,但我有一些字段我不想返回以供一般使用。一种费力的方法是创建一个单独的模型并创建使用 automapper 来映射我的输出以创建一些 DTO。
我想做的是用自定义属性注释我的模型,然后在将 JSON 发送到客户端之前,以某种方式在运行时使用某种扩展方法或 Web API actionfilter 过滤掉带注释的字段。我不能使用 JsonIgnore,因为我需要这些字段在我的应用程序中进行操作。
有人可以概述一下我将如何做到这一点吗?
提前致谢
编辑
所以我想我可以使用 newtonsoft ShouldSerialize 属性,但是我在寻找一种优雅的方式来设置触发它的条件方面不知所措。我有一个复杂的模型,我认为在运行时我需要反映整个输出,检测某个命名空间中的任何类,并设置一些导致 ShouldSerialize 返回 true 的值
解决方案
如果您绝对想避免 DTO 和[JsonIgnore]
,并且真的想使用自定义属性,则可能必须使用一些反射。我将提出一个远非最佳选择的解决方案,但它可以为您提供一些想法。
首先,创建一个自定义属性来标记不应该通过公共 API 显示的模型属性:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
class DontSendInPublicApiAttribute : Attribute { }
您必须创建一种方法来“擦除”您不想显示的对象属性上的数据。
public static void RemoveSecretData(object obj)
{
// Retrieve all public instance properties defined for the object's type and marked with [DontSendInPublicApi]
var propertiesToHide = obj.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.GetCustomAttribute<DontSendInPublicApiAttribute>() != null);
foreach (var prop in propertiesToHide)
{
// Set all of these properties in the given object to their default values.
// VALUE TYPES (ints, chars, doubles, etc.) will be set to default(TheTypeOfValue), by calling Activator.CreateInstance(TheTypeOfValue).
// REFERENCE TYPES will simply be set to null.
var propertyType = prop.PropertyType;
if (propertyType.IsValueType)
prop.SetValue(obj, Activator.CreateInstance(prop.PropertyType));
else
prop.SetValue(obj, null);
}
}
然后将该属性应用于模型中您希望隐藏的任何字段:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
[DontSendInPublicApi]
public string Occupation { get; set; }
[DontSendInPublicApi]
public int Salary { get; set; }
}
这是一个如何调用它的示例:
var person = new Person() { Name = "John", Age = 29, Occupation = "Engineer", Salary = 200000 };
RemoveSecretData(person);
执行后RemoveSecretData(person)
,您将对象的Occupation
和Salary
属性分别person
设置为null
和0
。
关于此解决方案的注意事项:
- 仅适用于属性。如有必要,您必须修改该
RemoveSecretData()
方法以使其也可以使用字段。 - 不递归访问对象图。如果您的对象引用了另一个带有标记为属性的对象
[DontSendInPublicApi]
,则该属性将不会被隐藏。如有必要,您必须修改该RemoveSecretData()
方法以对更深层次的对象执行递归调用。如果您打算这样做,请注意循环引用。 - 隐藏的属性仍将显示在输出 JSON 上,但值类型的属性将始终呈现
0
(零) 值,而引用类型的属性将始终呈现null
.
推荐阅读
- install4j - Install4J:以编程方式自定义水印文本
- nginx - 如何配置我的 nginx 以使我的 Web 应用程序可以通过 ip 和域名访问?
- cron - Cron 表达式每 30 分钟运行一次,但在两个特定时间之间
- windows-subsystem-for-linux - 您可以使用 Windows 安装制作 WSL 界面吗?
- c++ - 如何编写注册事件的控制台应用程序,只要通过 Windows 设置更改无线电状态,就应该调用它
- java - 当我在 android studio 中使用 recyclerView 时没有响应 onClickListner 为什么?
- database - 在作为 Postgresql 副本的表上创建物化视图时出现问题,返回错误
- performance - 为什么只有 1 KiB 或 2 KiB 访问大小的 L2 硬件预取器性能更差?
- web-crawler - Windows 出站爬虫速度限制
- performance - 在 React 和 Redux 应用程序中调度大量操作对性能有何影响?