The .NET server implementation of the {json:api} standard running on .NET Core 1.0 (aka ASP.NET 5, MVC 6, DNX/vNext/OWIN) and .NET 4.5.2 MVC 5.
This library is not a complete implementation of the JSONApi 1.0.
NJsonApiCore supports .NET 4.6.2 and .NET Core 1.0.
Originally courtesy of SocialCee, forked NJsonApi from the work done by https://github.com/jacek-gorgon/NJsonApi and then formed into its own repository courtesy of My Clinical Outcomes.
For your ASP.NET 4.5.2/MVC 5 project, install using nuget:
Install-Package NJsonApiCore
You need to tell NJsonApiCore which controllers serve which resources. Create a satic C# class with a single method that returns NJsonApi.IConfiguration
. The method will build up your resource configuration using a fluid API:
public static class MyNJsonApiConfiguration {
public static IConfiguration Build()
{
var configBuilder = new ConfigurationBuilder();
configBuilder
.Resource<MyResource, MyResourceController>()
.WithAllProperties();
return configBuilder.Build();
}
}
For .NET 4.6.2, see the MVC5 HelloWorld project for an example.
For .NET Core, see the MVC Core HelloWorld project for an example
If you are using ASP.NET 4.6.2/MVC5 then you need to update your Application_Start()
method in Global.asax.cs. The bare minimum you will need is:
protected void Application_Start()
{
// Setup the dependency injection container
var container = new UnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// Remove the generic XML formatter
GlobalConfiguration.Configuration.Formatters.Clear();
// Register the routes
GlobalConfiguration.Configure(WebApiConfig.Register);
// Build your NJsonApi configuration and pass it into the JsonApiAppStart configure method
var jsonApiConfiguration = MyNJsonApiConfiguration.Build();
JsonApiAppStart.Configure(GlobalConfiguration.Configuration, container, jsonApiConfiguration);
}
If you are using ASP.NET Core 1.0 then you need to update your Startup.cs
class in two places.
public Startup(IHostingEnvironment env)
{
var builder = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
var nJsonApiConfig = NJsonApiConfiguration.BuildConfiguration();
services.AddMvc(
options =>
{
options.Conventions.Add(new ApiExplorerVisibilityEnabledConvention());
options.Filters.Add(typeof(JsonApiActionFilter));
options.Filters.Add(typeof(JsonApiExceptionFilter));
options.OutputFormatters.Insert(0, new JsonApiOutputFormatter(nJsonApiConfig));
});
services.AddSingleton<ILinkBuilder, LinkBuilder>();
services.AddSingleton(nJsonApiConfig.GetJsonSerializer());
services.AddSingleton<IJsonApiTransformer, JsonApiTransformer >();
services.AddSingleton(nJsonApiConfig);
services.AddSingleton<TransformationHelper>();
}
There are two example projects in this repository, one for API.NET 4.5.2/MVC 5 and one for .NET Core. A solution file is included for each.
Load the NJsonApiCore.Web.MVC5.HelloWorld solution and run the HelloWorld project. It runs under IISExpress. You can then send requests to the NJsonApi using a REST client, such as Postman.
The example HelloWorld projects both implement the entities found on the JSONApi homepage.
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public List<Person> Author { get; set; }
public List<Comment> Comments { get; set}
}
public class Person
{
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Twitter { get; set; }
}
public class Comment
{
public int Id { get; set; }
public string Body { get; set; }
}
A GET request to http://localhost:5000/articles/1?include=comments.people
gives the compound document:
{
"data": {
"id": "1",
"type": "articles",
"attributes": {
"title": "JSON API paints my bikeshed!"
},
"relationships": {
"author": {
"links": {
"self": "http://localhost:5000/articles/1/relationships/author",
"related": "http://localhost:5000/articles/1/author"
},
"data": {
"id": "3",
"type": "people"
}
},
"comments": {
"links": {
"self": "http://localhost:5000/articles/1/relationships/comments",
"related": "http://localhost:5000/articles/1/comments"
},
"data": [
{
"id": "5",
"type": "comments"
},
{
"id": "6",
"type": "comments"
}
],
"meta": {
"count": "2"
}
}
},
"links": {
"self": "http://localhost:5000/articles/1"
}
},
"links": {
"self": "http://localhost:5000/articles/1?include=comments.people"
},
"included": [
{
"id": "3",
"type": "people",
"attributes": {
"firstName": "Dan",
"lastName": "Gebhardt",
"twitter": "dgeb"
},
"links": {
"self": "http://localhost:5000/people/3"
}
},
{
"id": "5",
"type": "comments",
"attributes": {
"body": "First!"
},
"relationships": {
"author": {
"links": {
"self": "http://localhost:5000/comments/5/relationships/author",
"related": "http://localhost:5000/comments/5/author"
},
"data": {
"id": "3",
"type": "people"
}
}
},
"links": {
"self": "http://localhost:5000/comments/5"
}
},
{
"id": "6",
"type": "comments",
"attributes": {
"body": "I like XML Better"
},
"relationships": {
"author": {
"links": {
"self": "http://localhost:5000/comments/6/relationships/author",
"related": "http://localhost:5000/comments/6/author"
},
"data": {
"id": "4",
"type": "people"
}
}
},
"links": {
"self": "http://localhost:5000/comments/6"
}
},
{
"id": "4",
"type": "people",
"attributes": {
"firstName": "Rob",
"lastName": "Lang",
"twitter": "brainwipe"
},
"links": {
"self": "http://localhost:5000/people/4"
}
}
],
"jsonapi": {
"Version": "1.0"
}
}