using CsvHelper;
using Microsoft.Net.Http.Headers;
using NetAdmin.Application.Repositories;
using NetAdmin.Application.Services;
using NetAdmin.Domain.Dto.Dependency;
using NetAdmin.Domain.Dto.Sys.Api;
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
namespace NetAdmin.SysComponent.Application.Services.Sys;
///
public sealed class ApiService(
BasicRepository rpo //
, XmlCommentReader xmlCommentReader //
, IActionDescriptorCollectionProvider actionDescriptorCollectionProvider) //
: RepositoryService(rpo), IApiService
{
///
public Task BulkDeleteAsync(BulkReq req)
{
req.ThrowIfInvalid();
throw new NotImplementedException();
}
///
public Task CountAsync(QueryReq req)
{
req.ThrowIfInvalid();
return QueryInternal(req)
#if DBTYPE_SQLSERVER
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#endif
.CountAsync();
}
///
public Task CreateAsync(CreateApiReq req)
{
req.ThrowIfInvalid();
throw new NotImplementedException();
}
///
public Task DeleteAsync(DelReq req)
{
req.ThrowIfInvalid();
throw new NotImplementedException();
}
///
public Task ExistAsync(QueryReq req)
{
req.ThrowIfInvalid();
return QueryInternal(req)
#if DBTYPE_SQLSERVER
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#endif
.AnyAsync();
}
///
public async Task ExportAsync(QueryReq req)
{
req.ThrowIfInvalid();
var data = await QueryInternal(req)
#if DBTYPE_SQLSERVER
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#endif
.Take(Numbers.MAX_LIMIT_EXPORT)
.ToListAsync()
.ConfigureAwait(false);
var list = data.Adapt>();
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
csv.WriteHeader();
await csv.NextRecordAsync().ConfigureAwait(false);
foreach (var item in list) {
csv.WriteRecord(item);
await csv.NextRecordAsync().ConfigureAwait(false);
}
await csv.FlushAsync().ConfigureAwait(false);
_ = stream.Seek(0, SeekOrigin.Begin);
App.HttpContext.Response.Headers.ContentDisposition
= new ContentDispositionHeaderValue(Chars.FLG_HTTP_HEADER_VALUE_ATTACHMENT) {
FileNameStar = $"{Ln.接口导出}_{DateTime.Now:yyyy.MM.dd-HH.mm.ss}.csv"
}.ToString();
return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM);
}
///
public Task GetAsync(QueryApiReq req)
{
req.ThrowIfInvalid();
throw new NotImplementedException();
}
///
public Task> PagedQueryAsync(PagedQueryReq req)
{
req.ThrowIfInvalid();
throw new NotImplementedException();
}
///
public async Task> QueryAsync(QueryReq req)
{
req.ThrowIfInvalid();
var ret = await Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
.WhereDynamic(req.Filter)
.ToTreeListAsync()
.ConfigureAwait(false);
return ret.Adapt>();
}
///
public IEnumerable ReflectionList(bool excludeAnonymous = true)
{
var regex = new Regex(@"\.(\w+)$", RegexOptions.Compiled);
var actionDescriptors //
= actionDescriptorCollectionProvider.ActionDescriptors.Items.Cast();
if (excludeAnonymous) {
actionDescriptors = actionDescriptors.Where(x => x.EndpointMetadata.All(y => y is AllowAnonymousAttribute));
}
var actionGroup //
= actionDescriptors.GroupBy(x => x.ControllerTypeInfo);
return actionGroup.Select(SelectQueryApiRsp);
QueryApiRsp SelectQueryApiRsp(IGrouping group)
{
var first = group.First()!;
return new QueryApiRsp {
Summary = xmlCommentReader.GetComments(group.Key)
, Name = first.ControllerName
, Id = Regex.Replace( //
first.AttributeRouteInfo!.Template!, $"/{first.ActionName}$", string.Empty)
, Children = GetChildren(group)
, Namespace = regex.Match(group.Key.Namespace!).Groups[1].Value.ToLowerInvariant()
};
}
}
///
public async Task SyncAsync()
{
_ = await Rpo.DeleteAsync(_ => true).ConfigureAwait(false);
var list = ReflectionList(false);
EnableCascadeSave = true;
foreach (var item in list) {
var entity = item.Adapt();
_ = await Rpo.InsertAsync(entity).ConfigureAwait(false);
}
}
private IEnumerable GetChildren(IEnumerable actionDescriptors)
{
return actionDescriptors //
.Select(x => new QueryApiRsp {
Summary = xmlCommentReader.GetComments(x.MethodInfo)
, Name = x.ActionName
, Id = x.AttributeRouteInfo!.Template
, Method = x.ActionConstraints?.OfType()
.FirstOrDefault()
?.HttpMethods.First()
});
}
private ISelect QueryInternal(QueryReq req)
{
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
switch (req.Order) {
case Orders.None:
return ret;
case Orders.Random:
return ret.OrderByRandom();
}
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
if (!req.Prop?.Equals(nameof(req.Filter.CreatedTime), StringComparison.OrdinalIgnoreCase) ?? true) {
ret = ret.OrderByDescending(a => a.CreatedTime);
}
return ret;
}
}