Skip to content

[WIP] The big rewrite #96

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 66 commits into from
Aug 22, 2015
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
490aad8
rewrite JSONAPI.NET to be compatible with JSON API 1.0
Jun 28, 2015
6e5fcd5
update TodoMVC project to use autofac integration
Jun 28, 2015
3664d39
change autofac configuration interface
Jun 28, 2015
3088b6b
remove redundant resolver statement
Jun 28, 2015
fefc3f2
allow UseJsonApiWithAutofac to take ILifetimeScope
Jun 28, 2015
00dee31
move generic parameter to interface for IPayloadMaterializer
Jun 29, 2015
a243266
fix mis-named class
Jun 29, 2015
84472a7
remove IMaterializer, IMetadataManager, and implementations
Jun 29, 2015
b75ae4e
make EFPayloadMaterializer method virtual
Jun 29, 2015
32779c5
use current request to get base url
Jun 29, 2015
78e7718
Add metadata param to resource collection payload builder
Jun 29, 2015
dea14d0
implement related resource URLs
Jun 29, 2015
dafa96d
implement related resource URLs for to-one relationships
Jun 29, 2015
25345f8
make new related methods protected
Jun 29, 2015
fc7732d
add IBaseUrlService
Jun 29, 2015
455af08
add new convenience methods for making JsonApiException
Jun 29, 2015
597513c
support custom filter and sort expressions for registered types
Jun 29, 2015
41d2b95
remove sorting by +
Jun 29, 2015
ec1cda6
rearrange acceptance tests
Jun 30, 2015
1abdddc
don't fail on unknown fields; ignore instead
Jun 30, 2015
f13058b
include relationships when materializing
Jun 30, 2015
e34d6f9
separate out value converters into files
Jun 30, 2015
2963d60
rename primitives and general cleanup
Jul 1, 2015
e27868b
make sure TodoMVC sample works.
Jul 1, 2015
f3ddb88
Move namespace of queryable transformers
Jul 1, 2015
edcb959
ensure not found works for fetching resource by ID
Jul 1, 2015
dae593f
return 404 for to-one related resources to non-existant resource
Jul 1, 2015
e1a78d2
return 404 for to-many related actions where primary resource doesn't…
Jul 1, 2015
b4fb7d2
provide serialization hooks for RelationshipObjectFormatter children
Jul 2, 2015
bc083df
don't crash when requesting related resource for non-existent relatio…
Jul 2, 2015
2e54d6a
make GetBaseUrl method virtual
Jul 4, 2015
b2a5213
allow specifying includes and metadata for queryable builder
Jul 4, 2015
7dc407e
don't fail on null to-many relationship
Jul 7, 2015
ba3388b
remove extraneous select
Jul 7, 2015
d1256af
simplify async queryable enumeration transformer
Jul 9, 2015
4d0de76
add queryable enumeration transform method
Jul 9, 2015
bf14fe0
add materializer for mapping entities to DTOs
Jul 9, 2015
464d648
allow serializing null related resources
Jul 10, 2015
48e19a4
allow serializing metadata with ISingleResourceDocumentBuilder
Jul 10, 2015
5dfaf4b
add some documentation
Jul 10, 2015
13b8c32
add single record filter to IDocumentMaterializer
Jul 10, 2015
91ca6a3
rearrange acceptance test projects
Jul 11, 2015
e5f9eb2
Refactor configuration and document materialization systems
Jul 12, 2015
0d2091b
split into new files
Jul 12, 2015
68dfca7
remove unused delegates
Jul 13, 2015
c2eaa23
sanitize configuration interfaces slightly
Jul 13, 2015
6ca6010
add way to configure a default related resource materializer per reso…
Jul 13, 2015
b963cd6
more configuration interface cleanup
Jul 13, 2015
d10b334
fix a couple mis-named things
Jul 13, 2015
d973bb1
provide hook for configuring lifetime scope before it is built
Jul 13, 2015
9db8a94
allow customizing DefaultNamingConventions
Jul 13, 2015
6b0ccc1
add convenience method for constructing 403 errors
Jul 14, 2015
e14592e
have MappedDocumentMaterializer punt on created, update, and delete
Jul 15, 2015
e851748
store relationship configurations by name instead of property
Jul 15, 2015
6bf83cc
make GetKeyNames work recursively
Jul 16, 2015
015b7ff
add test for subclass
Jul 17, 2015
9e185df
Adding globalization for decimal, double and single for conversion.
cybermats Jul 17, 2015
74fd025
convert linkage objects to using IResourceIdentifiers
Jul 17, 2015
f0324f5
Merge pull request #97 from cybermats/payload2
csantero Jul 18, 2015
fbc430a
make sure null to-one included relationships are serialized with null…
Jul 19, 2015
96b57f8
await tasks in JsonApiFormatter
Jul 21, 2015
8321989
allow specifying include paths
Jul 22, 2015
05cb963
expose PathVisitor
Jul 27, 2015
2d442ce
make GET methods virtual
Jul 30, 2015
adea1cb
send correct query to GetDocumentMetadata
Aug 2, 2015
aa795f0
make SetValue work with JToken null
Aug 13, 2015
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
Prev Previous commit
Next Next commit
add IBaseUrlService
  • Loading branch information
Chris Santero committed Jun 29, 2015
commit fc7732d1f34d65fc46f37d55f2c01d1d7ebcc2e1
2 changes: 2 additions & 0 deletions JSONAPI.Autofac/JsonApiAutofacModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Autofac;
using JSONAPI.ActionFilters;
using JSONAPI.Core;
using JSONAPI.Http;
using JSONAPI.Json;
using JSONAPI.Payload;
using JSONAPI.Payload.Builders;
Expand Down Expand Up @@ -36,6 +37,7 @@ protected override void Load(ContainerBuilder builder)
}).As<IResourceTypeRegistry>().SingleInstance();

builder.RegisterType<JsonApiHttpConfiguration>();
builder.RegisterType<BaseUrlService>().As<IBaseUrlService>();

// Serialization
builder.RegisterType<MetadataSerializer>().As<IMetadataSerializer>().SingleInstance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class EntityFrameworkPayloadMaterializer<T> : IPayloadMaterializer<T> whe
private readonly IResourceTypeRegistry _resourceTypeRegistry;
private readonly IQueryableResourceCollectionPayloadBuilder _queryableResourceCollectionPayloadBuilder;
private readonly ISingleResourcePayloadBuilder _singleResourcePayloadBuilder;
private readonly IBaseUrlService _baseUrlService;
private readonly MethodInfo _getRelatedToManyMethod;
private readonly MethodInfo _getRelatedToOneMethod;

Expand All @@ -33,16 +34,19 @@ public class EntityFrameworkPayloadMaterializer<T> : IPayloadMaterializer<T> whe
/// <param name="resourceTypeRegistry"></param>
/// <param name="queryableResourceCollectionPayloadBuilder"></param>
/// <param name="singleResourcePayloadBuilder"></param>
/// <param name="baseUrlService"></param>
public EntityFrameworkPayloadMaterializer(
DbContext dbContext,
IResourceTypeRegistry resourceTypeRegistry,
IQueryableResourceCollectionPayloadBuilder queryableResourceCollectionPayloadBuilder,
ISingleResourcePayloadBuilder singleResourcePayloadBuilder)
ISingleResourcePayloadBuilder singleResourcePayloadBuilder,
IBaseUrlService baseUrlService)
{
_dbContext = dbContext;
_resourceTypeRegistry = resourceTypeRegistry;
_queryableResourceCollectionPayloadBuilder = queryableResourceCollectionPayloadBuilder;
_singleResourcePayloadBuilder = singleResourcePayloadBuilder;
_baseUrlService = baseUrlService;
_getRelatedToManyMethod = GetType()
.GetMethod("GetRelatedToMany", BindingFlags.NonPublic | BindingFlags.Instance);
_getRelatedToOneMethod = GetType()
Expand Down Expand Up @@ -116,11 +120,9 @@ public virtual async Task<IJsonApiPayload> DeleteRecord(string id, CancellationT
/// <summary>
/// Gets the base URL for link creation from the current request
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
protected static string GetBaseUrlFromRequest(HttpRequestMessage request)
protected string GetBaseUrlFromRequest(HttpRequestMessage request)
{
return new Uri(request.RequestUri.AbsoluteUri.Replace(request.RequestUri.PathAndQuery, String.Empty)).ToString();
return _baseUrlService.GetBaseUrl(request);
}

/// <summary>
Expand Down
18 changes: 12 additions & 6 deletions JSONAPI.Tests/Payload/Builders/FallbackPayloadBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Web.Http.Controllers;
using FluentAssertions;
using JSONAPI.Core;
using JSONAPI.Http;
using JSONAPI.Payload;
using JSONAPI.Payload.Builders;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down Expand Up @@ -45,13 +46,12 @@ public async Task Creates_single_resource_payload_for_registered_non_collection_
var cancellationTokenSource = new CancellationTokenSource();

var request = new HttpRequestMessage(HttpMethod.Get, "https://www.example.com/fruits");
var mockRequestContext = new Mock<HttpRequestContext>();
mockRequestContext.Setup(c => c.VirtualPathRoot).Returns("https://www.example.com/fruits");
request.SetRequestContext(mockRequestContext.Object);
var mockBaseUrlService = new Mock<IBaseUrlService>(MockBehavior.Strict);
mockBaseUrlService.Setup(s => s.GetBaseUrl(request)).Returns("https://www.example.com");

// Act
var fallbackPayloadBuilder = new FallbackPayloadBuilder(singleResourcePayloadBuilder.Object,
mockQueryablePayloadBuilder.Object, mockResourceCollectionPayloadBuilder.Object);
mockQueryablePayloadBuilder.Object, mockResourceCollectionPayloadBuilder.Object, mockBaseUrlService.Object);
var resultPayload = await fallbackPayloadBuilder.BuildPayload(objectContent, request, cancellationTokenSource.Token);

// Assert
Expand All @@ -73,6 +73,9 @@ public async Task Creates_resource_collection_payload_for_queryables()
var singleResourcePayloadBuilder = new Mock<ISingleResourcePayloadBuilder>(MockBehavior.Strict);

var request = new HttpRequestMessage();

var mockBaseUrlService = new Mock<IBaseUrlService>(MockBehavior.Strict);
mockBaseUrlService.Setup(s => s.GetBaseUrl(request)).Returns("https://www.example.com/");

var cancellationTokenSource = new CancellationTokenSource();

Expand All @@ -85,7 +88,7 @@ public async Task Creates_resource_collection_payload_for_queryables()

// Act
var fallbackPayloadBuilder = new FallbackPayloadBuilder(singleResourcePayloadBuilder.Object,
mockQueryablePayloadBuilder.Object, mockResourceCollectionPayloadBuilder.Object);
mockQueryablePayloadBuilder.Object, mockResourceCollectionPayloadBuilder.Object, mockBaseUrlService.Object);
var resultPayload = await fallbackPayloadBuilder.BuildPayload(items, request, cancellationTokenSource.Token);

// Assert
Expand All @@ -110,6 +113,9 @@ public async Task Creates_resource_collection_payload_for_non_queryable_enumerab

var request = new HttpRequestMessage(HttpMethod.Get, "https://www.example.com/fruits");

var mockBaseUrlService = new Mock<IBaseUrlService>(MockBehavior.Strict);
mockBaseUrlService.Setup(s => s.GetBaseUrl(request)).Returns("https://www.example.com/");

var mockQueryablePayloadBuilder = new Mock<IQueryableResourceCollectionPayloadBuilder>(MockBehavior.Strict);
var mockResourceCollectionPayloadBuilder = new Mock<IResourceCollectionPayloadBuilder>(MockBehavior.Strict);
mockResourceCollectionPayloadBuilder
Expand All @@ -118,7 +124,7 @@ public async Task Creates_resource_collection_payload_for_non_queryable_enumerab

// Act
var fallbackPayloadBuilder = new FallbackPayloadBuilder(singleResourcePayloadBuilder.Object,
mockQueryablePayloadBuilder.Object, mockResourceCollectionPayloadBuilder.Object);
mockQueryablePayloadBuilder.Object, mockResourceCollectionPayloadBuilder.Object, mockBaseUrlService.Object);
var resultPayload = await fallbackPayloadBuilder.BuildPayload(items, request, cancellationTokenSource.Token);

// Assert
Expand Down
7 changes: 5 additions & 2 deletions JSONAPI/Core/JsonApiConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Web.Http;
using JSONAPI.ActionFilters;
using JSONAPI.Http;
using JSONAPI.Json;
using JSONAPI.Payload;
using JSONAPI.Payload.Builders;
Expand Down Expand Up @@ -67,12 +68,14 @@ public void Apply(HttpConfiguration httpConfig)
var paginationTransformer = new DefaultPaginationTransformer();

// Builders
var baseUrlService = new BaseUrlService();
var singleResourcePayloadBuilder = new RegistryDrivenSingleResourcePayloadBuilder(_resourceTypeRegistry, linkConventions);
var resourceCollectionPayloadBuilder = new RegistryDrivenResourceCollectionPayloadBuilder(_resourceTypeRegistry, linkConventions);
var queryableResourcePayloadBuilder = new DefaultQueryableResourceCollectionPayloadBuilder(resourceCollectionPayloadBuilder,
queryableEnumerationTransformer, filteringTransformer, sortingTransformer, paginationTransformer);
queryableEnumerationTransformer, filteringTransformer, sortingTransformer, paginationTransformer, baseUrlService);
var errorPayloadBuilder = new ErrorPayloadBuilder();
var fallbackPayloadBuilder = new FallbackPayloadBuilder(singleResourcePayloadBuilder, queryableResourcePayloadBuilder, resourceCollectionPayloadBuilder);
var fallbackPayloadBuilder = new FallbackPayloadBuilder(singleResourcePayloadBuilder,
queryableResourcePayloadBuilder, resourceCollectionPayloadBuilder, baseUrlService);

// Dependencies for JsonApiHttpConfiguration
var formatter = new JsonApiFormatter(singleResourcePayloadSerializer, resourceCollectionPayloadSerializer, errorPayloadSerializer, errorPayloadBuilder);
Expand Down
18 changes: 18 additions & 0 deletions JSONAPI/Http/BaseUrlService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Net.Http;

namespace JSONAPI.Http
{
/// <summary>
/// Default implementation of IBaseUrlService
/// </summary>
public class BaseUrlService : IBaseUrlService
{
public string GetBaseUrl(HttpRequestMessage requestMessage)
{
return
new Uri(requestMessage.RequestUri.AbsoluteUri.Replace(requestMessage.RequestUri.PathAndQuery,
String.Empty)).ToString();
}
}
}
15 changes: 15 additions & 0 deletions JSONAPI/Http/IBaseUrlService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Net.Http;

namespace JSONAPI.Http
{
/// <summary>
/// Service allowing you to get the base URL for a request
/// </summary>
public interface IBaseUrlService
{
/// <summary>
/// Gets the base URL for a request
/// </summary>
string GetBaseUrl(HttpRequestMessage requestMessage);
}
}
2 changes: 2 additions & 0 deletions JSONAPI/JSONAPI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
<Compile Include="Extensions\QueryableExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Extensions\TypeExtensions.cs" />
<Compile Include="Http\BaseUrlService.cs" />
<Compile Include="Http\IBaseUrlService.cs" />
<Compile Include="Http\IPayloadMaterializer.cs" />
<Compile Include="Http\JsonApiController.cs" />
<Compile Include="Http\PascalizedControllerSelector.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading;
using System.Threading.Tasks;
using JSONAPI.ActionFilters;
using JSONAPI.Http;

namespace JSONAPI.Payload.Builders
{
Expand All @@ -17,6 +18,7 @@ public class DefaultQueryableResourceCollectionPayloadBuilder : IQueryableResour
private readonly IQueryableFilteringTransformer _filteringTransformer;
private readonly IQueryableSortingTransformer _sortingTransformer;
private readonly IQueryablePaginationTransformer _paginationTransformer;
private readonly IBaseUrlService _baseUrlService;

/// <summary>
///
Expand All @@ -26,18 +28,21 @@ public class DefaultQueryableResourceCollectionPayloadBuilder : IQueryableResour
/// <param name="filteringTransformer"></param>
/// <param name="sortingTransformer"></param>
/// <param name="paginationTransformer"></param>
/// <param name="baseUrlService"></param>
public DefaultQueryableResourceCollectionPayloadBuilder(
IResourceCollectionPayloadBuilder resourceCollectionPayloadBuilder,
IQueryableEnumerationTransformer enumerationTransformer,
IQueryableFilteringTransformer filteringTransformer,
IQueryableSortingTransformer sortingTransformer,
IQueryablePaginationTransformer paginationTransformer)
IQueryablePaginationTransformer paginationTransformer,
IBaseUrlService baseUrlService)
{
_resourceCollectionPayloadBuilder = resourceCollectionPayloadBuilder;
_enumerationTransformer = enumerationTransformer;
_filteringTransformer = filteringTransformer;
_sortingTransformer = sortingTransformer;
_paginationTransformer = paginationTransformer;
_baseUrlService = baseUrlService;
}

public async Task<IResourceCollectionPayload> BuildPayload<T>(IQueryable<T> query, HttpRequestMessage request, CancellationToken cancellationToken)
Expand All @@ -54,7 +59,7 @@ public async Task<IResourceCollectionPayload> BuildPayload<T>(IQueryable<T> quer
query = paginationResults.PagedQuery;
}

var linkBaseUrl = new Uri(request.RequestUri.AbsoluteUri.Replace(request.RequestUri.PathAndQuery, String.Empty)).ToString();
var linkBaseUrl = _baseUrlService.GetBaseUrl(request);

var results = await _enumerationTransformer.Enumerate(query, cancellationToken);
return _resourceCollectionPayloadBuilder.BuildPayload(results, linkBaseUrl, null, null);
Expand Down
9 changes: 7 additions & 2 deletions JSONAPI/Payload/Builders/FallbackPayloadBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using JSONAPI.Http;

namespace JSONAPI.Payload.Builders
{
Expand All @@ -16,6 +17,7 @@ public class FallbackPayloadBuilder : IFallbackPayloadBuilder
private readonly ISingleResourcePayloadBuilder _singleResourcePayloadBuilder;
private readonly IQueryableResourceCollectionPayloadBuilder _queryableResourceCollectionPayloadBuilder;
private readonly IResourceCollectionPayloadBuilder _resourceCollectionPayloadBuilder;
private readonly IBaseUrlService _baseUrlService;
private readonly Lazy<MethodInfo> _openBuildPayloadFromQueryableMethod;
private readonly Lazy<MethodInfo> _openBuildPayloadFromEnumerableMethod;

Expand All @@ -25,13 +27,16 @@ public class FallbackPayloadBuilder : IFallbackPayloadBuilder
/// <param name="singleResourcePayloadBuilder"></param>
/// <param name="queryableResourceCollectionPayloadBuilder"></param>
/// <param name="resourceCollectionPayloadBuilder"></param>
/// <param name="baseUrlService"></param>
public FallbackPayloadBuilder(ISingleResourcePayloadBuilder singleResourcePayloadBuilder,
IQueryableResourceCollectionPayloadBuilder queryableResourceCollectionPayloadBuilder,
IResourceCollectionPayloadBuilder resourceCollectionPayloadBuilder)
IResourceCollectionPayloadBuilder resourceCollectionPayloadBuilder,
IBaseUrlService baseUrlService)
{
_singleResourcePayloadBuilder = singleResourcePayloadBuilder;
_queryableResourceCollectionPayloadBuilder = queryableResourceCollectionPayloadBuilder;
_resourceCollectionPayloadBuilder = resourceCollectionPayloadBuilder;
_baseUrlService = baseUrlService;

_openBuildPayloadFromQueryableMethod =
new Lazy<MethodInfo>(
Expand Down Expand Up @@ -72,7 +77,7 @@ public async Task<IJsonApiPayload> BuildPayload(object obj, HttpRequestMessage r
isCollection = true;
}

var linkBaseUrl = new Uri(requestMessage.RequestUri.AbsoluteUri.Replace(requestMessage.RequestUri.PathAndQuery, String.Empty)).ToString();
var linkBaseUrl = _baseUrlService.GetBaseUrl(requestMessage);

if (isCollection)
{
Expand Down