2013-07-26 66 views
3

我有一個業務需求只發送我們的響應負載中的權限屬性。例如,我們的答覆DTO可能有幾個屬性,其中一個屬於SSN。如果用戶沒有權限查看SSN,那麼我絕不希望它在Json響應中。第二個要求是,如果客戶端有權查看或更改屬性,則發送空值。由於第二個要求將用戶無法查看的屬性設置爲null將不起作用。我必須仍然返回空值。ServiceStack Json串行器忽略屬性

我有一個解決方案,將工作。我通過反射DTO來創建expandoObject,並只添加我需要的屬性。這是在我的測試中工作。

我看過實現ITextSerializer。我可以使用它並將我的響應DTO包裹在另一個將會跳過屬性列表的對象中。然後我可以推出我自己的SerializeToString()和SerializeToStream()。在這一點上,我真的沒有看到任何其他方法。我無法使用JsConfig並創建一個SerializeFn,因爲要跳過的屬性會隨着每個請求而改變。

所以我認爲實施ITextSerializer是一個不錯的選擇。有沒有這個實施的好例子?我真的很想使用已經在序列化程序中完成的所有努力工作,並充分利用優秀的性能。我認爲在一個理想的世界中,我只需要在WriteType.WriteProperties()中添加一個檢查來查看該屬性是可以編寫的屬性,但這是內部的,其中大部分都是我無法真正理解的他們的優勢。

如果有人有一些見解,請讓我知道!也許我正在讓ITextSerialzer的實現更加困難,它確實是這樣嗎?

謝謝!

拉請求#359將屬性「ExcludePropertyReference」添加到JsConfig和JsConfigScope。您現在可以像我需要的範圍中排除引用。

回答

0

我會猶豫編寫我自己的串行器。我會嘗試找到可以插入現有ServiceStack代碼的解決方案。這樣,您將不必擔心更新dll和重大更改。

一個潛在的解決方案是裝飾你的屬性與自定義屬性,你可以反思和晦澀的屬性值。即使發生序列化,也可以在服務中完成。這仍然包含用戶無權查看的值,但我會爭辯說,如果您將這些屬性清空,那麼它們甚至不會被JSON序列化。 如果您保留所有屬性相同,您將保留強類型DTO的好處。

這裏有一些我很快想到的hacky代碼來演示這一點。我會將這個插入到一個插件中,並通過某種屬性緩存來加快反射速度,但我認爲你會明白。

使用以下路線點擊兩次路徑即可看到它的行動。

  • /測試?作用
  • /測試?角色=管理員(黑客冒充驗證的請求)
 

[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

感謝您的幫助,但我想改變序列化程序的全部理由是,我不會多次通過響應對象進行反射。您的解決方案仍然需要。不過,我喜歡你創建自定義屬性的想法。我將擁有一些不是許可權限的屬性,我可以用屬性裝飾這些屬性。 –