Skip to content

Small refactorings #906

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 12 commits into from
Dec 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 0 additions & 2 deletions benchmarks/Query/QueryParserBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,10 @@ private void Run(int iterations, Action action) {

private sealed class FakeRequestQueryStringAccessor : IRequestQueryStringAccessor
{
public QueryString QueryString { get; private set; }
public IQueryCollection Query { get; private set; }

public void SetQueryString(string queryString)
{
QueryString = new QueryString(queryString);
Query = new QueryCollection(QueryHelpers.ParseQuery(queryString));
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/JsonApiDotNetCore/Controllers/JsonApiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ namespace JsonApiDotNetCore.Controllers
/// </summary>
/// <typeparam name="TResource">The resource type.</typeparam>
/// <typeparam name="TId">The resource identifier type.</typeparam>
public class JsonApiController<TResource, TId> : BaseJsonApiController<TResource, TId> where TResource : class, IIdentifiable<TId>
public abstract class JsonApiController<TResource, TId> : BaseJsonApiController<TResource, TId> where TResource : class, IIdentifiable<TId>
{
/// <inheritdoc />
public JsonApiController(
protected JsonApiController(
IJsonApiOptions options,
ILoggerFactory loggerFactory,
IResourceService<TResource, TId> resourceService)
: base(options, loggerFactory, resourceService)
{ }

/// <inheritdoc />
public JsonApiController(
protected JsonApiController(
IJsonApiOptions options,
ILoggerFactory loggerFactory,
IGetAllService<TResource, TId> getAll = null,
Expand Down Expand Up @@ -118,18 +118,18 @@ public override async Task<IActionResult> DeleteRelationshipAsync(TId id, string
}

/// <inheritdoc />
public class JsonApiController<TResource> : JsonApiController<TResource, int> where TResource : class, IIdentifiable<int>
public abstract class JsonApiController<TResource> : JsonApiController<TResource, int> where TResource : class, IIdentifiable<int>
{
/// <inheritdoc />
public JsonApiController(
protected JsonApiController(
IJsonApiOptions options,
ILoggerFactory loggerFactory,
IResourceService<TResource, int> resourceService)
: base(options, loggerFactory, resourceService)
{ }

/// <inheritdoc />
public JsonApiController(
protected JsonApiController(
IJsonApiOptions options,
ILoggerFactory loggerFactory,
IGetAllService<TResource, int> getAll = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ public interface IControllerResourceMapping
/// <summary>
/// Get the associated resource type for the provided controller name.
/// </summary>
Type GetAssociatedResource(string controllerName);
Type GetResourceTypeForController(string controllerName);
}
}
2 changes: 1 addition & 1 deletion src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private static ResourceContext CreatePrimaryResourceContext(RouteValueDictionary
var controllerName = (string) routeValues["controller"];
if (controllerName != null)
{
var resourceType = controllerResourceMapping.GetAssociatedResource(controllerName);
var resourceType = controllerResourceMapping.GetResourceTypeForController(controllerName);
if (resourceType != null)
{
return resourceContextProvider.GetResourceContext(resourceType);
Expand Down
10 changes: 5 additions & 5 deletions src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,20 @@ namespace JsonApiDotNetCore.Middleware
public class JsonApiRoutingConvention : IJsonApiRoutingConvention
{
private readonly IJsonApiOptions _options;
private readonly IResourceGraph _resourceGraph;
private readonly IResourceContextProvider _resourceContextProvider;
private readonly HashSet<string> _registeredTemplates = new HashSet<string>();

private readonly Dictionary<string, ResourceContext> _registeredResources =
new Dictionary<string, ResourceContext>();

public JsonApiRoutingConvention(IJsonApiOptions options, IResourceGraph resourceGraph)
public JsonApiRoutingConvention(IJsonApiOptions options, IResourceContextProvider resourceContextProvider)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_resourceGraph = resourceGraph ?? throw new ArgumentNullException(nameof(resourceGraph));
_resourceContextProvider = resourceContextProvider ?? throw new ArgumentNullException(nameof(resourceContextProvider));
}

/// <inheritdoc />
public Type GetAssociatedResource(string controllerName)
public Type GetResourceTypeForController(string controllerName)
{
if (controllerName == null) throw new ArgumentNullException(nameof(controllerName));

Expand All @@ -67,7 +67,7 @@ public void Apply(ApplicationModel application)

if (resourceType != null)
{
var resourceContext = _resourceGraph.GetResourceContext(resourceType);
var resourceContext = _resourceContextProvider.GetResourceContext(resourceType);

if (resourceContext != null)
{
Expand Down
4 changes: 2 additions & 2 deletions src/JsonApiDotNetCore/Queries/IQueryLayerComposer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ QueryLayer WrapLayerForSecondaryEndpoint<TId>(QueryLayer secondaryLayer, Resourc
QueryLayer ComposeForGetRelationshipRightIds(RelationshipAttribute relationship, ICollection<IIdentifiable> rightResourceIds);

/// <summary>
/// Builds a query for a many-to-many relationship with a filter to match on its left and right resource IDs.
/// Builds a query for a to-many relationship with a filter to match on its left and right resource IDs.
/// </summary>
QueryLayer ComposeForHasManyThrough<TId>(HasManyThroughAttribute hasManyThroughRelationship, TId leftId, ICollection<IIdentifiable> rightResourceIds);
QueryLayer ComposeForHasMany<TId>(HasManyAttribute hasManyRelationship, TId leftId, ICollection<IIdentifiable> rightResourceIds);
}
}
10 changes: 5 additions & 5 deletions src/JsonApiDotNetCore/Queries/Internal/QueryLayerComposer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,12 +337,12 @@ public QueryLayer ComposeForGetRelationshipRightIds(RelationshipAttribute relati
}

/// <inheritdoc />
public QueryLayer ComposeForHasManyThrough<TId>(HasManyThroughAttribute hasManyThroughRelationship, TId leftId, ICollection<IIdentifiable> rightResourceIds)
public QueryLayer ComposeForHasMany<TId>(HasManyAttribute hasManyRelationship, TId leftId, ICollection<IIdentifiable> rightResourceIds)
{
var leftResourceContext = _resourceContextProvider.GetResourceContext(hasManyThroughRelationship.LeftType);
var leftResourceContext = _resourceContextProvider.GetResourceContext(hasManyRelationship.LeftType);
var leftIdAttribute = GetIdAttribute(leftResourceContext);

var rightResourceContext = _resourceContextProvider.GetResourceContext(hasManyThroughRelationship.RightType);
var rightResourceContext = _resourceContextProvider.GetResourceContext(hasManyRelationship.RightType);
var rightIdAttribute = GetIdAttribute(rightResourceContext);
var rightTypedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray();

Expand All @@ -351,11 +351,11 @@ public QueryLayer ComposeForHasManyThrough<TId>(HasManyThroughAttribute hasManyT

return new QueryLayer(leftResourceContext)
{
Include = new IncludeExpression(new[] {new IncludeElementExpression(hasManyThroughRelationship)}),
Include = new IncludeExpression(new[] {new IncludeElementExpression(hasManyRelationship)}),
Filter = leftFilter,
Projection = new Dictionary<ResourceFieldAttribute, QueryLayer>
{
[hasManyThroughRelationship] = new QueryLayer(rightResourceContext)
[hasManyRelationship] = new QueryLayer(rightResourceContext)
{
Filter = rightFilter,
Projection = new Dictionary<ResourceFieldAttribute, QueryLayer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ namespace JsonApiDotNetCore.QueryStrings
/// </summary>
public interface IRequestQueryStringAccessor
{
QueryString QueryString { get; }
IQueryCollection Query { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ protected void AssertIsNotClearingRequiredRelationship(RelationshipAttribute rel

var relationshipIsBeingCleared = relationship is HasOneAttribute
? rightValue == null
: IsRequiredToManyRelationshipBeingCleared(relationship, leftResource, rightValue);
: IsToManyRelationshipBeingCleared(relationship, leftResource, rightValue);

if (relationshipIsRequired && relationshipIsBeingCleared)
{
Expand All @@ -203,7 +203,7 @@ protected void AssertIsNotClearingRequiredRelationship(RelationshipAttribute rel
}
}

private static bool IsRequiredToManyRelationshipBeingCleared(RelationshipAttribute relationship, TResource leftResource, object valueToAssign)
private static bool IsToManyRelationshipBeingCleared(RelationshipAttribute relationship, TResource leftResource, object valueToAssign)
{
ICollection<IIdentifiable> newRightResourceIds = TypeHelper.ExtractResources(valueToAssign);

Expand Down
26 changes: 9 additions & 17 deletions src/JsonApiDotNetCore/Serialization/JsonApiWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,23 @@ public JsonApiWriter(IJsonApiSerializer serializer, IExceptionHandler exceptionH

public async Task WriteAsync(OutputFormatterWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
if (context == null) throw new ArgumentNullException(nameof(context));

var response = context.HttpContext.Response;
response.ContentType = HeaderConstants.MediaType;

await using var writer = context.WriterFactory(response.Body, Encoding.UTF8);
string responseContent;

if (_serializer == null)
try
{
responseContent = JsonConvert.SerializeObject(context.Object);
responseContent = SerializeResponse(context.Object, (HttpStatusCode) response.StatusCode);
}
else
catch (Exception exception)
{
response.ContentType = HeaderConstants.MediaType;
try
{
responseContent = SerializeResponse(context.Object, (HttpStatusCode)response.StatusCode);
}
catch (Exception exception)
{
var errorDocument = _exceptionHandler.HandleException(exception);
responseContent = _serializer.Serialize(errorDocument);
var errorDocument = _exceptionHandler.HandleException(exception);
responseContent = _serializer.Serialize(errorDocument);

response.StatusCode = (int)errorDocument.GetErrorStatusCode();
}
response.StatusCode = (int) errorDocument.GetErrorStatusCode();
}

var url = context.HttpContext.Request.GetEncodedUrl();
Expand Down
6 changes: 6 additions & 0 deletions src/JsonApiDotNetCore/Serialization/Objects/Document.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ public sealed class Document : ExposableData<ResourceObject>
[JsonProperty("meta", NullValueHandling = NullValueHandling.Ignore)]
public IDictionary<string, object> Meta { get; set; }

/// <summary>
/// see "jsonapi" in https://jsonapi.org/format/#document-top-level
/// </summary>
[JsonProperty("jsonapi", NullValueHandling = NullValueHandling.Ignore)]
public IDictionary<string, object> JsonApi { get; set; }

/// <summary>
/// see "links" in https://jsonapi.org/format/#document-top-level
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using Newtonsoft.Json;

namespace JsonApiDotNetCore.Serialization.Objects
Expand All @@ -6,5 +7,8 @@ public sealed class RelationshipEntry : ExposableData<ResourceIdentifierObject>
{
[JsonProperty("links", NullValueHandling = NullValueHandling.Ignore)]
public RelationshipLinks Links { get; set; }

[JsonProperty("meta", NullValueHandling = NullValueHandling.Ignore)]
public IDictionary<string, object> Meta { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,6 @@ namespace JsonApiDotNetCore.Serialization.Objects
{
public class ResourceIdentifierObject
{
public ResourceIdentifierObject() { }

public ResourceIdentifierObject(string type, string id)
{
Type = type;
Id = id;
}

[JsonProperty("type", Order = -3)]
public string Type { get; set; }

Expand Down
4 changes: 4 additions & 0 deletions src/JsonApiDotNetCore/Serialization/Objects/TopLevelLinks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public sealed class TopLevelLinks
[JsonProperty("related")]
public string Related { get; set; }

[JsonProperty("describedby")]
public string DescribedBy { get; set; }

[JsonProperty("first")]
public string First { get; set; }

Expand All @@ -28,6 +31,7 @@ public sealed class TopLevelLinks
// http://www.newtonsoft.com/json/help/html/ConditionalProperties.htm
public bool ShouldSerializeSelf() => !string.IsNullOrEmpty(Self);
public bool ShouldSerializeRelated() => !string.IsNullOrEmpty(Related);
public bool ShouldSerializeDescribedBy() => !string.IsNullOrEmpty(DescribedBy);
public bool ShouldSerializeFirst() => !string.IsNullOrEmpty(First);
public bool ShouldSerializeLast() => !string.IsNullOrEmpty(Last);
public bool ShouldSerializePrev() => !string.IsNullOrEmpty(Prev);
Expand Down
11 changes: 7 additions & 4 deletions src/JsonApiDotNetCore/Services/JsonApiResourceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,13 @@ public virtual async Task<TResource> CreateAsync(TResource resource, Cancellatio
}
catch (DataStoreUpdateException)
{
var existingResource = await TryGetPrimaryResourceByIdAsync(resourceFromRequest.Id, TopFieldSelection.OnlyIdAttribute, cancellationToken);
if (existingResource != null)
if (!Equals(resourceFromRequest.Id, default(TId)))
{
throw new ResourceAlreadyExistsException(resourceFromRequest.StringId, _request.PrimaryResource.PublicName);
var existingResource = await TryGetPrimaryResourceByIdAsync(resourceFromRequest.Id, TopFieldSelection.OnlyIdAttribute, cancellationToken);
if (existingResource != null)
{
throw new ResourceAlreadyExistsException(resourceFromRequest.StringId, _request.PrimaryResource.PublicName);
}
}

await AssertResourcesToAssignInRelationshipsExistAsync(resourceFromRequest, cancellationToken);
Expand Down Expand Up @@ -287,7 +290,7 @@ public async Task AddToToManyRelationshipAsync(TId primaryId, string relationshi
private async Task RemoveExistingIdsFromSecondarySet(TId primaryId, ISet<IIdentifiable> secondaryResourceIds,
HasManyThroughAttribute hasManyThrough, CancellationToken cancellationToken)
{
var queryLayer = _queryLayerComposer.ComposeForHasManyThrough(hasManyThrough, primaryId, secondaryResourceIds);
var queryLayer = _queryLayerComposer.ComposeForHasMany(hasManyThrough, primaryId, secondaryResourceIds);
var primaryResources = await _repositoryAccessor.GetAsync<TResource>(queryLayer, cancellationToken);

var primaryResource = primaryResources.FirstOrDefault();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public async Task Can_filter_equality_on_type(string propertyName, object value)

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.RemoveRange(dbContext.FilterableResources);
await dbContext.ClearTableAsync<FilterableResource>();
dbContext.FilterableResources.AddRange(resource, new FilterableResource());

await dbContext.SaveChangesAsync();
Expand All @@ -71,7 +71,7 @@ public async Task Can_filter_equality_on_type_Decimal()

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.RemoveRange(dbContext.FilterableResources);
await dbContext.ClearTableAsync<FilterableResource>();
dbContext.FilterableResources.AddRange(resource, new FilterableResource());

await dbContext.SaveChangesAsync();
Expand All @@ -97,7 +97,7 @@ public async Task Can_filter_equality_on_type_Guid()

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.RemoveRange(dbContext.FilterableResources);
await dbContext.ClearTableAsync<FilterableResource>();
dbContext.FilterableResources.AddRange(resource, new FilterableResource());

await dbContext.SaveChangesAsync();
Expand All @@ -123,7 +123,7 @@ public async Task Can_filter_equality_on_type_DateTime()

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.RemoveRange(dbContext.FilterableResources);
await dbContext.ClearTableAsync<FilterableResource>();
dbContext.FilterableResources.AddRange(resource, new FilterableResource());

await dbContext.SaveChangesAsync();
Expand Down Expand Up @@ -152,7 +152,7 @@ public async Task Can_filter_equality_on_type_DateTimeOffset()

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.RemoveRange(dbContext.FilterableResources);
await dbContext.ClearTableAsync<FilterableResource>();
dbContext.FilterableResources.AddRange(resource, new FilterableResource());

await dbContext.SaveChangesAsync();
Expand All @@ -178,7 +178,7 @@ public async Task Can_filter_equality_on_type_TimeSpan()

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.RemoveRange(dbContext.FilterableResources);
await dbContext.ClearTableAsync<FilterableResource>();
dbContext.FilterableResources.AddRange(resource, new FilterableResource());

await dbContext.SaveChangesAsync();
Expand All @@ -204,7 +204,7 @@ public async Task Cannot_filter_equality_on_incompatible_value()

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.RemoveRange(dbContext.FilterableResources);
await dbContext.ClearTableAsync<FilterableResource>();
dbContext.FilterableResources.AddRange(resource, new FilterableResource());

await dbContext.SaveChangesAsync();
Expand Down Expand Up @@ -261,7 +261,7 @@ public async Task Can_filter_is_null_on_type(string propertyName)

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.RemoveRange(dbContext.FilterableResources);
await dbContext.ClearTableAsync<FilterableResource>();
dbContext.FilterableResources.AddRange(resource, otherResource);

await dbContext.SaveChangesAsync();
Expand Down Expand Up @@ -312,7 +312,7 @@ public async Task Can_filter_is_not_null_on_type(string propertyName)

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.RemoveRange(dbContext.FilterableResources);
await dbContext.ClearTableAsync<FilterableResource>();
dbContext.FilterableResources.AddRange(resource, new FilterableResource());

await dbContext.SaveChangesAsync();
Expand Down
Loading