Skip to content

Commit

Permalink
Merge pull request #59 from Research-Institute/develop
Browse files Browse the repository at this point in the history
fixes around id types
  • Loading branch information
jaredcnance authored Mar 16, 2017
2 parents 214f7d0 + 3d51f1c commit 8b1c537
Show file tree
Hide file tree
Showing 34 changed files with 588 additions and 449 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
\.vs/
13 changes: 11 additions & 2 deletions Build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,14 @@ $revision = "{0:D4}" -f [convert]::ToInt32($revision, 10)
dotnet restore .\src\JsonApiDotNetCore\JsonApiDotNetCore.csproj
dotnet build .\src\JsonApiDotNetCore -c Release

If($env:APPVEYOR_REPO_TAG) { dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts }
Else { dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision }
echo "APPVEYOR_REPO_TAG: $env:APPVEYOR_REPO_TAG"
echo "VERSION-SUFFIX: alpha1-$revision"

If($env:APPVEYOR_REPO_TAG -eq $true) {
echo "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts "
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts
}
Else {
echo "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision"
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision
}
48 changes: 48 additions & 0 deletions JsonApiDotnetCore.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore", "src\JsonApiDotNetCore\JsonApiDotNetCore.csproj", "{C0EC9E70-EB2E-436F-9D94-FA16FA774123}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCoreExample", "src\JsonApiDotNetCoreExample\JsonApiDotNetCoreExample.csproj", "{97EE048B-16C0-43F6-BDA9-4E762B2F579F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCoreExampleTests", "test\JsonApiDotNetCoreExampleTests\JsonApiDotNetCoreExampleTests.csproj", "{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C5B4D998-CECB-454D-9F32-085A897577BE}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
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}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C0EC9E70-EB2E-436F-9D94-FA16FA774123}.Release|Any CPU.Build.0 = 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}.Release|Any CPU.ActiveCfg = Release|Any CPU
{97EE048B-16C0-43F6-BDA9-4E762B2F579F}.Release|Any CPU.Build.0 = 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}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B959765-40D2-43B5-87EE-FE2FEF9DBED5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{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}
EndGlobalSection
EndGlobal
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ JsonApiDotnetCore provides a framework for building [json:api](http://jsonapi.or
- [Filtering](#filtering)
- [Sorting](#sorting)
- [Meta](#meta)
- [Client Generated Ids](#client-generated-ids)
- [Tests](#tests)

## Comprehensive Demo
Expand Down Expand Up @@ -342,6 +343,20 @@ public class Person : Identifiable<int>, IHasMeta
}
```

### Client Generated Ids

By default, the server will respond with a `403 Forbidden` HTTP Status Code if a `POST` request is
received with a client generated id. However, this can be allowed by setting the `AllowClientGeneratedIds`
flag in the options:

```csharp
services.AddJsonApi<AppDbContext>(opt =>
{
opt.AllowClientGeneratedIds = true;
// ..
});
```

## Tests

I am using DotNetCoreDocs to generate sample requests and documentation.
Expand Down
13 changes: 1 addition & 12 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,8 @@
#exit if any command fails
set -e

artifactsFolder="./artifacts"

if [ -d $artifactsFolder ]; then
rm -R $artifactsFolder
fi

dotnet restore ./src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
dotnet restore ./src/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
dotnet restore ./test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj

dotnet test ./test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj

revision=${TRAVIS_JOB_ID:=1}
revision=$(printf "%04d" $revision)

dotnet pack ./src/JsonApiDotNetCore -c Release -o ./artifacts --version-suffix=$revision
dotnet test ./test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
12 changes: 6 additions & 6 deletions src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ private DocumentData _getData(ContextEntity contextEntity, IIdentifiable entity)
var data = new DocumentData
{
Type = contextEntity.EntityName,
Id = entity.Id.ToString()
Id = entity.StringId
};

if (_jsonApiContext.IsRelationshipData)
Expand Down Expand Up @@ -124,8 +124,8 @@ private void _addRelationships(DocumentData data, ContextEntity contextEntity, I
{
Links = new Links
{
Self = linkBuilder.GetSelfRelationLink(contextEntity.EntityName, entity.Id.ToString(), r.InternalRelationshipName),
Related = linkBuilder.GetRelatedRelationLink(contextEntity.EntityName, entity.Id.ToString(), r.InternalRelationshipName)
Self = linkBuilder.GetSelfRelationLink(contextEntity.EntityName, entity.StringId, r.InternalRelationshipName),
Related = linkBuilder.GetRelatedRelationLink(contextEntity.EntityName, entity.StringId, r.InternalRelationshipName)
}
};
Expand Down Expand Up @@ -175,7 +175,7 @@ private DocumentData _getIncludedEntity(IIdentifiable entity)
var data = new DocumentData
{
Type = contextEntity.EntityName,
Id = entity.Id.ToString()
Id = entity.StringId
};

data.Attributes = new Dictionary<string, object>();
Expand Down Expand Up @@ -205,7 +205,7 @@ private List<Dictionary<string, string>> _getRelationships(IEnumerable<object> e
{
relationships.Add(new Dictionary<string, string> {
{"type", typeName.EntityName.Dasherize() },
{"id", ((IIdentifiable)entity).Id.ToString() }
{"id", ((IIdentifiable)entity).StringId }
});
}
return relationships;
Expand All @@ -218,7 +218,7 @@ private Dictionary<string, string> _getRelationship(object entity, string relati

return new Dictionary<string, string> {
{"type", typeName.EntityName.Dasherize() },
{"id", ((IIdentifiable)entity).Id.ToString() }
{"id", ((IIdentifiable)entity).StringId }
};
}
}
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 @@ -5,5 +5,6 @@ public class JsonApiOptions
public string Namespace { get; set; }
public int DefaultPageSize { get; set; }
public bool IncludeTotalRecordCount { get; set; }
public bool AllowClientGeneratedIds { get; set; }
}
}
29 changes: 14 additions & 15 deletions src/JsonApiDotNetCore/Controllers/JsonApiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace JsonApiDotNetCore.Controllers
{
public class JsonApiController<T>
public class JsonApiController<T>
: JsonApiController<T, int> where T : class, IIdentifiable<int>
{
public JsonApiController(
Expand All @@ -24,7 +24,7 @@ public JsonApiController(
{ }
}

public class JsonApiController<T, TId>
public class JsonApiController<T, TId>
: JsonApiControllerMixin where T : class, IIdentifiable<TId>
{
private readonly IEntityRepository<T, TId> _entities;
Expand Down Expand Up @@ -77,7 +77,7 @@ public virtual async Task<IActionResult> GetAsync()
public virtual async Task<IActionResult> GetAsync(TId id)
{
T entity;
if(_jsonApiContext.QuerySet?.IncludedRelationships != null)
if (_jsonApiContext.QuerySet?.IncludedRelationships != null)
entity = await _getWithRelationshipsAsync(id);
else
entity = await _entities.GetAsync(id);
Expand Down Expand Up @@ -138,8 +138,7 @@ public virtual async Task<IActionResult> PostAsync([FromBody] T entity)
return UnprocessableEntity();
}

var stringId = entity.Id.ToString();
if(stringId.Length > 0 && stringId != "0")
if (!_jsonApiContext.Options.AllowClientGeneratedIds && !string.IsNullOrEmpty(entity.StringId))
return Forbidden();

await _entities.CreateAsync(entity);
Expand All @@ -158,7 +157,7 @@ public virtual async Task<IActionResult> PatchAsync(TId id, [FromBody] T entity)

var updatedEntity = await _entities.UpdateAsync(id, entity);

if(updatedEntity == null) return NotFound();
if (updatedEntity == null) return NotFound();

return Ok(updatedEntity);
}
Expand All @@ -185,12 +184,12 @@ public virtual async Task<IActionResult> PatchRelationshipsAsync(TId id, string
.Relationships
.FirstOrDefault(r => r.InternalRelationshipName == relationshipName);

var relationshipIds = relationships.Select(r=>r.Id);
var relationshipIds = relationships.Select(r => r.Id);

await _entities.UpdateRelationshipsAsync(entity, relationship, relationshipIds);

return Ok();

}

[HttpDelete("{id}")]
Expand All @@ -208,14 +207,14 @@ private IQueryable<T> ApplySortAndFilterQuery(IQueryable<T> entities)
{
var query = _jsonApiContext.QuerySet;

if(_jsonApiContext.QuerySet == null)
if (_jsonApiContext.QuerySet == null)
return entities;

if(query.Filters.Count > 0)
foreach(var filter in query.Filters)
if (query.Filters.Count > 0)
foreach (var filter in query.Filters)
entities = _entities.Filter(entities, filter);

if(query.SortParameters != null && query.SortParameters.Count > 0)
if (query.SortParameters != null && query.SortParameters.Count > 0)
entities = _entities.Sort(entities, query.SortParameters);

return entities;
Expand All @@ -224,7 +223,7 @@ private IQueryable<T> ApplySortAndFilterQuery(IQueryable<T> entities)
private async Task<IEnumerable<T>> ApplyPageQueryAsync(IQueryable<T> entities)
{
var pageManager = _jsonApiContext.PageManager;
if(!pageManager.IsPaginated)
if (!pageManager.IsPaginated)
return entities;

var query = _jsonApiContext.QuerySet?.PageQuery ?? new PageQuery();
Expand All @@ -238,7 +237,7 @@ private IQueryable<T> IncludeRelationships(IQueryable<T> entities, List<string>
{
_jsonApiContext.IncludedRelationships = relationships;

foreach(var r in relationships)
foreach (var r in relationships)
entities = _entities.Include(entities, r.ToProperCase());

return entities;
Expand Down
5 changes: 4 additions & 1 deletion src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.EntityFrameworkCore;

namespace JsonApiDotNetCore.Formatters
{
Expand Down Expand Up @@ -37,13 +38,15 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
var loggerFactory = GetService<ILoggerFactory>(context);
var logger = loggerFactory?.CreateLogger<JsonApiInputFormatter>();

var dbContext = GetService<DbContext>(context);

try
{
var body = GetRequestBody(context.HttpContext.Request.Body);
var jsonApiContext = GetService<IJsonApiContext>(context);
var model = jsonApiContext.IsRelationshipPath ?
JsonApiDeSerializer.DeserializeRelationship(body, jsonApiContext) :
JsonApiDeSerializer.Deserialize(body, jsonApiContext);
JsonApiDeSerializer.Deserialize(body, jsonApiContext, dbContext);

if(model == null)
logger?.LogError("An error occurred while de-serializing the payload");
Expand Down
19 changes: 11 additions & 8 deletions src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using JsonApiDotNetCore.Extensions;
using JsonApiDotNetCore.Models;
Expand All @@ -18,21 +16,26 @@ public GenericProcessor(DbContext context)
}

public async Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds)
{
SetRelationships(parent, relationship, relationshipIds);

await _context.SaveChangesAsync();
}

public void SetRelationships(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds)
{
var relationshipType = relationship.Type;

if(relationship.IsHasMany)
if (relationship.IsHasMany)
{
var entities = _context.GetDbSet<T>().Where(x => relationshipIds.Contains(x.Id.ToString())).ToList();
var entities = _context.GetDbSet<T>().Where(x => relationshipIds.Contains(x.StringId)).ToList();
relationship.SetValue(parent, entities);
}
else
{
var entity = _context.GetDbSet<T>().SingleOrDefault(x => relationshipIds.First() == x.Id.ToString());
var entity = _context.GetDbSet<T>().SingleOrDefault(x => relationshipIds.First() == x.StringId);
relationship.SetValue(parent, entity);
}

await _context.SaveChangesAsync();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ namespace JsonApiDotNetCore.Internal
public interface IGenericProcessor
{
Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds);
void SetRelationships(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds);
}
}
24 changes: 24 additions & 0 deletions src/JsonApiDotNetCore/Internal/TypeHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Reflection;

namespace JsonApiDotNetCore.Internal
{
public static class TypeHelper
{
public static object ConvertType(object value, Type type)
{
if(value == null)
return null;

if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
type = Nullable.GetUnderlyingType(type);

var stringValue = value.ToString();

if(type == typeof(Guid))
return Guid.Parse(stringValue);

return Convert.ChangeType(stringValue, type);
}
}
}
2 changes: 1 addition & 1 deletion src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<VersionPrefix>1.1.0</VersionPrefix>
<VersionPrefix>1.1.1</VersionPrefix>
<TargetFramework>netcoreapp1.0</TargetFramework>
<AssemblyName>JsonApiDotNetCore</AssemblyName>
<PackageId>JsonApiDotNetCore</PackageId>
Expand Down
4 changes: 2 additions & 2 deletions src/JsonApiDotNetCore/Models/IIdentifiable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ namespace JsonApiDotNetCore.Models
{
public interface IIdentifiable
{
object Id { get; set; }
string StringId { get; set; }
}

public interface IIdentifiable<T> : IIdentifiable
{
new T Id { get; set; }
T Id { get; set; }
}
}
Loading

0 comments on commit 8b1c537

Please sign in to comment.