Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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 :))</p> <p>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. </p> <p><strong>Request classes</strong> </p> <pre><code>[Route("/Profiles/{Id}")] public class Profiles { public int? Id { get; set; } } [Route("/SocialNetworks/{Id}")] public class SocialNetworks { public int? Id { get; set; } } </code></pre> <p><strong>Base Response class</strong></p> <pre><code>public class BaseResponse { protected virtual string hrefPath { get { return ""; } } public string Id { get; set; } public string href { get { return hrefPath + Id; } } } </code></pre> <p><strong>Classes from example</strong> </p> <pre><code>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&lt;BaseResponse&gt; 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; } } </code></pre> <p><strong>Services</strong></p> <pre><code>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&lt;BaseResponse&gt; { 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&lt;Profile&gt;(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&lt;SocialNetwork&gt;(testSocialNetwork, this.Request.QueryString); return testSocialNetwork; } } </code></pre> <p><strong>Reflection Helper Class</strong></p> <pre><code>public static class ServiceHelper { public static object BuildResponseObject&lt;T&gt;(T typedObject, NameValueCollection queryString) where T: BaseResponse { var newObject = new ExpandoObject() as IDictionary&lt;string, object&gt;; 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; } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload