102 lines
3.7 KiB
C#
102 lines
3.7 KiB
C#
using Sozsoft.Platform.Domain.DeveloperKit;
|
|
using Sozsoft.Platform.Entities;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text.Json;
|
|
using System.Threading.Tasks;
|
|
using Volo.Abp;
|
|
using Volo.Abp.Application.Services;
|
|
using Volo.Abp.Domain.Repositories;
|
|
|
|
namespace Sozsoft.Platform.Application;
|
|
|
|
[RemoteService]
|
|
[Route("api/app/crudendpoint")]
|
|
public class CrudEndpointAppService : ApplicationService
|
|
{
|
|
private readonly IRepository<CrudEndpoint, Guid> _endpointRepository;
|
|
private readonly IDynamicEntityManager _dynamicManager;
|
|
|
|
public CrudEndpointAppService(
|
|
IRepository<CrudEndpoint, Guid> endpointRepository,
|
|
IDynamicEntityManager dynamicManager)
|
|
{
|
|
_endpointRepository = endpointRepository;
|
|
_dynamicManager = dynamicManager;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Every query string entry that is not a paging parameter is a column filter:
|
|
/// <c>?RoleId=…</c> compares for equality, <c>?Name.contains=…</c> applies the
|
|
/// named operator. The column names are validated against the table schema in
|
|
/// the manager, so an unknown column fails loudly instead of returning the
|
|
/// unfiltered collection.
|
|
/// </summary>
|
|
[HttpGet("{entityName}")]
|
|
public async Task<List<object>?> GetEntityListAsync(string entityName)
|
|
{
|
|
await EnsureEndpointAsync(entityName, "GET", "GetList");
|
|
return await _dynamicManager.GetEntityListAsync(entityName, ReadQueryFilters());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Route values are not filters, so only the query string is read. A repeated
|
|
/// parameter keeps its comma joined form, which is what the <c>in</c> operator
|
|
/// expects.
|
|
/// </summary>
|
|
private Dictionary<string, string?> ReadQueryFilters()
|
|
{
|
|
var filters = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
|
|
var query = LazyServiceProvider.LazyGetService<IHttpContextAccessor>()?.HttpContext?.Request?.Query;
|
|
if (query == null)
|
|
return filters;
|
|
|
|
foreach (var entry in query)
|
|
filters[entry.Key] = string.Join(",", entry.Value.ToArray());
|
|
|
|
return filters;
|
|
}
|
|
|
|
[HttpGet("{entityName}/{id}")]
|
|
public async Task<object?> GetEntityByIdAsync(string entityName, Guid id)
|
|
{
|
|
await EnsureEndpointAsync(entityName, "GET", "GetById");
|
|
return await _dynamicManager.GetEntityByIdAsync(entityName, id);
|
|
}
|
|
|
|
[HttpPost("{entityName}")]
|
|
public async Task<object?> CreateEntityAsync(string entityName, [FromBody] JsonElement data)
|
|
{
|
|
await EnsureEndpointAsync(entityName, "POST", "Create");
|
|
return await _dynamicManager.CreateEntityAsync(entityName, data);
|
|
}
|
|
|
|
[HttpPut("{entityName}/{id}")]
|
|
public async Task<object?> UpdateEntityAsync(string entityName, Guid id, [FromBody] JsonElement data)
|
|
{
|
|
await EnsureEndpointAsync(entityName, "PUT", "Update");
|
|
return await _dynamicManager.UpdateEntityAsync(entityName, id, data);
|
|
}
|
|
|
|
[HttpDelete("{entityName}/{id}")]
|
|
public async Task<bool> DeleteEntityAsync(string entityName, Guid id)
|
|
{
|
|
await EnsureEndpointAsync(entityName, "DELETE", "Delete");
|
|
return await _dynamicManager.DeleteEntityAsync(entityName, id);
|
|
}
|
|
|
|
private async Task EnsureEndpointAsync(string entityName, string method, string operation)
|
|
{
|
|
var exists = await _endpointRepository.AnyAsync(x =>
|
|
x.EntityName.ToLower() == entityName.ToLower() &&
|
|
x.Method == method &&
|
|
x.OperationType == operation &&
|
|
x.IsActive);
|
|
|
|
if (!exists)
|
|
throw new UserFriendlyException($"No active endpoint defined for {entityName} {operation}");
|
|
}
|
|
}
|
|
|