This commit is contained in:
David Lebee
2021-02-02 12:19:59 -05:00
parent b9fbe5aca1
commit 20df5ce79d
16 changed files with 220 additions and 15 deletions
@@ -0,0 +1,40 @@
using Microsoft.AspNetCore.Mvc;
using PoweredSoft.CQRS.Abstractions;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace PoweredSoft.CQRS.AspNetCore.Mvc
{
[ApiController, Route("api/command/[controller]")]
public class CommandController<TCommand> : Controller
where TCommand : class
{
[HttpPost]
public async Task<IActionResult> Handle([FromServices] ICommandHandler<TCommand> handler,
[FromBody] TCommand command)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
await handler.HandleAsync(command, this.Request.HttpContext.RequestAborted);
return Ok();
}
}
[ApiController, Route("api/command/[controller]")]
public class CommandController<TCommand, TTCommandResult> : Controller
where TCommand : class
{
[HttpPost]
public async Task<ActionResult<TTCommandResult>> Handle([FromServices] ICommandHandler<TCommand, TTCommandResult> handler,
[FromBody] TCommand command)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
return Ok(await handler.HandleAsync(command, this.Request.HttpContext.RequestAborted));
}
}
}
@@ -0,0 +1,28 @@
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.DependencyInjection;
using PoweredSoft.CQRS.Abstractions.Discovery;
using System;
namespace PoweredSoft.CQRS.AspNetCore.Mvc
{
public class QueryControllerConvention : IControllerModelConvention
{
private readonly IServiceProvider serviceProvider;
public QueryControllerConvention(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public void Apply(ControllerModel controller)
{
if (controller.ControllerType.IsGenericType && controller.ControllerType.Name.Contains("QueryController") && controller.ControllerType.Assembly == typeof(QueryControllerConvention).Assembly)
{
var genericType = controller.ControllerType.GenericTypeArguments[0];
var queryDiscovery = this.serviceProvider.GetRequiredService<IQueryDiscovery>();
var query = queryDiscovery.FindQuery(genericType);
controller.ControllerName = query.Name;
}
}
}
}
@@ -0,0 +1,46 @@
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.DependencyInjection;
using PoweredSoft.CQRS.Abstractions.Discovery;
using PoweredSoft.CQRS.AspNetCore.Abstractions.Attributes;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace PoweredSoft.CQRS.AspNetCore.Mvc
{
public class CommandControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
{
private readonly ServiceProvider serviceProvider;
public CommandControllerFeatureProvider(ServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
{
var commandDiscovery = this.serviceProvider.GetRequiredService<ICommandDiscovery>();
foreach (var f in commandDiscovery.GetCommands())
{
var ignoreAttribute = f.CommandType.GetCustomAttribute<CommandControllerIgnoreAttribute>();
if (ignoreAttribute != null)
continue;
if (f.CommandResultType == null)
{
var controllerType = typeof(CommandController<>).MakeGenericType(f.CommandType);
var controllerTypeInfo = controllerType.GetTypeInfo();
feature.Controllers.Add(controllerTypeInfo);
}
else
{
var controllerType = typeof(CommandController<,>).MakeGenericType(f.CommandType, f.CommandResultType);
var controllerTypeInfo = controllerType.GetTypeInfo();
feature.Controllers.Add(controllerTypeInfo);
}
}
}
}
}
@@ -0,0 +1,7 @@
namespace PoweredSoft.CQRS.AspNetCore.Mvc
{
public class CommandControllerOptions
{
}
}
@@ -12,10 +12,14 @@ namespace PoweredSoft.CQRS.AspNetCore.Mvc
where TQuery : class
{
[HttpPost]
public Task<TQueryResult> Handle([FromServices] IQueryHandler<TQuery, TQueryResult> handler,
public async Task<ActionResult<TQueryResult>> Handle([FromServices] IQueryHandler<TQuery, TQueryResult> handler,
[FromBody] TQuery query)
{
return handler.HandleAsync(query, this.Request.HttpContext.RequestAborted);
if (!ModelState.IsValid)
return BadRequest(ModelState);
return Ok(await handler.HandleAsync(query, this.Request.HttpContext.RequestAborted));
}
}
}
@@ -5,23 +5,23 @@ using System;
namespace PoweredSoft.CQRS.AspNetCore.Mvc
{
public class QueryControllerConvention : IControllerModelConvention
public class CommandControllerConvention : IControllerModelConvention
{
private readonly IServiceProvider serviceProvider;
public QueryControllerConvention(IServiceProvider serviceProvider)
public CommandControllerConvention(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public void Apply(ControllerModel controller)
{
if (controller.ControllerType.IsGenericType && controller.ControllerType.Name.Contains("QueryController") && controller.ControllerType.Assembly == typeof(QueryControllerConvention).Assembly)
if (controller.ControllerType.IsGenericType && controller.ControllerType.Name.Contains("CommandController") && controller.ControllerType.Assembly == typeof(CommandControllerConvention).Assembly)
{
var genericType = controller.ControllerType.GenericTypeArguments[0];
var queryDiscovery = this.serviceProvider.GetRequiredService<IQueryDiscovery>();
var query = queryDiscovery.FindQuery(genericType);
controller.ControllerName = query.Name;
var commandDiscovery = this.serviceProvider.GetRequiredService<ICommandDiscovery>();
var command = commandDiscovery.FindCommand(genericType);
controller.ControllerName = command.Name;
}
}
}
@@ -17,7 +17,6 @@ namespace PoweredSoft.CQRS.AspNetCore.Mvc
return builder;
}
/*
public static IMvcBuilder AddPoweredSoftCommandController(this IMvcBuilder builder)
{
var services = builder.Services;
@@ -25,6 +24,6 @@ namespace PoweredSoft.CQRS.AspNetCore.Mvc
builder.AddMvcOptions(o => o.Conventions.Add(new CommandControllerConvention(serviceProvider)));
builder.ConfigureApplicationPartManager(m => m.FeatureProviders.Add(new CommandControllerFeatureProvider(serviceProvider)));
return builder;
}*/
}
}
}
@@ -10,6 +10,7 @@
<ItemGroup>
<ProjectReference Include="..\PoweredSoft.CQRS.Abstractions\PoweredSoft.CQRS.Abstractions.csproj" />
<ProjectReference Include="..\PoweredSoft.CQRS.AspNetCore.Abstractions\PoweredSoft.CQRS.AspNetCore.Abstractions.csproj" />
</ItemGroup>
</Project>