Skip to content
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
39 changes: 13 additions & 26 deletions JSONAPI.EntityFramework.Tests.TestWebApp/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web;
using System.Web.Http;
using System.Web.Http.Dispatcher;
using Autofac;
using Autofac.Integration.WebApi;
using JSONAPI.ActionFilters;
using JSONAPI.Core;
using JSONAPI.EntityFramework.ActionFilters;
using JSONAPI.EntityFramework.Tests.TestWebApp.Models;
using JSONAPI.Http;
using JSONAPI.Json;
using Microsoft.Owin;
using Owin;

Expand Down Expand Up @@ -62,32 +56,25 @@ public void Configuration(IAppBuilder app)

private static HttpConfiguration GetWebApiConfiguration()
{
var config = new HttpConfiguration();

var pluralizationService = new PluralizationService();
var modelManager = new ModelManager(pluralizationService);
modelManager.RegisterResourceType(typeof(Comment));
modelManager.RegisterResourceType(typeof(Post));
modelManager.RegisterResourceType(typeof(Tag));
modelManager.RegisterResourceType(typeof(User));
modelManager.RegisterResourceType(typeof(UserGroup));

var formatter = new JsonApiFormatter(modelManager);
config.Formatters.Clear();
config.Formatters.Add(formatter);
var httpConfig = new HttpConfiguration();

// Global filters
config.Filters.Add(new EnumerateQueryableAsyncAttribute());
config.Filters.Add(new EnableSortingAttribute(modelManager));
config.Filters.Add(new EnableFilteringAttribute(modelManager));
// Configure JSON API
new JsonApiConfiguration()
.PluralizeResourceTypesWith(pluralizationService)
.UseEntityFramework()
.RegisterResourceType(typeof(Comment))
.RegisterResourceType(typeof(Post))
.RegisterResourceType(typeof(Tag))
.RegisterResourceType(typeof(User))
.RegisterResourceType(typeof(UserGroup))
.Apply(httpConfig);

// Override controller selector
config.Services.Replace(typeof(IHttpControllerSelector), new PascalizedControllerSelector(config));

// Web API routes
config.Routes.MapHttpRoute("DefaultApi", "{controller}/{id}", new { id = RouteParameter.Optional });
httpConfig.Routes.MapHttpRoute("DefaultApi", "{controller}/{id}", new { id = RouteParameter.Optional });

return config;
return httpConfig;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Data.Common;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
Expand All @@ -20,7 +19,7 @@
namespace JSONAPI.EntityFramework.Tests.ActionFilters
{
[TestClass]
public class EnumerateQueryableAsyncAttributeTests
public class AsynchronousEnumerationTransformerTests
{
public class Dummy
{
Expand Down Expand Up @@ -54,7 +53,7 @@ public void SetupFixtures()
}.AsQueryable();
}

private HttpActionExecutedContext CreateActionExecutedContext(IDbAsyncEnumerator<Dummy> asyncEnumerator)
private IQueryable<Dummy> CreateQueryable(IDbAsyncEnumerator<Dummy> asyncEnumerator)
{
var mockSet = new Mock<DbSet<Dummy>>();
mockSet.As<IDbAsyncEnumerable<Dummy>>()
Expand All @@ -69,39 +68,17 @@ private HttpActionExecutedContext CreateActionExecutedContext(IDbAsyncEnumerator
mockSet.As<IQueryable<Dummy>>().Setup(m => m.ElementType).Returns(_fixtures.ElementType);
mockSet.As<IQueryable<Dummy>>().Setup(m => m.GetEnumerator()).Returns(_fixtures.GetEnumerator());

var formatter = new JsonMediaTypeFormatter();

var httpContent = new ObjectContent(typeof(IQueryable<Dummy>), mockSet.Object, formatter);

return new HttpActionExecutedContext
{
ActionContext = new HttpActionContext
{
ControllerContext = new HttpControllerContext
{
Request = new HttpRequestMessage(HttpMethod.Get, "http://api.example.com/dummies")
}
},
Response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = httpContent
}
};
return mockSet.Object;
}

[TestMethod]
public async Task ResolvesQueryable()
{
var actionFilter = new EnumerateQueryableAsyncAttribute();

var context = CreateActionExecutedContext(new TestDbAsyncEnumerator<Dummy>(_fixtures.GetEnumerator()));

await actionFilter.OnActionExecutedAsync(context, new CancellationToken());
var transformer = new AsynchronousEnumerationTransformer();

var objectContent = context.Response.Content as ObjectContent;
objectContent.Should().NotBeNull();
var query = CreateQueryable(new TestDbAsyncEnumerator<Dummy>(_fixtures.GetEnumerator()));

var array = objectContent.Value as Dummy[];
var array = await transformer.Enumerate(query, new CancellationToken());
array.Should().NotBeNull();
array.Length.Should().Be(3);
array[0].Id.Should().Be("1");
Expand All @@ -112,16 +89,16 @@ public async Task ResolvesQueryable()
[TestMethod]
public void CancelsProperly()
{
var actionFilter = new EnumerateQueryableAsyncAttribute();
var actionFilter = new AsynchronousEnumerationTransformer();

var context = CreateActionExecutedContext(new WaitsUntilCancellationDbAsyncEnumerator<Dummy>(1000, _fixtures.GetEnumerator()));
var context = CreateQueryable(new WaitsUntilCancellationDbAsyncEnumerator<Dummy>(1000, _fixtures.GetEnumerator()));

var cts = new CancellationTokenSource();
cts.CancelAfter(300);

Func<Task> action = async () =>
{
await actionFilter.OnActionExecutedAsync(context, cts.Token);
await actionFilter.Enumerate(context, cts.Token);
};
action.ShouldThrow<TaskCanceledException>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
<Compile Include="Acceptance\PostsTests.cs" />
<Compile Include="Acceptance\AcceptanceTestsBase.cs" />
<Compile Include="Acceptance\SortingTests.cs" />
<Compile Include="ActionFilters\EnumerateQueryableAsyncAttributeTests.cs" />
<Compile Include="ActionFilters\AsynchronousEnumerationTransformerTests.cs" />
<Compile Include="EntityFrameworkMaterializerTests.cs" />
<Compile Include="Helpers\TestDbAsyncEnumerable.cs" />
<Compile Include="Helpers\WaitsUntilCancellationDbAsyncEnumerator.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Data.Entity;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using JSONAPI.ActionFilters;

namespace JSONAPI.EntityFramework.ActionFilters
{
/// <summary>
/// Enumerates an IQueryable asynchronously using Entity Framework's ToArrayAsync() method.
/// </summary>
public class AsynchronousEnumerationTransformer : IQueryableEnumerationTransformer
{
private readonly Lazy<MethodInfo> _toArrayAsyncMethod = new Lazy<MethodInfo>(() =>
typeof(QueryableExtensions).GetMethods().FirstOrDefault(x => x.Name == "ToArrayAsync" && x.GetParameters().Count() == 2));

public async Task<T[]> Enumerate<T>(IQueryable<T> query, CancellationToken cancellationToken)
{
var queryableElementType = typeof (T);
var openToArrayAsyncMethod = _toArrayAsyncMethod.Value;
var toArrayAsyncMethod = openToArrayAsyncMethod.MakeGenericMethod(queryableElementType);
var invocation = (dynamic)toArrayAsyncMethod.Invoke(null, new object[] { query, cancellationToken });

var resultArray = await invocation;
return resultArray;
}
}
}

This file was deleted.

3 changes: 2 additions & 1 deletion JSONAPI.EntityFramework/JSONAPI.EntityFramework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,11 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ActionFilters\EnumerateQueryableAsyncAttribute.cs" />
<Compile Include="ActionFilters\AsynchronousEnumerationTransformer.cs" />
<Compile Include="EntityFrameworkMaterializer.cs" />
<Compile Include="EntityFrameworkMaterializer_Util.cs" />
<Compile Include="Http\ApiController.cs" />
<Compile Include="JsonApiConfigurationExtensions.cs" />
<Compile Include="PluralizationService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
Expand Down
23 changes: 23 additions & 0 deletions JSONAPI.EntityFramework/JsonApiConfigurationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using JSONAPI.Core;
using JSONAPI.EntityFramework.ActionFilters;

namespace JSONAPI.EntityFramework
{
/// <summary>
/// Extension Methods for JSONAPI.JsonApiConfiguration
/// </summary>
public static class JsonApiConfigurationExtensions
{
/// <summary>
/// Add Entity Framework specific handling to the configuration
/// </summary>
/// <param name="jsonApiConfig">The configuration object to modify</param>
/// <returns>The same configuration object that was passed in</returns>
public static JsonApiConfiguration UseEntityFramework(this JsonApiConfiguration jsonApiConfig)
{
jsonApiConfig.EnumerateQueriesWith(new AsynchronousEnumerationTransformer());

return jsonApiConfig;
}
}
}
Loading