Skip to content

Fix/id type support #55

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 17 commits into from
Mar 15, 2017
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
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
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 (!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
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);
}
}
}
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; }
}
}
32 changes: 29 additions & 3 deletions src/JsonApiDotNetCore/Models/Identifiable.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
using JsonApiDotNetCore.Internal;

namespace JsonApiDotNetCore.Models
{
public class Identifiable : Identifiable<int>
Expand All @@ -7,10 +11,32 @@ public class Identifiable<T> : IIdentifiable<T>, IIdentifiable
{
public virtual T Id { get; set; }

object IIdentifiable.Id
[NotMapped]
public string StringId
{
get { return GetStringId(Id); }
set { Id = (T)GetConcreteId(value); }
}

protected virtual string GetStringId(object value)
{
var type = typeof(T);
var stringValue = value.ToString();

if(type == typeof(Guid))
{
var guid = Guid.Parse(stringValue);
return (guid == Guid.Empty ? string.Empty : stringValue);
}

if(stringValue == "0") return string.Empty;

return stringValue;
}

protected virtual object GetConcreteId(string value)
{
get { return Id; }
set { Id = (T)value; }
return TypeHelper.ConvertType(value, typeof(T));
}
}
}
Loading