Skip to content

CarterCommunity/Carter.SirenNegotiator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Carter.SirenNegotiator

Build status NuGet

Carter.SirenNegotiator adds content negotiation for Siren requests to your Carter API.

Installation

Packaage Manager

PM> Install-Package Carter.SirenNegotiator

.Net CLI

$ dotnet add package Carter.SirenNegotiator

Usage

Taken from the sample project.

Create a Response Generator

public class ActorResponseGenerator : ISirenResponseGenerator
{
    public bool CanHandle(Type type)
    {
        var listType = typeof(IEnumerable<Actor>);
        var classType = typeof(Actor);
        return classType.IsAssignableFrom(type) || listType.IsAssignableFrom(type);
    }

    public Siren Generate(object data, Uri uri)
    {
        return data is IEnumerable<Actor> 
            ? Generate((IEnumerable<Actor>) data, uri) 
            : Generate((Actor) data, uri);
    }

    private Siren Generate(IEnumerable<Actor> actors, Uri uri)
    {
        var doc = new Siren
        {
            @class = new [] { "collection" },
            entities = new List<Entity>(),
            properties = new { Count = actors.Count() }
        };

        foreach (var actor in actors)
        {
            var entity = new Entity
            {
                @class = new [] { nameof(Actor) },
                rel = new [] { "item" },
                properties = actor,
                links = new List<Link> { new Link { href = uri + "/" + actor.Id, rel = new [] { "self" } } }
            };

            doc.entities.Add (entity);
        }

        doc.actions = new List<Action> (new []{

            new Action
            {
                name = "create-actor",
                title = "Create Actor",
                method = "POST",
                href = uri.ToString(),
                type = "application/json",
                fields = new List<Field>(new[] {new Field {name = "name", type = "text"}, new Field{name = "age", type = "number"}})
            }
        });

        doc.links = new List<Link> { new Link { href = uri.ToString(), rel = new [] { "self" } } };

        return doc;
    }
    
    private Siren Generate(Actor actor, Uri uri)
    {
        return new Siren
        {
            @class = new [] { nameof(Actor) },
            properties = actor,
            links = new List<Link> { new Link { href = uri.ToString(), rel = new [] { "self" } } },
            actions = new List<Action> (new []{
                new Action
                {
                    name = "update-actor",
                    title = "Update Actor",
                    method = "PUT",
                    href = uri.ToString(),
                    type = "application/json",
                    fields = new List<Field>(new[] {new Field {name = "name", type = "text"}, new Field{name = "age", type = "number"}})
                },
                new Action
                {
                    name = "delete-actor",
                    title = "Delete Actor",
                    method = "DELETE",
                    href = uri.ToString()
                }
            })
        };
    }
}

This respose generator can handle a list of actors IList<Actor> or a single Actor.

Register Your Response Generator

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IActorProvider, ActorProvider>();
    services.AddScoped<ISirenResponseGenerator, ActorResponseGenerator>();
    
    services.AddCarter();
}

Create Your Module

public class ActorsModule : CarterModule
{
    public ActorsModule(IActorProvider actorProvider)
    {
        Get("/actors/{id:int}", async (req, res, routeData) =>
        {
            try
            {
                var person = actorProvider.Get(routeData.As<int>("id"));
                await res.Negotiate(person);
            }
            catch (InvalidOperationException)
            {
                res.StatusCode = 404;
            }
        });
    }
}

Send a Request

$ curl -H "Accept: application/vnd.siren+json" http://localhost:5000/actors/1
{
  "class": [
    "Actor"
  ],
  "properties": {
    "Name": "Brad Pitt",
    "Id": 1,
    "Age": 51
  },
  "actions": [
    {
      "name": "update-actor",
      "title": "Update Actor",
      "method": "PUT",
      "href": "http://localhost:5000/actors/1",
      "type": "application/json",
      "fields": [
        {
          "name": "name",
          "type": "text"
        },
        {
          "name": "age",
          "type": "number"
        }
      ]
    },
    {
      "name": "delete-actor",
      "title": "Delete Actor",
      "method": "DELETE",
      "href": "http://localhost:5000/actors/1"
    }
  ],
  "links": [
    {
      "rel": [
        "self"
      ],
      "href": "http://localhost:5000/actors/1"
    }
  ]
}

Contributing

Carter.SirenNegotiator is a community project. We invite your participation through issues and pull requests!

License

Carter.SirenNegotiator is licensed under MIT. Refer to LICENSE for more information.

Releases

No releases published

Packages

No packages published

Languages