Skip to content

Commit

Permalink
Merge pull request #38 from Research-Institute/meta-objects
Browse files Browse the repository at this point in the history
Meta objects
  • Loading branch information
jaredcnance authored Feb 25, 2017
2 parents 605e039 + 456d65c commit 989b862
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 22 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ JsonApiDotnetCore provides a framework for building [json:api](http://jsonapi.or
- [Pagination](#pagination)
- [Filtering](#filtering)
- [Sorting](#sorting)
- [Meta](#meta)
- [Tests](#tests)

## Installation
Expand Down Expand Up @@ -240,6 +241,18 @@ when setting up the services:
opt => opt.DefaultPageSize = 10);
```

**Total Record Count**

The total number of records can be added to the document meta by setting it in the options:

```
services.AddJsonApi<AppDbContext>(opt =>
{
opt.DefaultPageSize = 5;
opt.IncludeTotalRecordCount = true;
});
```

### Filtering

You can filter resources by attributes using the `filter` query parameter.
Expand Down Expand Up @@ -270,6 +283,25 @@ Resources can be sorted by an attribute:
?sort=-attribute // descending
```

### Meta

Resource meta can be defined by implementing `IHasMeta` on the model class:

```
public class Person : Identifiable<int>, IHasMeta
{
// ...
public Dictionary<string, object> GetMeta(IJsonApiContext context)
{
return new Dictionary<string, object> {
{ "copyright", "Copyright 2015 Example Corp." },
{ "authors", new string[] { "Jared Nance" } }
};
}
}
```

## Tests

I am using DotNetCoreDocs to generate sample requests and documentation.
Expand Down
24 changes: 22 additions & 2 deletions src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using JsonApiDotNetCore.Extensions;
using JsonApiDotNetCore.Internal;
using JsonApiDotNetCore.Models;
Expand All @@ -24,7 +25,8 @@ public Document Build(IIdentifiable entity)

var document = new Document
{
Data = _getData(contextEntity, entity)
Data = _getData(contextEntity, entity),
Meta = _getMeta(entity)
};

document.Included = _appendIncludedObject(document.Included, contextEntity, entity);
Expand All @@ -42,7 +44,8 @@ public Documents Build(IEnumerable<IIdentifiable> entities)

var documents = new Documents
{
Data = new List<DocumentData>()
Data = new List<DocumentData>(),
Meta = _getMeta(entities.FirstOrDefault())
};

foreach (var entity in entities)
Expand All @@ -54,6 +57,23 @@ public Documents Build(IEnumerable<IIdentifiable> entities)
return documents;
}

private Dictionary<string, object> _getMeta(IIdentifiable entity)
{
if (entity == null) return null;

var meta = new Dictionary<string, object>();
var metaEntity = entity as IHasMeta;

if(metaEntity != null)
meta = metaEntity.GetMeta(_jsonApiContext);

if(_jsonApiContext.Options.IncludeTotalRecordCount)
meta["total-records"] = _jsonApiContext.TotalRecords;

if(meta.Count > 0) return meta;
return null;
}

private List<DocumentData> _appendIncludedObject(List<DocumentData> includedObject, ContextEntity contextEntity, IIdentifiable entity)
{
var includedEntities = _getIncludedEntities(contextEntity, entity);
Expand Down
1 change: 1 addition & 0 deletions src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ public class JsonApiOptions
{
public string Namespace { get; set; }
public int DefaultPageSize { get; set; }
public bool IncludeTotalRecordCount { get; set; }
}
}
3 changes: 3 additions & 0 deletions src/JsonApiDotNetCore/Controllers/JsonApiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ public virtual async Task<IActionResult> GetAsync()
if (_jsonApiContext.QuerySet != null && _jsonApiContext.QuerySet.IncludedRelationships != null && _jsonApiContext.QuerySet.IncludedRelationships.Count > 0)
entities = IncludeRelationships(entities, _jsonApiContext.QuerySet.IncludedRelationships);

if (_jsonApiContext.Options.IncludeTotalRecordCount)
_jsonApiContext.TotalRecords = await entities.CountAsync();

// pagination should be done last since it will execute the query
var pagedEntities = await ApplyPageQueryAsync(entities);

Expand Down
6 changes: 1 addition & 5 deletions src/JsonApiDotNetCore/Models/Document.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
using System.Collections.Generic;
using Newtonsoft.Json;

namespace JsonApiDotNetCore.Models
{
public class Document
public class Document : DocumentBase
{
[JsonProperty("data")]
public DocumentData Data { get; set; }

[JsonProperty("included")]
public List<DocumentData> Included { get; set; }
}
}
12 changes: 12 additions & 0 deletions src/JsonApiDotNetCore/Models/DocumentBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Collections.Generic;
using Newtonsoft.Json;

namespace JsonApiDotNetCore.Models
{
public class DocumentBase
{
[JsonProperty("included")]
public List<DocumentData> Included { get; set; }
public Dictionary<string, object> Meta { get; set; }
}
}
5 changes: 1 addition & 4 deletions src/JsonApiDotNetCore/Models/Documents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@

namespace JsonApiDotNetCore.Models
{
public class Documents
public class Documents : DocumentBase
{
[JsonProperty("data")]
public List<DocumentData> Data { get; set; }

[JsonProperty("included")]
public List<DocumentData> Included { get; set; }
}
}
10 changes: 10 additions & 0 deletions src/JsonApiDotNetCore/Models/IHasMeta.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Collections.Generic;
using JsonApiDotNetCore.Services;

namespace JsonApiDotNetCore.Models
{
public interface IHasMeta
{
Dictionary<string, object> GetMeta(IJsonApiContext context);
}
}
1 change: 1 addition & 0 deletions src/JsonApiDotNetCore/Services/IJsonApiContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ public interface IJsonApiContext
QuerySet QuerySet { get; set; }
bool IsRelationshipData { get; set; }
List<string> IncludedRelationships { get; set; }
int TotalRecords { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/JsonApiDotNetCore/Services/JsonApiContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ public JsonApiContext(
_httpContextAccessor = httpContextAccessor;
Options = options;
}

public JsonApiOptions Options { get; set; }
public IContextGraph ContextGraph { get; set; }
public ContextEntity RequestEntity { get; set; }
public string BasePath { get; set; }
public QuerySet QuerySet { get; set; }
public bool IsRelationshipData { get; set; }
public List<string> IncludedRelationships { get; set; }
public int TotalRecords { get; set; }

public IJsonApiContext ApplyContext<T>()
{
Expand Down
2 changes: 1 addition & 1 deletion src/JsonApiDotNetCore/project.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.2.11",
"version": "0.2.12",

"dependencies": {
"Microsoft.NETCore.App": {
Expand Down
11 changes: 10 additions & 1 deletion src/JsonApiDotNetCoreExample/Models/Person.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.Collections.Generic;
using JsonApiDotNetCore.Internal;
using JsonApiDotNetCore.Models;
using JsonApiDotNetCore.Services;

namespace JsonApiDotNetCoreExample.Models
{
public class Person : Identifiable<int>
public class Person : Identifiable<int>, IHasMeta
{
public override int Id { get; set; }

Expand All @@ -15,5 +16,13 @@ public class Person : Identifiable<int>
public string LastName { get; set; }

public virtual List<TodoItem> TodoItems { get; set; }

public Dictionary<string, object> GetMeta(IJsonApiContext context)
{
return new Dictionary<string, object> {
{ "copyright", "Copyright 2015 Example Corp." },
{ "authors", new string[] { "Jared Nance" } }
};
}
}
}
18 changes: 9 additions & 9 deletions src/JsonApiDotNetCoreExample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace JsonApiDotNetCoreExample
{
public class Startup
{
private readonly IConfiguration _config;
public readonly IConfiguration Config;

public Startup(IHostingEnvironment env)
{
Expand All @@ -25,10 +25,10 @@ public Startup(IHostingEnvironment env)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();

_config = builder.Build();
Config = builder.Build();
}

public IServiceProvider ConfigureServices(IServiceCollection services)
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
{
var loggerFactory = new LoggerFactory();
loggerFactory
Expand All @@ -37,7 +37,7 @@ public IServiceProvider ConfigureServices(IServiceCollection services)

services.AddDbContext<AppDbContext>(options =>
{
options.UseNpgsql(_getDbConnectionString());
options.UseNpgsql(GetDbConnectionString());
}, ServiceLifetime.Transient);

services.AddJsonApi<AppDbContext>(opt =>
Expand All @@ -46,7 +46,7 @@ public IServiceProvider ConfigureServices(IServiceCollection services)
opt.DefaultPageSize = 5;
});

services.AddDocumentationConfiguration(_config);
services.AddDocumentationConfiguration(Config);

var provider = services.BuildServiceProvider();
var appContext = provider.GetRequiredService<AppDbContext>();
Expand All @@ -55,25 +55,25 @@ public IServiceProvider ConfigureServices(IServiceCollection services)
return provider;
}

public void Configure(
public virtual void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
AppDbContext context)
{
context.Database.Migrate();

loggerFactory.AddConsole(_config.GetSection("Logging"));
loggerFactory.AddConsole(Config.GetSection("Logging"));
loggerFactory.AddDebug();

app.UseDocs();

app.UseJsonApi();
}

private string _getDbConnectionString()
public string GetDbConnectionString()
{
return _config["Data:DefaultConnection"];
return Config["Data:DefaultConnection"];
}
}
}
Loading

0 comments on commit 989b862

Please sign in to comment.