mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-06-20 02:38:15 +08:00
fix: 🐛 操作日志不显示userName (#141)
[skip ci] Co-authored-by: tk <fiyne1a@dingtalk.com>
This commit is contained in:
@ -10,11 +10,6 @@ public interface IFieldCreatedClient
|
||||
/// </summary>
|
||||
int? CreatedClientIp { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者来源地址
|
||||
/// </summary>
|
||||
string CreatedReferer { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者客户端用户代理
|
||||
/// </summary>
|
||||
|
@ -1,5 +1,16 @@
|
||||
using NetAdmin.Domain.Attributes;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract record SimpleEntity : SimpleEntity<long>
|
||||
{
|
||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
[Snowflake]
|
||||
public override long Id { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 简单实体
|
||||
/// </summary>
|
||||
|
@ -31,7 +31,7 @@ public record Sys_JobRecord : LiteImmutableEntity
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public virtual int HttpStatusCode { get; init; }
|
||||
public int HttpStatusCode { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 拥有者信息
|
||||
|
@ -8,9 +8,10 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// </summary>
|
||||
[Index(Chars.FLG_DB_INDEX_PREFIX + nameof(ApiId), nameof(ApiId), false)]
|
||||
[Index(Chars.FLG_DB_INDEX_PREFIX + nameof(CreatedTime), nameof(CreatedTime), false)]
|
||||
[Index(Chars.FLG_DB_INDEX_PREFIX + nameof(UserId), nameof(UserId), false)]
|
||||
[Index(Chars.FLG_DB_INDEX_PREFIX + nameof(HttpStatusCode), nameof(HttpStatusCode), false)]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_RequestLog))]
|
||||
public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
||||
public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldCreatedClient
|
||||
{
|
||||
/// <summary>
|
||||
/// 接口
|
||||
@ -26,23 +27,17 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
||||
[JsonIgnore]
|
||||
public virtual string ApiId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者客户端IP
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[Column(Position = -1)]
|
||||
[JsonIgnore]
|
||||
public int? CreatedClientIp { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者来源地址
|
||||
/// </summary>
|
||||
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
/// <inheritdoc />
|
||||
[Column(ServerTime = DateTimeKind.Local, CanUpdate = false, Position = -1)]
|
||||
[JsonIgnore]
|
||||
public string CreatedReferer { get; init; }
|
||||
public virtual DateTime CreatedTime { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者客户端用户代理
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
#if DBTYPE_SQLSERVER
|
||||
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_1022)]
|
||||
#else
|
||||
@ -76,17 +71,6 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
||||
[JsonIgnore]
|
||||
public virtual string Exception { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 附加数据
|
||||
/// </summary>
|
||||
#if DBTYPE_SQLSERVER
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||
#else
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
#endif
|
||||
[JsonIgnore]
|
||||
public virtual string ExtraData { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// HTTP状态码
|
||||
/// </summary>
|
||||
@ -101,13 +85,6 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
||||
[JsonIgnore]
|
||||
public virtual string Method { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 来源地址
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string ReferUrl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求内容
|
||||
/// </summary>
|
||||
@ -179,4 +156,18 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public virtual int? ServerIp { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(UserId))]
|
||||
public Sys_User User { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户编号
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public virtual long? UserId { get; init; }
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.RequestLog;
|
||||
|
||||
@ -13,6 +14,11 @@ public sealed record QueryRequestLogRsp : Sys_RequestLog, IRegister
|
||||
/// </summary>
|
||||
public new string CreatedClientIp => base.CreatedClientIp?.ToIpV4();
|
||||
|
||||
/// <summary>
|
||||
/// 登录名
|
||||
/// </summary>
|
||||
public string LoginName => RequestBody?.ToObject<LoginByPwdReq>()?.Account;
|
||||
|
||||
/// <summary>
|
||||
/// 操作系统
|
||||
/// </summary>
|
||||
@ -35,10 +41,6 @@ public sealed record QueryRequestLogRsp : Sys_RequestLog, IRegister
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string CreatedUserAgent { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldCreatedUser.CreatedUserName" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string CreatedUserName { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_RequestLog.Duration" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Duration { get; init; }
|
||||
@ -51,10 +53,6 @@ public sealed record QueryRequestLogRsp : Sys_RequestLog, IRegister
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Exception { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_RequestLog.ExtraData" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string ExtraData { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_RequestLog.HttpStatusCode" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override int HttpStatusCode { get; init; }
|
||||
@ -63,10 +61,6 @@ public sealed record QueryRequestLogRsp : Sys_RequestLog, IRegister
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Method { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_RequestLog.ReferUrl" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string ReferUrl { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_RequestLog.RequestBody" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string RequestBody { get; init; }
|
||||
@ -99,6 +93,13 @@ public sealed record QueryRequestLogRsp : Sys_RequestLog, IRegister
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override int? ServerIp { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_RequestLog.User" />
|
||||
public new QueryUserRsp User { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_RequestLog.UserId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override long? UserId { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
|
@ -7,17 +7,10 @@ namespace NetAdmin.Host.Utils;
|
||||
/// <summary>
|
||||
/// 请求日志记录器
|
||||
/// </summary>
|
||||
public sealed class RequestLogger(
|
||||
ILogger<RequestLogger> logger
|
||||
, IOptions<SpecificationDocumentSettingsOptions> specificationDocumentSettingsOptions
|
||||
, IEventPublisher eventPublisher) : ISingleton
|
||||
public sealed class RequestLogger(ILogger<RequestLogger> logger, IEventPublisher eventPublisher) : ISingleton
|
||||
{
|
||||
private static readonly string[] _textContentTypes = ["text", "json", "xml", "urlencoded"];
|
||||
|
||||
private readonly int _tokenPrefixLength
|
||||
= specificationDocumentSettingsOptions?.Value.SecurityDefinitions?[0]?.Scheme?.Length + 1 ??
|
||||
0; // eg. "Bearer ";
|
||||
|
||||
/// <summary>
|
||||
/// 生成审计数据
|
||||
/// </summary>
|
||||
@ -30,7 +23,6 @@ public sealed class RequestLogger(
|
||||
var auditData = new CreateRequestLogReq {
|
||||
Duration = duration
|
||||
, Method = context.Request.Method
|
||||
, ReferUrl = context.Request.GetRefererUrlAddress()
|
||||
, RequestContentType = context.Request.ContentType
|
||||
, RequestBody = Array.Exists( //
|
||||
_textContentTypes
|
||||
@ -50,8 +42,7 @@ public sealed class RequestLogger(
|
||||
, HttpStatusCode = context.Response.StatusCode
|
||||
, ErrorCode = errorCode
|
||||
, Exception = exception?.Error.ToString()
|
||||
, CreatedUserId = associatedUser?.UserId
|
||||
, CreatedUserName = associatedUser?.UserName
|
||||
, UserId = associatedUser?.UserId
|
||||
, CreatedUserAgent = context.Request.Headers.UserAgent.ToString()
|
||||
, CreatedClientIp = context.GetRealIpAddress()
|
||||
?.MapToIPv4()
|
||||
@ -77,8 +68,9 @@ public sealed class RequestLogger(
|
||||
|
||||
ContextUserToken userToken = null;
|
||||
try {
|
||||
var jsonWebToken = JWTEncryption.ReadJwtToken(token[_tokenPrefixLength..]);
|
||||
var claim = jsonWebToken?.Claims.FirstOrDefault(y => y.Type == nameof(ContextUserToken));
|
||||
var jsonWebToken
|
||||
= JWTEncryption.ReadJwtToken(token.TrimStart($"{Chars.FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA} "));
|
||||
var claim = jsonWebToken?.Claims.FirstOrDefault(y => y.Type == nameof(ContextUserToken));
|
||||
userToken = claim?.Value.ToObject<ContextUserToken>();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
@ -63,13 +63,6 @@ public sealed class SqlAuditor : ISingleton
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetCreatedReferer(AuditValueEventArgs e)
|
||||
{
|
||||
if (e.Value is null or "") {
|
||||
e.Value = App.HttpContext?.Request.GetRefererUrlAddress();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetCreatedTime(AuditValueEventArgs e)
|
||||
{
|
||||
if (e.Value == null || (e.Value is DateTime val && val == default)) {
|
||||
@ -119,9 +112,6 @@ public sealed class SqlAuditor : ISingleton
|
||||
case nameof(IFieldCreatedClient.CreatedUserAgent):
|
||||
SetCreatedUserAgent(e);
|
||||
break;
|
||||
case nameof(IFieldCreatedClient.CreatedReferer):
|
||||
SetCreatedReferer(e);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ public static class Chars
|
||||
public const string FLG_HTTP_METHOD_POST = "POST";
|
||||
public const string FLG_HTTP_METHOD_PUT = "PUT";
|
||||
public const string FLG_HTTP_METHOD_TRACE = "TRACE";
|
||||
public const string FLG_PATH_API_SYS_USER_LOGIN_BY_PWD = "api/sys/user/login.by.pwd";
|
||||
public const string FLG_PATH_PREFIX_HEALTH_CHECK = "probe/health.check";
|
||||
public const string FLG_RANDOM_UNAME_PWD = "VcXlp7WY";
|
||||
public const string FLG_REDIS_INSTANCE_DATA_CACHE = "DataCache";
|
||||
|
@ -9,9 +9,9 @@
|
||||
<PackageReference Include="Cronos" Version="0.8.4"/>
|
||||
<PackageReference Include="FreeSql.DbContext.NS" Version="3.2.821-ns1"/>
|
||||
<PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.821-ns1"/>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.3"/>
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.3-ns1"/>
|
||||
<PackageReference Include="Furion.Pure.NS" Version="4.9.3-ns1"/>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.4"/>
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.4-ns1"/>
|
||||
<PackageReference Include="Furion.Pure.NS" Version="4.9.4-ns1"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0-preview.4.24267.6"/>
|
||||
<PackageReference Include="Minio" Version="6.0.2"/>
|
||||
<PackageReference Include="NSExt" Version="2.1.0"/>
|
||||
|
@ -12,6 +12,8 @@ namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo) //
|
||||
: RepositoryService<Sys_RequestLog, long, IRequestLogService>(rpo), IRequestLogService
|
||||
{
|
||||
private static readonly Regex _regex = new(Chars.RGXL_IP_V4);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
@ -134,26 +136,45 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
|
||||
public async Task<PagedQueryRsp<QueryRequestLogRsp>> PagedQueryAsync(PagedQueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.Count(out var total)
|
||||
.ToListAsync(a => new {
|
||||
a.ApiId
|
||||
, ApiSummary = a.Api.Summary
|
||||
, a.ExtraData
|
||||
, a.CreatedClientIp
|
||||
, a.CreatedTime
|
||||
, a.CreatedUserName
|
||||
, a.Duration
|
||||
, a.Method
|
||||
, a.CreatedUserAgent
|
||||
, a.HttpStatusCode
|
||||
, a.Id
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
var select = QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.Count(out var total);
|
||||
object list = req.DynamicFilter?.Filters?.Exists(
|
||||
x => nameof(QueryRequestLogReq.ApiId).Equals(x.Field, StringComparison.OrdinalIgnoreCase) &&
|
||||
Chars.FLG_PATH_API_SYS_USER_LOGIN_BY_PWD.Equals( //
|
||||
x.Value.ToString(), StringComparison.OrdinalIgnoreCase)) ?? false
|
||||
? await select.ToListAsync(a => new {
|
||||
a.ApiId
|
||||
, ApiSummary = a.Api.Summary
|
||||
, a.CreatedClientIp
|
||||
, a.CreatedTime
|
||||
, a.Duration
|
||||
, a.Method
|
||||
, a.CreatedUserAgent
|
||||
, a.HttpStatusCode
|
||||
, a.Id
|
||||
, a.UserId
|
||||
, a.User
|
||||
, a.RequestBody
|
||||
})
|
||||
.ConfigureAwait(false)
|
||||
: await select.ToListAsync(a => new {
|
||||
a.ApiId
|
||||
, ApiSummary = a.Api.Summary
|
||||
, a.CreatedClientIp
|
||||
, a.CreatedTime
|
||||
, a.Duration
|
||||
, a.Method
|
||||
, a.CreatedUserAgent
|
||||
, a.HttpStatusCode
|
||||
, a.Id
|
||||
, a.UserId
|
||||
, a.User
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return new PagedQueryRsp<QueryRequestLogRsp>(req.Page, req.PageSize, total
|
||||
, list.Adapt<IEnumerable<QueryRequestLogRsp>>());
|
||||
@ -175,7 +196,18 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
|
||||
|
||||
private ISelect<Sys_RequestLog> QueryInternal(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.Include(a => a.Api).WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
var ret = Rpo.Select.Include(a => a.Api).Include(a => a.User).WhereDynamicFilter(req.DynamicFilter);
|
||||
if (req.Filter?.Id is not 0) {
|
||||
ret = ret.WhereDynamic(req.Filter);
|
||||
}
|
||||
|
||||
if (req.Keywords?.Length > 0) {
|
||||
ret = _regex.IsMatch(req.Keywords)
|
||||
? ret.Where(a => a.CreatedClientIp == req.Keywords.IpV4ToInt32())
|
||||
: ret.Where(a => a.Id == req.Keywords.Int64Try(0) || a.UserId == req.Keywords.Int64Try(0) ||
|
||||
a.User.UserName == req.Keywords || a.RequestBody.Contains(req.Keywords));
|
||||
}
|
||||
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
|
@ -1,5 +1,3 @@
|
||||
using NetAdmin.Domain.Dto.Sys.RequestLog;
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
using NetAdmin.Domain.Events.Sys;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
@ -27,22 +25,7 @@ public sealed class OperationLogger : IEventSubscriber
|
||||
return;
|
||||
}
|
||||
|
||||
CreateRequestLogReq logReq = null;
|
||||
|
||||
// 登录日志特殊处理
|
||||
if (operationEvent.Data.ApiId.Equals("api/sys/user/login.by.pwd", StringComparison.OrdinalIgnoreCase)) {
|
||||
try {
|
||||
var loginReq = operationEvent.Data.RequestBody.ToObject<LoginByPwdReq>();
|
||||
logReq = operationEvent.Data with { ExtraData = loginReq.Account };
|
||||
}
|
||||
catch {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
logReq ??= operationEvent.Data;
|
||||
var logService = App.GetService<IRequestLogService>();
|
||||
logReq.TruncateStrings();
|
||||
_ = await logService.CreateAsync(logReq).ConfigureAwait(false);
|
||||
operationEvent.Data.TruncateStrings();
|
||||
_ = await App.GetService<IRequestLogService>().CreateAsync(operationEvent.Data).ConfigureAwait(false);
|
||||
}
|
||||
}
|
@ -15,10 +15,8 @@ public abstract class WebApiTestBase<T>(WebApplicationFactory<T> factory, ITestO
|
||||
: IClassFixture<WebApplicationFactory<T>>
|
||||
where T : AppStartup
|
||||
{
|
||||
private const string _ACCOUNT = "root";
|
||||
private const string _API_SYS_USER_LOGIN_BY_PWD = "/api/sys/user/login.by.pwd";
|
||||
private const string _AUTH_SCHEMA = "Bearer";
|
||||
private const string _PASSWORD = "1234qwer";
|
||||
private const string _ACCOUNT = "root";
|
||||
private const string _PASSWORD = "1234qwer";
|
||||
private string _accessToken;
|
||||
|
||||
/// <summary>
|
||||
@ -28,7 +26,7 @@ public abstract class WebApiTestBase<T>(WebApplicationFactory<T> factory, ITestO
|
||||
{
|
||||
var client = factory.CreateClient();
|
||||
if (_accessToken == null) {
|
||||
var loginRsp = await client.PostAsync(_API_SYS_USER_LOGIN_BY_PWD
|
||||
var loginRsp = await client.PostAsync(Chars.FLG_PATH_API_SYS_USER_LOGIN_BY_PWD
|
||||
, JsonContent.Create(
|
||||
new LoginByPwdReq { Password = _PASSWORD, Account = _ACCOUNT }))
|
||||
.ConfigureAwait(false);
|
||||
@ -37,7 +35,8 @@ public abstract class WebApiTestBase<T>(WebApplicationFactory<T> factory, ITestO
|
||||
_accessToken = loginRspObj.Data.AccessToken;
|
||||
}
|
||||
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(_AUTH_SCHEMA, _accessToken);
|
||||
client.DefaultRequestHeaders.Authorization
|
||||
= new AuthenticationHeaderValue(Chars.FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA, _accessToken);
|
||||
var ret = await client.PostAsync(url, content).ConfigureAwait(false);
|
||||
testOutputHelper.WriteLine(await ret.Content.ReadAsStringAsync().ConfigureAwait(false));
|
||||
return ret;
|
||||
|
Reference in New Issue
Block a user