Skip to content

v2.0.0 #94

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 54 commits into from
May 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
4ed46c8
feat(services): define IResourceService
jaredcnance Apr 8, 2017
fa9364f
refactor(controller): move bulk of logic into the resource service
jaredcnance Apr 8, 2017
b62227d
feat(service-collection-ext): add new service
jaredcnance Apr 8, 2017
6d6c3e4
chore(example-controllers): update for new JsonApiController ctor
jaredcnance Apr 8, 2017
e17cad2
docs(readme): stub out documentation updates
jaredcnance Apr 8, 2017
550e00a
feat(context-graph): first pass at refactoring the graph API
jaredcnance Apr 12, 2017
ba4719d
fix(IContextGraphBuilder): expose the AddDbContext method
jaredcnance Apr 13, 2017
b89b18f
refactor(service-collection-ext): prevent breaking changes
jaredcnance Apr 13, 2017
4b859a3
hack(service-collection-ext): inject bogus dbContext types for DI
jaredcnance Apr 13, 2017
8457b22
example: add "no entity framework" example
jaredcnance Apr 13, 2017
99e8b4d
test(extensibility): add initial test around fetching non-ef data
jaredcnance Apr 13, 2017
194d31d
Merge remote-tracking branch 'origin/develop' into feat/decouple-dal
jaredcnance Apr 13, 2017
09cc32a
example(no-ef): rename models, controllers seem to cause conflict
jaredcnance Apr 13, 2017
7c20d77
refactor(context-graph): the stored entity name should be dasherized …
jaredcnance Apr 14, 2017
2fd9eb3
test(no-ef): validate the response body
jaredcnance Apr 14, 2017
94e5dee
docs(readme): document custom data implementation
jaredcnance Apr 14, 2017
e6ba54f
docs(readme): document custom context mapping
jaredcnance Apr 14, 2017
0264ea8
docs(readme): document new controller constructor
jaredcnance Apr 14, 2017
84cf741
feat(example): use Dapper and Npgsql in NoEF example
jaredcnance Apr 18, 2017
93edba5
test(acceptance/no-ef): ensure the database is created
jaredcnance Apr 18, 2017
2c164fa
test(acceptance/no-ef): ensure database is migrated
jaredcnance Apr 18, 2017
edc4626
fix(example/startups): try using EnsureCreated to fix travis-ci build
jaredcnance Apr 18, 2017
7c14d49
refactor(tests): split test projects
jaredcnance Apr 18, 2017
36b55d8
fix(ci): restore new test project
jaredcnance Apr 19, 2017
62183f3
chore(example): remove build files from source control
jaredcnance Apr 19, 2017
629169f
chore(csproj): bump package major version
jaredcnance Apr 19, 2017
fd5e04a
feat(context-graph-builder): intro resource attr
jaredcnance Apr 19, 2017
b0146c4
refactor(*): further reduction of Dasherize usage
jaredcnance Apr 19, 2017
75ae1b5
docs(readme): show ResourceAttribute usage
jaredcnance Apr 19, 2017
3d95c01
fix(de-serializer): do not dasherize a public name
jaredcnance Apr 19, 2017
7cff6d0
test(no-ef): additional tests / examples
jaredcnance Apr 19, 2017
517367b
fix(example): missing attribute
jaredcnance Apr 19, 2017
aec7e1c
test(extensibility): add tests for dasherized routes for inherited an…
JanMattner Apr 20, 2017
4480e6b
fix(link-builder): do not dasherize routes by default
jaredcnance Apr 21, 2017
1de23d8
test(extensibility): fix/remove failing tests
jaredcnance Apr 25, 2017
8d134f3
chore(csproj): add package information
jaredcnance Apr 25, 2017
d4cb99d
Merge pull request #89 from Research-Institute/feat/decouple-dal
jaredcnance Apr 25, 2017
b1ecb9a
Allow PATCH objects with nullable attribute (e.g. DateTime?)
Apr 25, 2017
244b91f
Merge branch 'develop' into patch-nullable-attributes
jaredcnance Apr 25, 2017
38f4818
refactor(serialization): use TypeHelper.ConvertType
Apr 26, 2017
aeb41af
fix(format): convert tabs to spaces
Apr 26, 2017
d89dd23
refactor(type-helper): remove reflection dep and simplify null check
jaredcnance Apr 26, 2017
30e1c0d
Merge pull request #96 from Gerfaut/patch-nullable-attributes
jaredcnance Apr 26, 2017
c5e7a9d
feat(controllers): add attribute to disable the routing convention
jaredcnance Apr 27, 2017
cb11ae3
refactor(routing-convention): respect the disable attribute
jaredcnance Apr 27, 2017
7276ee0
test(disable-rte-convention): add acceptance tests
jaredcnance Apr 27, 2017
d2ef98e
docs(readme): document the new controller attribute
jaredcnance Apr 27, 2017
11450e5
Merge pull request #97 from Research-Institute/fix/#93
jaredcnance Apr 27, 2017
a3e0268
style(*): code cleaning
jaredcnance May 3, 2017
06ec8a7
fix(routing-convention): do not try to infer routing
jaredcnance May 5, 2017
d93c625
docs(readme): document the routing convention details
jaredcnance May 5, 2017
a8f41aa
Merge pull request #98 from Research-Institute/fix/routing-convention
jaredcnance May 5, 2017
a477cf8
docs(readme): remove link to demo
jaredcnance May 6, 2017
66dbdc5
docs(readme): remove generator mention
jaredcnance May 6, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
\.vs/

*.user
50 changes: 48 additions & 2 deletions JsonApiDotnetCore.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
VisualStudioVersion = 15.0.26228.9
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore", "src\JsonApiDotNetCore\JsonApiDotNetCore.csproj", "{C0EC9E70-EB2E-436F-9D94-FA16FA774123}"
EndProject
Expand All @@ -16,26 +15,71 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C5B4D998-CECB-454D-9F32-085A897577BE}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoEntityFrameworkExample", "src\NoEntityFrameworkExample\NoEntityFrameworkExample.csproj", "{570165EC-62B5-4684-A139-8D2A30DD4475}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoEntityFrameworkTests", "test\NoEntityFrameworkTests\NoEntityFrameworkTests.csproj", "{73DA578D-A63F-4956-83ED-6D7102E09140}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C0EC9E70-EB2E-436F-9D94-FA16FA774123}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C0EC9E70-EB2E-436F-9D94-FA16FA774123}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0EC9E70-EB2E-436F-9D94-FA16FA774123}.Debug|x64.ActiveCfg = Debug|Any CPU
{C0EC9E70-EB2E-436F-9D94-FA16FA774123}.Debug|x86.ActiveCfg = Debug|Any CPU
{C0EC9E70-EB2E-436F-9D94-FA16FA774123}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C0EC9E70-EB2E-436F-9D94-FA16FA774123}.Release|Any CPU.Build.0 = Release|Any CPU
{C0EC9E70-EB2E-436F-9D94-FA16FA774123}.Release|x64.ActiveCfg = Release|Any CPU
{C0EC9E70-EB2E-436F-9D94-FA16FA774123}.Release|x86.ActiveCfg = Release|Any CPU
{97EE048B-16C0-43F6-BDA9-4E762B2F579F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{97EE048B-16C0-43F6-BDA9-4E762B2F579F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{97EE048B-16C0-43F6-BDA9-4E762B2F579F}.Debug|x64.ActiveCfg = Debug|Any CPU
{97EE048B-16C0-43F6-BDA9-4E762B2F579F}.Debug|x86.ActiveCfg = Debug|Any CPU
{97EE048B-16C0-43F6-BDA9-4E762B2F579F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{97EE048B-16C0-43F6-BDA9-4E762B2F579F}.Release|Any CPU.Build.0 = Release|Any CPU
{97EE048B-16C0-43F6-BDA9-4E762B2F579F}.Release|x64.ActiveCfg = Release|Any CPU
{97EE048B-16C0-43F6-BDA9-4E762B2F579F}.Release|x86.ActiveCfg = Release|Any CPU
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}.Debug|x64.ActiveCfg = Debug|Any CPU
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}.Debug|x86.ActiveCfg = Debug|Any CPU
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}.Release|Any CPU.Build.0 = Release|Any CPU
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}.Release|x64.ActiveCfg = Release|Any CPU
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}.Release|x86.ActiveCfg = Release|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Debug|Any CPU.Build.0 = Debug|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Debug|x64.ActiveCfg = Debug|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Debug|x64.Build.0 = Debug|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Debug|x86.ActiveCfg = Debug|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Debug|x86.Build.0 = Debug|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Release|Any CPU.ActiveCfg = Release|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Release|Any CPU.Build.0 = Release|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Release|x64.ActiveCfg = Release|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Release|x64.Build.0 = Release|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Release|x86.ActiveCfg = Release|Any CPU
{570165EC-62B5-4684-A139-8D2A30DD4475}.Release|x86.Build.0 = Release|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Debug|x64.ActiveCfg = Debug|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Debug|x64.Build.0 = Debug|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Debug|x86.ActiveCfg = Debug|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Debug|x86.Build.0 = Debug|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Release|Any CPU.Build.0 = Release|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Release|x64.ActiveCfg = Release|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Release|x64.Build.0 = Release|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Release|x86.ActiveCfg = Release|Any CPU
{73DA578D-A63F-4956-83ED-6D7102E09140}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -44,5 +88,7 @@ Global
{C0EC9E70-EB2E-436F-9D94-FA16FA774123} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
{97EE048B-16C0-43F6-BDA9-4E762B2F579F} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
{570165EC-62B5-4684-A139-8D2A30DD4475} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
{73DA578D-A63F-4956-83ED-6D7102E09140} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
EndGlobalSection
EndGlobal
146 changes: 122 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@
JsonApiDotnetCore provides a framework for building [json:api](http://jsonapi.org/) compliant web servers. Unlike other .Net implementations, this library provides all the required middleware to build a complete server. All you need to focus on is defining the resources. However, the library is also fully extensible so you can customize the implementation to meet your specific needs.

# Table Of Contents
- [Comprehensive Demo](#comprehensive-demo)
- [Installation](#installation)
- [Generators](#generators)
- [Usage](#usage)
- [Middleware and Services](#middleware-and-services)
- [Defining Models](#defining-models)
- [Specifying Public Attributes](#specifying-public-attributes)
- [Relationships](#relationships)
- [Resource Names](#resource-names)
- [Defining Controllers](#defining-controllers)
- [Non-Integer Type Keys](#non-integer-type-keys)
- [Routing](#routing)
- [Namespacing and Versioning URLs](#namespacing-and-versioning-urls)
- [Disable Convention](#disable-convention)
- [Defining Custom Data Access Methods](#defining-custom-data-access-methods)
- [Pagination](#pagination)
- [Filtering](#filtering)
Expand All @@ -32,12 +32,6 @@ JsonApiDotnetCore provides a framework for building [json:api](http://jsonapi.or
- [Sparse Fieldsets](#sparse-fieldsets)
- [Tests](#tests)

## Comprehensive Demo

The following is a WIP demo showing how to create a web application using this library, EmberJS and PostgreSQL. If there are specific topics you'd like to see in future videos, comment on the playlist.

[![Goto Playlist](https://img.youtube.com/vi/KAMuo6K7VcE/0.jpg)](https://www.youtube.com/watch?v=KAMuo6K7VcE&list=PLu4Bq53iqJJAo1RF0TY4Q5qCG7n9AqSZf)

## Installation

- Visual Studio
Expand All @@ -47,14 +41,14 @@ Install-Package JsonApiDotnetCore

- project.json
```json
"JsonApiDotNetCore": "1.3.0"
"JsonApiDotNetCore": "2.0.0"
```

- *.csproj
```xml
<ItemGroup>
<!-- ... -->
<PackageReference Include="JsonApiDotNetCore" Version="1.3.0" />
<PackageReference Include="JsonApiDotNetCore" Version="2.0.0" />
</ItemGroup>
```

Expand All @@ -64,22 +58,14 @@ For pre-releases, add the [MyGet](https://www.myget.org/feed/Details/research-in
(https://www.myget.org/F/research-institute/api/v3/index.json)
to your nuget configuration.

## Generators

You can install the [Yeoman generators](https://github.com/Research-Institute/json-api-dotnet-core-generators)
to make building applications much easier.

## Usage

You need to do 3 things:
The most basic use case requires 3 things:

- Add Middleware and Services
- Define Models
- Define Controllers

I recommend reading the details below, but once you're familiar with the
setup, you can use the Yeoman generator to generate the required classes.

### Middleware and Services

Add the following to your `Startup.ConfigureServices` method.
Expand Down Expand Up @@ -169,6 +155,23 @@ public class TodoItem : Identifiable<int>
}
```

#### Resource Names

If a DbContext is specified when adding the services, the context will be used to define the resources and their names.

```csharp
public DbSet<MyModel> SomeModels { get; set; } // this will be translated into "some-models"
```

However, you can specify a custom name like so:

```csharp
[Resource("some-models")]
public DbSet<MyModel> MyModels { get; set; } // this will be translated into "some-models"
```

For further resource customizations, please see the section on [Defining Custom Data Access Methods](#defining-custom-data-access-methods).

### Defining Controllers

You need to create controllers that inherit from `JsonApiController<TEntity>` or `JsonApiController<TEntity, TId>`
Expand All @@ -180,9 +183,9 @@ public class ThingsController : JsonApiController<Thing>
{
public ThingsController(
IJsonApiContext jsonApiContext,
IEntityRepository<Thing> entityRepository,
IResourceService<Thing> resourceService,
ILoggerFactory loggerFactory)
: base(jsonApiContext, entityRepository, loggerFactory)
: base(jsonApiContext, resourceService, loggerFactory)
{ }
}
```
Expand All @@ -199,9 +202,9 @@ public class ThingsController : JsonApiController<Thing, Guid>
{
public ThingsController(
IJsonApiContext jsonApiContext,
IEntityRepository<Thing, Guid> entityRepository,
IResourceService<Thing, Guid> resourceService,
ILoggerFactory loggerFactory)
: base(jsonApiContext, entityRepository, loggerFactory)
: base(jsonApiContext, resourceService, loggerFactory)
{ }
}
```
Expand All @@ -226,9 +229,104 @@ services.AddJsonApi<AppDbContext>(
opt => opt.Namespace = "api/v1");
```

#### Disable Convention

You can disable the dasherized convention and specify your own template
by using the `DisableRoutingConvention` Attribute.

```csharp
[Route("[controller]")]
[DisableRoutingConvention]
public class CamelCasedModelsController : JsonApiController<CamelCasedModel>
{
public CamelCasedModelsController(
IJsonApiContext jsonApiContext,
IResourceService<CamelCasedModel> resourceService,
ILoggerFactory loggerFactory)
: base(jsonApiContext, resourceService, loggerFactory)
{ }
}
```

It is important to note that your routes *must* still end with the model name in the same format
as the resource name. This is so that we can build accurrate resource links in the json:api document.
For example, if you define a resource as `MyModels` the controller route must match:

```csharp
// resource definition
builder.AddResource<TodoItem>("myModels");

// controller definition
[Route("api/myModels")]
[DisableRoutingConvention]
public class TodoItemsController : JsonApiController<TodoItem>
{ //...
}
```

### Defining Custom Data Access Methods

You can implement custom methods for accessing the data by creating an implementation of
By default, data retrieval is distributed across 3 layers:

1. `JsonApiController`
2. `EntityResourceService`
3. `DefaultEntityRepository`

Customization can be done at any of these layers. However, it is recommended that you make your customizations at the service or the repository layer when possible to keep the controllers free of unnecessary logic.

#### Not Using Entity Framework?

Out of the box, the library uses your `DbContext` to create a "ContextGraph" or map of all your models and their relationships. If, however, you have models that are not members of a `DbContext`, you can manually create this graph like so:

```csharp
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
var mvcBuilder = services.AddMvc();

services.AddJsonApi(options => {
options.Namespace = "api/v1";
options.BuildContextGraph((builder) => {
builder.AddResource<MyModel>("my-models");1
});
}, mvcBuilder);
// ...
}
```

#### Custom Resource Service Implementation

By default, this library uses Entity Framework. If you'd like to use another ORM that does not implement `IQueryable`, you can inject a custom service like so:

```csharp
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IResourceService<MyModel>, MyModelService>();
// ...
}
```

```csharp
// MyModelService.cs
public class MyModelService : IResourceService<MyModel>
{
private readonly IMyModelDAL _dal;
public MyModelService(IMyModelDAL dal)
{
_dal = dal;
}
public Task<IEnumerable<MyModel>> GetAsync()
{
return await _dal.GetModelAsync();
}
}
```

#### Custom Entity Repository Implementation

If you want to use EF, but need additional data access logic (such as authorization), you can implement custom methods for accessing the data by creating an implementation of
`IEntityRepository<TEntity, TId>`. If you only need minor changes you can override the
methods defined in `DefaultEntityRepository<TEntity, TId>`. The repository should then be
add to the service collection in `Startup.ConfigureServices` like so:
Expand Down
4 changes: 3 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ set -e
dotnet restore ./src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
dotnet restore ./src/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
dotnet restore ./test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
dotnet restore ./test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj

dotnet test ./test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
dotnet test ./test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
dotnet test ./test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
Loading