2013-07-26 4 views
3

У меня есть бизнес-требование только отправлять разрешенные свойства в нашу полезную нагрузку. Например, наш ответ DTO может иметь несколько свойств, а один из них - SSN. Если у пользователя нет разрешений для просмотра SSN, я бы никогда не захотел, чтобы он был в ответ Json. Второе требование состоит в том, что мы отправляем пустые значения, если у клиента есть разрешения на просмотр или изменение свойства. Из-за требования второго требования свойства, которые пользователь не может просматривать в null, не будут работать. Я должен по-прежнему возвращать нулевые значения.ServiceStack Json Serializer игнорирует свойства

У меня есть решение, которое будет работать. Я создаю expandoObject, отражая через мой DTO и добавляя только те свойства, которые мне нужны. Это работает в моих тестах.

Я рассмотрел реализацию ITextSerializer. Я мог бы использовать это и обернуть свой ответ DTO в другой объект, который будет иметь список свойств, которые нужно пропустить. Затем я мог бы свернуть собственные SerializeToString() и SerializeToStream(). На данный момент я не вижу других способов. Я не могу использовать JsConfig и сделать SerializeFn, потому что свойства для пропуска будут меняться с каждым запросом.

Поэтому я считаю, что реализация ITextSerializer - хороший вариант. Есть ли хорошие примеры этого внедрения? Я бы очень хотел использовать всю тяжелую работу, которая уже была выполнена в сериализаторе, и использовать отличную производительность. Я думаю, что в идеальном мире мне просто нужно добавить проверку в WriteType.WriteProperties(), чтобы посмотреть, и свойство - это одно, чтобы писать, но это внутреннее и действительно, большинство из них так что я действительно не могу их преимущества.

Если у кого-то есть проницательность, пожалуйста, дайте мне знать! Может быть, я делаю реализацию ITextSerialzer намного сложнее, чем она есть на самом деле?

Спасибо!

Запрос на увольнение #359 добавил свойство «ExcludePropertyReference» к JsConfig и JsConfigScope. Теперь вы можете исключить ссылки в области, как мне было нужно.

ответ

0

Я бы не стал писать собственный Сериализатор. Я бы попытался найти решения, которые вы можете подключить к существующему коду ServiceStack. Таким образом вам придется меньше беспокоиться об обновлении dll и нарушении изменений.

Одним из возможных решений будет , украшающий ваши свойства специальными атрибутами, которые вы могли бы отразить и скрыть значения свойств. Это может быть сделано в Сервисе до того, как произойдет сериализация. Это все равно будет включать в себя значения, которые у них нет у пользователя, но я бы сказал, что если вы исключите эти свойства, они даже не будут сериализованы JSON в любом случае. Если вы сохраните все свойства одинаково, вы сохраните преимущества сильных типовых DTO.

Вот какой хакерский код я быстро придумал, чтобы продемонстрировать это. Я бы переместил это в плагин и сделал бы отражение быстрее с каким-то кэшированием свойств, но я думаю, что вы получите эту идею.

Убейте URL дважды, используя следующие маршруты, чтобы увидеть его в действии.

  • /тест? Роль
  • /тест?Роль = Администратор (хак притвориться аутентификацией запрос)
 

[System.AttributeUsage(System.AttributeTargets.Property)] 
public class SecureProperty : System.Attribute 
{ 
    public string Role {get;set;} 

    public SecureProperty(string role) 
    { 
     Role = role; 
    } 
} 

[Route("/test")] 
public class Test : IReturn 
{ 
    public string Name { get; set; } 

    [SecureProperty("Admin")] 
    public string SSN { get; set; } 

    public string SSN2 { get; set; } 

    public string Role {get;set;} 
} 

public class TestService : Service 
{ 
    public object Get(Test request) 
    { 
     // hack to demo roles. 
     var usersCurrentRole = request.Role; 

     var props = typeof(Test).GetProperties() 
     .Where(
      prop => ((SecureProperty[])prop 
       .GetCustomAttributes(typeof(SecureProperty), false)) 
       .Any(att => att.Role != usersCurrentRole) 
     ); 

     var t = new Test() { 
      Name = "Joe", 
      SSN = "123-45-6789", 
      SSN2 = "123-45-6789" }; 

     foreach(var p in props) { 
      p.SetValue(t, "xxx-xx-xxxx", null); 
     } 

     return t; 
    } 
} 

Require().StartHost("http://localhost:8080/", 
    configurationBuilder: host => { }); 

Я создаю эту демонстрацию в ScriptCS. Проверьте это.

+0

Благодарим за помощь, но вся моя причина в том, что вы хотите изменить сериализатор, так что я не буду отражать объект ответа более одного раза. Ваше решение все равно потребует этого. Однако мне нравится ваша идея создания настраиваемого атрибута. У меня будут некоторые свойства, которые не являются полномочиями, и я могу украсить их атрибутами. –

Смежные вопросы