ServiceStack support for conditionally omitting fields from a REST response on a per-call basis

后端 未结 2 927
后悔当初
后悔当初 2021-02-06 13:34

At a minimum, I\'m looking for a way to conditionally exclude certain properties on the resource from being included in the r

2条回答
  •  忘了有多久
    2021-02-06 14:28

    So...in my opinion ServiceStack's best feature is that it makes sending, receiving and handling POCOs over HTTP super easy. How you set up the POCOs and what you do in between (within the 'Service') is up to you. Does SS have opinions? Yes. Do you have to agree with them? No. (But you probably should :))

    I think expanding on something like below would get you close to how you want to handle your api. Probably not the best example of ServiceStack but the ServiceStack code/requirements are barely noticeable and don't get in your way (AppHost configure not shown). You could probably do something similar in other .NET Frameworks (MVC/Web API/etc) but, in my opinion, won't look as much like straight C#/.NET code as with ServiceStack.

    Request classes

    [Route("/Profiles/{Id}")]
    public class Profiles
    {
        public int? Id { get; set; }
    }
    
    [Route("/SocialNetworks/{Id}")]
    public class SocialNetworks
    {
        public int? Id { get; set; }
    }
    

    Base Response class

    public class BaseResponse
    {
        protected virtual string hrefPath
        {
            get { return ""; }
        }
    
        public string Id { get; set; }
        public string href { get { return hrefPath + Id; } }
    }
    

    Classes from example

    public class Profile : BaseResponse
    {
        protected override string hrefPath { get { return "https://host/profiles/"; } }
    
        public string GivenName { get; set; }
        public string SurName { get; set; }
        public string Gender { get; set; }
        public string FavColor { get; set; }
    
        public List SocialNetworks { get; set; }
    }
    
    public class SocialNetwork: BaseResponse
    {
        protected override string hrefPath { get { return "https://host/socialNetworkMemberships?profileId="; }}
    
        public string SiteName { get; set; }
        public string ProfileUrl { get; set; }
    }
    

    Services

    public class ProfileService : Service
    {
        public object Get(Profiles request)
        {
            var testProfile = new Profile { Id= "123", GivenName = "Bob", SurName = "Smith", Gender = "Male", FavColor = "Red", 
                    SocialNetworks = new List
                        {
                            new SocialNetwork { Id = "abcde", SiteName = "Facebook", ProfileUrl = "http://www.facebook.com/"}
                        }
            };
    
            if (!String.IsNullOrEmpty(this.Request.QueryString.Get("fields")) || !String.IsNullOrEmpty(this.Request.QueryString.Get("expand")))
                return ServiceHelper.BuildResponseObject(testProfile, this.Request.QueryString);
    
            return testProfile;
        }
    }
    
    public class SocialNetworkService : Service
    {
        public object Get(SocialNetworks request)
        {
            var testSocialNetwork = new SocialNetwork
                {
                    Id = "abcde",
                    SiteName = "Facebook",
                    ProfileUrl = "http://www.facebook.com/"
                };
    
            if (!String.IsNullOrEmpty(this.Request.QueryString.Get("fields")) || !String.IsNullOrEmpty(this.Request.QueryString.Get("expand")))
                return ServiceHelper.BuildResponseObject(testSocialNetwork, this.Request.QueryString);
    
            return testSocialNetwork;
        }
    }
    

    Reflection Helper Class

    public static class ServiceHelper
    {
        public static object BuildResponseObject(T typedObject, NameValueCollection queryString) where T: BaseResponse
        {
            var newObject = new ExpandoObject() as IDictionary;
            newObject.Add("href", typedObject.href);
    
            if (!String.IsNullOrEmpty(queryString.Get("fields")))
            {
                foreach (var propertyName in queryString.Get("fields").Split(',').ToList())
                {
                    //could check for 'socialNetwork' and exclude if you wanted
                    newObject.Add(propertyName, typedObject.GetType().GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(typedObject, null));
                }
            }
    
            if (!String.IsNullOrEmpty(queryString.Get("expand")))
            {
                foreach (var propertyName in queryString.Get("expand").Split(',').ToList())
                {
                    newObject.Add(propertyName, typedObject.GetType().GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(typedObject, null));
                }
            }
    
            return newObject;
        }
    }
    

提交回复
热议问题