Skip to content

Instantly share code, notes, and snippets.

@joaopgrassi
Last active October 24, 2018 07:24
Show Gist options
  • Save joaopgrassi/a0b113699f809847839f3c52d9f81a01 to your computer and use it in GitHub Desktop.
Save joaopgrassi/a0b113699f809847839f3c52d9f81a01 to your computer and use it in GitHub Desktop.
A sample of a controller action receiving an "expand" query parameter that enable returning detailed data
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace WebApplication2.Controllers
{
[Route("api/entities")]
public class ExpandableController : ApiController
{
[HttpGet]
public IHttpActionResult Get([FromUri] string expand = null)
{
var entity = new Entity
{
Id = 1,
Name = "John Doe",
};
if (!string.IsNullOrWhiteSpace(expand))
{
var expandedRequest = expand.Split(',');
(bool valid, IEnumerable<string> properties) = ParseExpandedPropertiesRequest(expandedRequest, Entity.GetExpandables());
if (!valid)
{
// return conflict with some data indicating which properties are wrong..
// https://httpstatuses.com/409
return Conflict();
}
// we have the properties we want to expand.. now just need to pass them and change the queries accordingly.
}
return Ok(entity);
}
/// <summary>
/// Validates and parses the properties the caller wants to "expand"
/// </summary>
/// <param name="requestedPropertiesToExpand"></param>
/// <param name="expandables"></param>
/// <returns></returns>
private (bool valid, IEnumerable<string> properties) ParseExpandedPropertiesRequest(
string[] requestedPropertiesToExpand,
IEnumerable<string> expandables)
{
if (!requestedPropertiesToExpand.Any())
return (false, Enumerable.Empty<string>());
var loweredRequestedProperties = requestedPropertiesToExpand.Select(p => p.ToLower()).ToList();
var allowedExpandableProperties = expandables.Select(p => p.ToLower()).ToList();
if (!loweredRequestedProperties.All(p => allowedExpandableProperties.Contains(p)))
return (false, Enumerable.Empty<string>());
// extract the "diff", returning only the properties requested by the caller
var requestedExpanded = allowedExpandableProperties.Where(x => loweredRequestedProperties.Contains(x)).Select(p => p);
return (true, requestedExpanded);
}
}
public sealed class Entity
{
public int Id { get; set; }
public string Name { get; set; }
public string Measurements { get; set; }
public string Logs { get; set; }
public string OtherProperty { get; set; }
public IEnumerable<string> Expandables => GetExpandables();
/// <summary>
/// All classes that we want to provide the "expand" functionality
/// needs to implement this static method
/// </summary>
/// <see href="https://developer.atlassian.com/server/confluence/expansions-in-the-rest-api/"/>
/// <returns></returns>
internal static IEnumerable<string> GetExpandables()
{
return new[]
{
nameof(Measurements),
nameof(Logs),
nameof(OtherProperty)
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment