简体   繁体   English

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

[英]Is there @JsonView equivalent in ASP.NET Web API

I have much more experience in Spring and Java, but now I am working on ASP.NET Web API project. 我在Spring和Java方面有很多经验,但现在我正在开发ASP.NET Web API项目。

So in Spring there is @JsonView annotation with which I can annotate my DTOs, so I could select which data I will show through REST. 所以在Spring中有@JsonView注释,我可以用它来注释我的DTO,所以我可以选择通过REST显示哪些数据。 And I find that very useful. 而且我发现它非常有用。 But I cannot find any equivalent in ASP.NET. 但我在ASP.NET中找不到任何等价物。 So I would need to create DTO for every special usecase. 所以我需要为每个特殊用例创建DTO。

So for example in Java if I have UserEntity that contains information about users. 因此,例如在Java中,如果我有UserEntity包含有关用户的信息。 Some information can be seen publicly and some can be seen only by admins. 有些信息可以公开查看,有些信息只能由管理员查看。 The siple solution could be this 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;
}

So in this case for equivalent functionality in ASP.NET I would need to create 2 DTOs. 所以在这种情况下,对于ASP.NET中的等效功能,我需要创建2个DTO。 One for user that can be seen publicly and one for user that can be seen only by admin. 一个可以公开看到的用户和一个只能由管理员看到的用户。

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;}
}

Is there any better solution? 有没有更好的解决方案? Is there some mechanism that I can use to create view over my data in ASP.NET Web API? 是否有一些机制可用于在ASP.NET Web API中创建我的数据视图?

JSON.NET has something called Conditional Property Initialization . JSON.NET有一个叫做条件属性初始化的东西。 You can write a method with the following format: 您可以使用以下格式编写方法:

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

JSON.NET will call that method to determine if that property should be serialized or not. JSON.NET将调用该方法来确定是否应该序列化该属性。 So you could have something like: 所以你可能有类似的东西:

public DateTime DateOfBirth {get; set;}

public bool ShouldSerializeDateOfBirth() => isAdmin;

It's not as pretty as JsonView but it should do the job. 它不如JsonView那么漂亮,但它应该完成这项工作。

You can implement that yourself using custom contract resolver. 您可以使用自定义合约解析程序自行实现。 Suppose you have attribute: 假设你有属性:

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

    public string ViewName { get; }
}

Views: 浏览次数:

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

And DTO class: 和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; }
}

And your goal is to serialize properties decorated with JsonView only if current user is authenticated and has target role ("Administrator"). 并且您的目标是仅在当前用户经过身份验证且具有目标角色(“管理员”)时序列化使用JsonView属性。 Then you can create contract resolver like this: 然后你可以像这样创建合约解析器:

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<JsonViewAttribute>();
        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;
    }
}

And set it in config: 并在配置中设置:

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

Now whenever you return json in controller like this: 现在,只要你在控制器中返回json,就像这样:

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

And it is serialized to json - admin properties would be omitted if user is not administrator. 它被序列化为json - 如果用户不是管理员,将省略admin属性。

Note that if you would do this: 请注意,如果你这样做:

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

Formatter is not used and you have to pass serialization settings with custom formatter yourself (of course you need to make it into reusable method, for example declare Json method in your base controller from which all other inherit): 没有使用Formatter,你必须自己传递自定义格式化程序的序列化设置(当然你需要将它变成可重用的方法,例如在你的基本控制器中声明所有其他继承的Json方法):

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

Using roles is just an example to show how you can extend JSON.NET serializer used by asp.net api by default to achieve desired result. 使用角色只是一个示例,说明如何扩展asp.net api默认使用的JSON.NET序列化程序以获得所需的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM