entitiesByRelationship, ResourcePipeline pipeline)
{
@@ -20,5 +26,13 @@ public override void BeforeImplicitUpdateRelationship(IRelationshipsDictionary().ToList().ForEach(kvp => DisallowLocked(kvp.Value));
}
+
+ public Dictionary GetMeta()
+ {
+ return new Dictionary {
+ { "copyright", "Copyright 2015 Example Corp." },
+ { "authors", new string[] { "Jared Nance", "Maurits Moeys", "Harro van der Kroft" } }
+ };
+ }
}
}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Resources/TagResource.cs b/src/Examples/JsonApiDotNetCoreExample/Resources/TagResource.cs
index e3b3100ddd..1999936e34 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Resources/TagResource.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Resources/TagResource.cs
@@ -4,14 +4,13 @@
using JsonApiDotNetCore.Hooks;
using JsonApiDotNetCoreExample.Models;
using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Internal.Contracts;
namespace JsonApiDotNetCoreExample.Resources
{
public class TagResource : ResourceDefinition
{
- public TagResource(IResourceGraph graph) : base(graph)
- {
- }
+ public TagResource(IResourceGraph resourceGraph) : base(resourceGraph) { }
public override IEnumerable BeforeCreate(IEntityHashSet affected, ResourcePipeline pipeline)
{
diff --git a/src/Examples/JsonApiDotNetCoreExample/Resources/TodoResource.cs b/src/Examples/JsonApiDotNetCoreExample/Resources/TodoResource.cs
index cfba9855d3..26f6c69c64 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Resources/TodoResource.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Resources/TodoResource.cs
@@ -4,12 +4,13 @@
using JsonApiDotNetCore.Internal;
using JsonApiDotNetCore.Hooks;
using JsonApiDotNetCoreExample.Models;
+using JsonApiDotNetCore.Internal.Contracts;
namespace JsonApiDotNetCoreExample.Resources
{
public class TodoResource : LockableResource
{
- public TodoResource(IResourceGraph graph) : base(graph) { }
+ public TodoResource(IResourceGraph resourceGraph) : base(resourceGraph) { }
public override void BeforeRead(ResourcePipeline pipeline, bool isIncluded = false, string stringId = null)
{
diff --git a/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs b/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs
index ec54b6144e..9aa8d8397f 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs
@@ -1,18 +1,18 @@
-using System.Collections.Generic;
using System.Linq;
using JsonApiDotNetCore.Models;
using JsonApiDotNetCoreExample.Models;
using JsonApiDotNetCore.Internal.Query;
-using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Internal.Contracts;
+using JsonApiDotNetCore.Services;
namespace JsonApiDotNetCoreExample.Resources
{
public class UserResource : ResourceDefinition
{
- public UserResource(IResourceGraph graph) : base(graph) { }
-
- protected override List OutputAttrs()
- => Remove(user => user.Password);
+ public UserResource(IResourceGraph resourceGraph) : base(resourceGraph)
+ {
+ HideFields(u => u.Password);
+ }
public override QueryFilters GetQueryFilters()
{
@@ -24,13 +24,15 @@ public override QueryFilters GetQueryFilters()
private IQueryable FirstCharacterFilter(IQueryable users, FilterQuery filterQuery)
{
- switch(filterQuery.Operation)
- {
- case "lt":
- return users.Where(u => u.Username[0] < filterQuery.Value[0]);
- default:
- return users.Where(u => u.Username[0] == filterQuery.Value[0]);
- }
+ switch (filterQuery.Operation)
+ {
+ /// In EF core >= 3.0 we need to explicitly evaluate the query first. This could probably be translated
+ /// into a query by building expression trees.
+ case "lt":
+ return users.ToList().Where(u => u.Username.First() < filterQuery.Value[0]).AsQueryable();
+ default:
+ return users.ToList().Where(u => u.Username.First() == filterQuery.Value[0]).AsQueryable();
+ }
}
}
}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Services/CustomArticleService.cs b/src/Examples/JsonApiDotNetCoreExample/Services/CustomArticleService.cs
new file mode 100644
index 0000000000..d34f32756d
--- /dev/null
+++ b/src/Examples/JsonApiDotNetCoreExample/Services/CustomArticleService.cs
@@ -0,0 +1,37 @@
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Data;
+using JsonApiDotNetCore.Hooks;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Internal.Contracts;
+using JsonApiDotNetCore.Query;
+using JsonApiDotNetCore.Services;
+using JsonApiDotNetCoreExample.Models;
+using Microsoft.Extensions.Logging;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace JsonApiDotNetCoreExample.Services
+{
+ public class CustomArticleService : DefaultResourceService
+ {
+ public CustomArticleService(IEnumerable queryParameters,
+ IJsonApiOptions options,
+ IResourceRepository repository,
+ IResourceContextProvider provider,
+ IResourceHookExecutor hookExecutor = null,
+ ILoggerFactory loggerFactory = null)
+ : base(queryParameters, options, repository, provider, hookExecutor, loggerFactory) { }
+
+ public override async Task GetAsync(int id)
+ {
+ var newEntity = await base.GetAsync(id);
+ if(newEntity == null)
+ {
+ throw new JsonApiException(404, "The entity could not be found");
+ }
+ newEntity.Name = "None for you Glen Coco";
+ return newEntity;
+ }
+ }
+
+}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Startups/ClientGeneratedIdsStartup.cs b/src/Examples/JsonApiDotNetCoreExample/Startups/ClientGeneratedIdsStartup.cs
new file mode 100644
index 0000000000..10255d6727
--- /dev/null
+++ b/src/Examples/JsonApiDotNetCoreExample/Startups/ClientGeneratedIdsStartup.cs
@@ -0,0 +1,44 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using JsonApiDotNetCoreExample.Data;
+using Microsoft.EntityFrameworkCore;
+using JsonApiDotNetCore.Extensions;
+using System.Reflection;
+
+namespace JsonApiDotNetCoreExample
+{
+ ///
+ /// This should be in JsonApiDotNetCoreExampleTests project but changes in .net core 3.0
+ /// do no longer allow that. See https://github.com/aspnet/AspNetCore/issues/15373.
+ ///
+ public class ClientGeneratedIdsStartup : Startup
+ {
+ public ClientGeneratedIdsStartup(IWebHostEnvironment env)
+ : base (env)
+ { }
+
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ var loggerFactory = new LoggerFactory();
+ var mvcBuilder = services.AddMvcCore();
+ services
+ .AddSingleton(loggerFactory)
+ .AddLogging(builder =>
+ {
+ builder.AddConsole();
+ })
+ .AddDbContext(options => options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Transient)
+ .AddJsonApi(options => {
+ options.Namespace = "api/v1";
+ options.DefaultPageSize = 5;
+ options.IncludeTotalRecordCount = true;
+ options.EnableResourceHooks = true;
+ options.LoaDatabaseValues = true;
+ options.AllowClientGeneratedIds = true;
+ },
+ discovery => discovery.AddAssembly(Assembly.Load(nameof(JsonApiDotNetCoreExample))),
+ mvcBuilder: mvcBuilder);
+ }
+ }
+}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Startups/MetaStartup.cs b/src/Examples/JsonApiDotNetCoreExample/Startups/MetaStartup.cs
new file mode 100644
index 0000000000..32accb087a
--- /dev/null
+++ b/src/Examples/JsonApiDotNetCoreExample/Startups/MetaStartup.cs
@@ -0,0 +1,34 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using JsonApiDotNetCore.Services;
+using System.Collections.Generic;
+
+namespace JsonApiDotNetCoreExample
+{
+ ///
+ /// This should be in JsonApiDotNetCoreExampleTests project but changes in .net core 3.0
+ /// do no longer allow that. See https://github.com/aspnet/AspNetCore/issues/15373.
+ ///
+ public class MetaStartup : Startup
+ {
+ public MetaStartup(IWebHostEnvironment env)
+ : base (env)
+ { }
+
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ services.AddScoped();
+ base.ConfigureServices(services);
+ }
+ }
+
+ public class MetaService : IRequestMeta
+ {
+ public Dictionary GetMeta()
+ {
+ return new Dictionary {
+ { "request-meta", "request-meta-value" }
+ };
+ }
+ }
+}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Startup.cs b/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs
similarity index 68%
rename from src/Examples/JsonApiDotNetCoreExample/Startup.cs
rename to src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs
index 44784f7eac..3e9d3ca9e3 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Startup.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs
@@ -14,50 +14,49 @@ public class Startup
{
public readonly IConfiguration Config;
- public Startup(IHostingEnvironment env)
+ public Startup(IWebHostEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
-
Config = builder.Build();
}
- public virtual IServiceProvider ConfigureServices(IServiceCollection services)
+ public virtual void ConfigureServices(IServiceCollection services)
{
var loggerFactory = new LoggerFactory();
- loggerFactory.AddConsole(LogLevel.Warning);
-
- var mvcBuilder = services.AddMvcCore();
-
services
.AddSingleton(loggerFactory)
- .AddDbContext(options => options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Transient)
- .AddJsonApi(options => {
+ .AddLogging(builder =>
+ {
+ builder.AddConsole();
+ builder.AddConfiguration(Config.GetSection("Logging"));
+ })
+ .AddDbContext(options =>
+ {
+ options.UseNpgsql(GetDbConnectionString(), options => options.SetPostgresVersion(new Version(9,6)));
+ }, ServiceLifetime.Transient)
+ .AddJsonApi(options =>
+ {
options.Namespace = "api/v1";
options.DefaultPageSize = 5;
options.IncludeTotalRecordCount = true;
options.EnableResourceHooks = true;
- options.LoadDatabaseValues = true;
- },
- mvcBuilder,
+ options.LoaDatabaseValues = true;
+ },
discovery => discovery.AddCurrentAssembly());
-
- return services.BuildServiceProvider();
+ services.AddClientSerialization();
}
public virtual void Configure(
IApplicationBuilder app,
- IHostingEnvironment env,
ILoggerFactory loggerFactory,
AppDbContext context)
{
- context.Database.EnsureCreated();
-
- loggerFactory.AddConsole(Config.GetSection("Logging"));
+ context.Database.EnsureCreated();
app.UseJsonApi();
}
diff --git a/src/Examples/JsonApiDotNetCoreExample/web.config b/src/Examples/JsonApiDotNetCoreExample/web.config
index a8d6672758..50d0b02786 100644
--- a/src/Examples/JsonApiDotNetCoreExample/web.config
+++ b/src/Examples/JsonApiDotNetCoreExample/web.config
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Examples/NoEntityFrameworkExample/Controllers/CustomTodoItemsController.cs b/src/Examples/NoEntityFrameworkExample/Controllers/CustomTodoItemsController.cs
deleted file mode 100644
index a6ded9749f..0000000000
--- a/src/Examples/NoEntityFrameworkExample/Controllers/CustomTodoItemsController.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using JsonApiDotNetCore.Controllers;
-using JsonApiDotNetCore.Services;
-using JsonApiDotNetCoreExample.Models;
-using Microsoft.Extensions.Logging;
-
-namespace NoEntityFrameworkExample.Controllers
-{
- public class CustomTodoItemsController : JsonApiController
- {
- public CustomTodoItemsController(
- IJsonApiContext jsonApiContext,
- IResourceService resourceService,
- ILoggerFactory loggerFactory)
- : base(jsonApiContext, resourceService, loggerFactory)
- { }
- }
-}
diff --git a/src/Examples/NoEntityFrameworkExample/Controllers/TodoItemsController.cs b/src/Examples/NoEntityFrameworkExample/Controllers/TodoItemsController.cs
new file mode 100644
index 0000000000..cf18987700
--- /dev/null
+++ b/src/Examples/NoEntityFrameworkExample/Controllers/TodoItemsController.cs
@@ -0,0 +1,18 @@
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Controllers;
+using JsonApiDotNetCore.Services;
+using NoEntityFrameworkExample.Models;
+using Microsoft.Extensions.Logging;
+
+namespace NoEntityFrameworkExample.Controllers
+{
+ public class TodoItemsController : JsonApiController
+ {
+ public TodoItemsController(
+ IJsonApiOptions jsonApiOptions,
+ IResourceService resourceService,
+ ILoggerFactory loggerFactory)
+ : base(jsonApiOptions, resourceService, loggerFactory)
+ { }
+ }
+}
diff --git a/src/Examples/NoEntityFrameworkExample/Data/AppDbContext.cs b/src/Examples/NoEntityFrameworkExample/Data/AppDbContext.cs
new file mode 100644
index 0000000000..e7247108dd
--- /dev/null
+++ b/src/Examples/NoEntityFrameworkExample/Data/AppDbContext.cs
@@ -0,0 +1,14 @@
+using NoEntityFrameworkExample.Models;
+using Microsoft.EntityFrameworkCore;
+
+namespace NoEntityFrameworkExample.Data
+{
+ public class AppDbContext : DbContext
+ {
+ public AppDbContext(DbContextOptions options)
+ : base(options)
+ { }
+
+ public DbSet TodoItems { get; set; }
+ }
+}
diff --git a/src/Examples/NoEntityFrameworkExample/Models/TodoItem.cs b/src/Examples/NoEntityFrameworkExample/Models/TodoItem.cs
new file mode 100644
index 0000000000..b1021d18f5
--- /dev/null
+++ b/src/Examples/NoEntityFrameworkExample/Models/TodoItem.cs
@@ -0,0 +1,36 @@
+using System;
+using JsonApiDotNetCore.Models;
+
+namespace NoEntityFrameworkExample.Models
+{
+ public class TodoItem : Identifiable
+ {
+ public TodoItem()
+ {
+ GuidProperty = Guid.NewGuid();
+ }
+
+ public bool IsLocked { get; set; }
+
+ [Attr("description")]
+ public string Description { get; set; }
+
+ [Attr("ordinal")]
+ public long Ordinal { get; set; }
+
+ [Attr("guid-property")]
+ public Guid GuidProperty { get; set; }
+
+ [Attr("created-date")]
+ public DateTime CreatedDate { get; set; }
+
+ [Attr("achieved-date", isFilterable: false, isSortable: false)]
+ public DateTime? AchievedDate { get; set; }
+
+ [Attr("updated-date")]
+ public DateTime? UpdatedDate { get; set; }
+
+ [Attr("offset-date")]
+ public DateTimeOffset? OffsetDate { get; set; }
+ }
+}
diff --git a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
old mode 100755
new mode 100644
index efdaa68e5b..b387f93746
--- a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
+++ b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
@@ -1,24 +1,15 @@
-
+
$(NetCoreAppVersion)
+ InProcess
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Examples/NoEntityFrameworkExample/Program.cs b/src/Examples/NoEntityFrameworkExample/Program.cs
index 76f3020c52..9cd9c3ce22 100755
--- a/src/Examples/NoEntityFrameworkExample/Program.cs
+++ b/src/Examples/NoEntityFrameworkExample/Program.cs
@@ -1,4 +1,4 @@
-using Microsoft.AspNetCore;
+using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
namespace NoEntityFrameworkExample
@@ -7,12 +7,10 @@ public class Program
{
public static void Main(string[] args)
{
- BuildWebHost(args).Run();
+ CreateWebHostBuilder(args).Build().Run();
}
-
- public static IWebHost BuildWebHost(string[] args) =>
+ public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
- .UseStartup()
- .Build();
+ .UseStartup();
}
}
diff --git a/src/Examples/NoEntityFrameworkExample/Properties/launchSettings.json b/src/Examples/NoEntityFrameworkExample/Properties/launchSettings.json
index 310f04da95..1dff6cfe69 100644
--- a/src/Examples/NoEntityFrameworkExample/Properties/launchSettings.json
+++ b/src/Examples/NoEntityFrameworkExample/Properties/launchSettings.json
@@ -8,16 +8,20 @@
}
},
"profiles": {
+ "NoEntityFrameworkExample": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:5000/"
+ },
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
- },
- "NoEntityFrameworkExample": {
- "commandName": "Project",
- "environmentVariables": {}
}
}
}
\ No newline at end of file
diff --git a/src/Examples/NoEntityFrameworkExample/Services/TodoItemService.cs b/src/Examples/NoEntityFrameworkExample/Services/TodoItemService.cs
index f68c056829..09078cda2c 100644
--- a/src/Examples/NoEntityFrameworkExample/Services/TodoItemService.cs
+++ b/src/Examples/NoEntityFrameworkExample/Services/TodoItemService.cs
@@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using JsonApiDotNetCore.Models;
using JsonApiDotNetCore.Services;
using Microsoft.Extensions.Configuration;
using Npgsql;
using Dapper;
using System.Data;
-using JsonApiDotNetCoreExample.Models;
+using NoEntityFrameworkExample.Models;
using System.Linq;
namespace NoEntityFrameworkExample.Services
@@ -20,7 +19,7 @@ public TodoItemService(IConfiguration config)
{
_connectionString = config.GetValue("Data:DefaultConnection");
}
-
+
private IDbConnection Connection
{
get
@@ -59,7 +58,7 @@ public Task