在ASP.NET Web API中是否有@JsonView等效

我在Spring和Java方面有更多的经验,但现在我正在开发ASP.NET Web API项目。

所以在Spring中有@JsonView注释,我可以用它来注释我的DTO,所以我可以选择通过REST显示哪些数据。 而且我发现它非常有用。 但我在ASP.NET中找不到任何等价物。 所以我需要为每个特殊用例创建DTO。

因此,例如在Java中,如果我有UserEntity包含有关用户的信息。 有些信息可以公开查看,有些信息只能由管理员查看。 siple解决方案可能就是这样

public class UserEntity { @JsonView(Views.Public.class) @JsonProperty("ID") private Integer id; @JsonView(Views.Public.class) private String name; @JsonView(Views.Admin.class) @JsonFormat( shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") private Date dateOfBirth; @JsonView(Views.Admin.class) private String email; @JsonIgnore private String password; private Integer version; } 

所以在这种情况下,对于ASP.NET中的等效function,我需要创建2个DTO。 一个可以公开看到的用户和一个只能由管理员看到的用户。

 public class PublicUserDto { public int ID {get; set;} public String Name {get; set;} } public class AdminUserDto { public int ID {get; set;} public String Name {get; set;} public DateTime DateOfBirth {get; set;} public string Email {get; set;} } 

有没有更好的解决方案? 是否有一些机制可用于在ASP.NET Web API中创建我的数据视图?

JSON.NET有一个叫做条件属性初始化的东西。 您可以使用以下格式编写方法:

 public bool ShouldSerialize[YourPropertyName]() => someBoolCondition; 

JSON.NET将调用该方法来确定是否应该序列化该属性。 所以你可以有类似的东西:

 public DateTime DateOfBirth {get; set;} public bool ShouldSerializeDateOfBirth() => isAdmin; 

它不如JsonView那么漂亮,但它应该完成这项工作。

您可以使用自定义合约解析程序自行实现。 假设你有属性:

 [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] public class JsonViewAttribute : Attribute { public JsonViewAttribute(string viewName) { ViewName = viewName; } public string ViewName { get; } } 

浏览次数:

 public static class JsonViews { public const string Administrator = "Administrator"; } 

和DTO课程:

 public class UserDto { public int ID { get; set; } public String Name { get; set; } [JsonView(JsonViews.Administrator)] public DateTime DateOfBirth { get; set; } [JsonView(JsonViews.Administrator)] public string Email { get; set; } } 

并且您的目标是仅在当前用户经过身份validation且具有目标角色(“管理员”)时序列化使用JsonView属性。 然后你可以像这样创建合约解析器:

 public class JsonViewContractResolver : JsonContractResolver { public JsonViewContractResolver(MediaTypeFormatter formatter) : base(formatter) { } protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); var viewAttr = member.GetCustomAttribute(); if (viewAttr != null) { // if decorated with attribute property.ShouldSerialize = (instance) => { var context = HttpContext.Current; if (context == null) return true; // we are in context of http request if (context.User == null || context.User.Identity == null) return false; // should serialize only if user is in target role return context.User.Identity.IsAuthenticated && context.User.IsInRole(viewAttr.ViewName); }; } return property; } } 

并在配置中设置它:

 public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new JsonViewContractResolver(config.Formatters.JsonFormatter); } 

现在,只要你在控制器中返回json,就像这样:

 [System.Web.Http.HttpGet] public UserDto Get() { return new UserDto() { ID = 1, DateOfBirth = DateTime.UtcNow, Email = "test", Name = "name" }; } 

它被序列化为json – 如果用户不是管理员,则会省略admin属性。

请注意,如果你这样做:

 [System.Web.Http.HttpGet] public IHttpActionResult Get() { return Json(new UserDto() { ID = 1, DateOfBirth = DateTime.UtcNow, Email = "test", Name = "name" }); } 

不使用Formatter,你必须自己传递自定义格式化程序的序列化设置(当然你需要将它变成可重用的方法,例如在你的基本控制器中声明所有其他inheritance的Json方法):

 return Json(new UserDto() { ID = 1, DateOfBirth = DateTime.UtcNow, Email = "test", Name = "name" }, GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings); 

使用角色只是一个示例,说明如何扩展asp.net api默认使用的JSON.NET序列化程序以获得所需的结果。