This commit is contained in:
2018-10-04 00:16:17 +00:00
parent f95dc34b41
commit 0f9ac2600c
20 changed files with 127 additions and 145 deletions

View File

@@ -50,6 +50,7 @@ IMMEDIATE ITEMS:
- Delete children in User object: I don't like it this way, the children would all be common to another biz object so instead I would like to see it call the other object, not directly issue sql changes
(right now the user deletes the tag maps directly, this is just wrong)
- NAMING is it dbObj, o, inObj? Go through and consistivize
- Widgetcontroller and UserController POST, move check for authorized rights into biz object
- Auto visible id number assigning code
- Give widgets a visible ID number scheme and add to tests

View File

@@ -187,7 +187,7 @@ namespace AyaNova.Api.Controllers
await ct.SaveChangesAsync();
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, o.Id, AyaType.Locale, AyaEvent.Created), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, o.Id, AyaType.Locale, AyaEvent.Created), ct);
await ct.SaveChangesAsync();
return CreatedAtAction("GetLocale", new { id = o.Id }, new ApiCreatedResponse(o));
@@ -247,7 +247,7 @@ namespace AyaNova.Api.Controllers
}
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, oDbParent.Id, AyaType.Locale, AyaEvent.Modified), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, oDbParent.Id, AyaType.Locale, AyaEvent.Modified), ct);
try
{
@@ -317,7 +317,7 @@ namespace AyaNova.Api.Controllers
}
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, oFromDb.Id, AyaType.Locale, AyaEvent.Modified), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, oFromDb.Id, AyaType.Locale, AyaEvent.Modified), ct);
try
{
@@ -387,7 +387,7 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(biz.Errors));
}
//Log
EventLogProcessor.DeleteObject(biz.userId, AyaType.Locale, dbObj.Id, dbObj.Name, ct);
EventLogProcessor.DeleteObject(biz.UserId, AyaType.Locale, dbObj.Id, dbObj.Name, ct);
await ct.SaveChangesAsync();
//Delete children / attached objects

View File

@@ -141,8 +141,11 @@ namespace AyaNova.Api.Controllers
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
}
//Instantiate the business object handler
TagBiz biz = new TagBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items));
//If a user has change roles, or editOwnRoles then they can create, true is passed for isOwner since they are creating so by definition the owner
if (!Authorized.IsAuthorizedToCreate(HttpContext.Items, AyaType.Tag))
if (!Authorized.IsAuthorizedToCreate(HttpContext.Items, TagBiz.BizType))
{
return StatusCode(401, new ApiNotAuthorizedResponse());
}
@@ -152,8 +155,7 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(ModelState));
}
//Instantiate the business object handler
TagBiz biz = new TagBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items));
//Create and validate
Tag o = await biz.CreateAsync(inObj.Name);
@@ -169,7 +171,7 @@ namespace AyaNova.Api.Controllers
await ct.SaveChangesAsync();
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, o.Id, AyaType.Tag, AyaEvent.Created), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, o.Id, AyaType.Tag, AyaEvent.Created), ct);
await ct.SaveChangesAsync();
return CreatedAtAction("GetTag", new { id = o.Id }, new ApiCreatedResponse(o));
@@ -222,7 +224,7 @@ namespace AyaNova.Api.Controllers
}
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, oFromDb.Id, AyaType.Tag, AyaEvent.Modified), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, oFromDb.Id, AyaType.Tag, AyaEvent.Modified), ct);
try
{
@@ -294,7 +296,7 @@ namespace AyaNova.Api.Controllers
}
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, oFromDb.Id, AyaType.Tag, AyaEvent.Modified), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, oFromDb.Id, AyaType.Tag, AyaEvent.Modified), ct);
try
{
@@ -407,7 +409,7 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(biz.Errors));
}
//Log
EventLogProcessor.DeleteObject(biz.userId, AyaType.Tag, dbObj.Id, dbObj.Name, ct);
EventLogProcessor.DeleteObject(biz.UserId, AyaType.Tag, dbObj.Id, dbObj.Name, ct);
await ct.SaveChangesAsync();

View File

@@ -204,7 +204,7 @@ namespace AyaNova.Api.Controllers
await ct.SaveChangesAsync();
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, o.Id, AyaType.TagGroup, AyaEvent.Created), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, o.Id, AyaType.TagGroup, AyaEvent.Created), ct);
await ct.SaveChangesAsync();
return CreatedAtAction("GetTagGroup", new { id = o.Id }, new ApiCreatedResponse(o));
@@ -257,7 +257,7 @@ namespace AyaNova.Api.Controllers
}
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, oFromDb.Id, AyaType.TagGroup, AyaEvent.Modified), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, oFromDb.Id, AyaType.TagGroup, AyaEvent.Modified), ct);
try
{
@@ -329,7 +329,7 @@ namespace AyaNova.Api.Controllers
}
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, oFromDb.Id, AyaType.TagGroup, AyaEvent.Modified), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, oFromDb.Id, AyaType.TagGroup, AyaEvent.Modified), ct);
try
{
@@ -391,7 +391,7 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(biz.Errors));
}
//Log
EventLogProcessor.DeleteObject(biz.userId, AyaType.TagGroup, dbObj.Id, dbObj.Name, ct);
EventLogProcessor.DeleteObject(biz.UserId, AyaType.TagGroup, dbObj.Id, dbObj.Name, ct);
await ct.SaveChangesAsync();

View File

@@ -297,6 +297,9 @@ namespace AyaNova.Api.Controllers
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
}
//Instantiate the business object handler
UserBiz biz = UserBiz.GetBiz(ct, HttpContext);
//If a user has change roles, or editOwnRoles then they can create, true is passed for isOwner since they are creating so by definition the owner
if (!Authorized.IsAuthorizedToCreate(HttpContext.Items, UserBiz.BizType))
{
@@ -308,8 +311,7 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(ModelState));
}
//Instantiate the business object handler
UserBiz biz = UserBiz.GetBiz(ct, HttpContext);
//Create and validate
User o = await biz.CreateAsync(inObj);
@@ -354,6 +356,9 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(ModelState));
}
//Instantiate the business object handler
UserBiz biz = UserBiz.GetBiz(ct, HttpContext);
var dbObj = await ct.User.SingleOrDefaultAsync(m => m.Id == id);
if (dbObj == null)
{
@@ -365,8 +370,7 @@ namespace AyaNova.Api.Controllers
return StatusCode(401, new ApiNotAuthorizedResponse());
}
//Instantiate the business object handler
UserBiz biz = UserBiz.GetBiz(ct, HttpContext);
if (!biz.Delete(dbObj))
{
return BadRequest(new ApiErrorResponse(biz.Errors));

View File

@@ -136,7 +136,7 @@ namespace AyaNova.Api.Controllers
try
{
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, o.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, o.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
await ct.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
@@ -207,7 +207,7 @@ namespace AyaNova.Api.Controllers
try
{
//Log
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.userId, o.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(biz.UserId, o.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
await ct.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)

View File

@@ -297,6 +297,9 @@ namespace AyaNova.Api.Controllers
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
}
//Instantiate the business object handler
WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext);
//If a user has change roles, or editOwnRoles then they can create, true is passed for isOwner since they are creating so by definition the owner
if (!Authorized.IsAuthorizedToCreate(HttpContext.Items, WidgetBiz.BizType))
{
@@ -308,9 +311,6 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(ModelState));
}
//Instantiate the business object handler
WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext);
//Create and validate
Widget o = await biz.CreateAsync(inObj);
@@ -352,6 +352,9 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(ModelState));
}
//Instantiate the business object handler
WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext);
var dbObj = await ct.Widget.SingleOrDefaultAsync(m => m.Id == id);
if (dbObj == null)
{
@@ -363,9 +366,6 @@ namespace AyaNova.Api.Controllers
return StatusCode(401, new ApiNotAuthorizedResponse());
}
//Instantiate the business object handler
WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext);
if (!biz.Delete(dbObj))
{
return BadRequest(new ApiErrorResponse(biz.Errors));

View File

@@ -19,12 +19,21 @@ namespace AyaNova.Biz
}
#region Roles
public AuthorizationRoles CurrentUserRoles { get; set; }
#endregion roles
#region common props
internal static AyaType BizType { get; set; }
internal AyaNova.Models.AyContext ct { get; set; }
internal long UserId { get; set; }
internal long UserLocaleId { get; set; }
internal AuthorizationRoles CurrentUserRoles { get; set; }
#endregion
#region Error handling
private readonly List<ValidationError> _errors = new List<ValidationError>();
@@ -63,9 +72,10 @@ namespace AyaNova.Biz
sb.AppendLine("Validation errors:");
foreach (ValidationError e in _errors)
{
var msg=e.Message;
if(string.IsNullOrWhiteSpace(msg)){
msg=e.ErrorType.ToString();
var msg = e.Message;
if (string.IsNullOrWhiteSpace(msg))
{
msg = e.ErrorType.ToString();
}
sb.AppendLine($"Target: {e.Target} error: {msg}");
}

View File

@@ -14,14 +14,6 @@ namespace AyaNova.Biz
//https://stackoverflow.com/questions/36330981/is-the-validationresult-class-suitable-when-validating-the-state-of-an-object
/// <summary>
/// Roles of current user
/// </summary>
/// <returns></returns>
AuthorizationRoles CurrentUserRoles { get; set; }
/// <summary>
/// Contains list of errors
/// </summary>
@@ -47,7 +39,7 @@ namespace AyaNova.Biz
/// <param name="errorType"></param>
/// <param name="errorMessage"></param>
/// <param name="propertyName"></param>
void AddError(ValidationErrorType errorType, string propertyName=null, string errorMessage=null);
void AddError(ValidationErrorType errorType, string propertyName = null, string errorMessage = null);
/// <summary>
///

View File

@@ -18,16 +18,17 @@ namespace AyaNova.Biz
internal class ImportAyaNova7Biz : BizObject, IJobObject
{
private readonly AyContext ct;
public readonly long userId;
private readonly AuthorizationRoles userRoles;
// private readonly AyContext ct;
// public readonly long userId;
// private readonly AuthorizationRoles userRoles;
internal ImportAyaNova7Biz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
internal ImportAyaNova7Biz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
{
ct = dbcontext;
userId = currentUserId;
userRoles = UserRoles;
UserId = currentUserId;
CurrentUserRoles = userRoles;
BizType = AyaType.AyaNova7Import;
}
////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -18,16 +18,13 @@ namespace AyaNova.Biz
internal class JobOperationsBiz : BizObject
{
private readonly AyContext ct;
public readonly long userId;
private readonly AuthorizationRoles userRoles;
internal JobOperationsBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
internal JobOperationsBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
{
ct = dbcontext;
userId = currentUserId;
userRoles = UserRoles;
UserId = currentUserId;
CurrentUserRoles = userRoles;
BizType=AyaType.JobOperations;
}

View File

@@ -18,16 +18,14 @@ namespace AyaNova.Biz
internal class LocaleBiz : BizObject, IImportAyaNova7Object
{
private readonly AyContext ct;
public readonly long userId;
private readonly AuthorizationRoles userRoles;
public bool SeedOrImportRelaxedRulesMode { get; set; }
internal LocaleBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
internal LocaleBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
{
ct = dbcontext;
userId = currentUserId;
userRoles = UserRoles;
UserId = currentUserId;
CurrentUserRoles = userRoles;
BizType = AyaType.Locale;
SeedOrImportRelaxedRulesMode = false;//default
}
@@ -55,9 +53,9 @@ namespace AyaNova.Biz
//replicate the source to a new dest and save
Locale NewLocale = new Locale();
NewLocale.Name = inObj.Name;
NewLocale.OwnerId = this.userId;
NewLocale.OwnerId = UserId;
NewLocale.Stock = false;
NewLocale.CjkIndex=false;
NewLocale.CjkIndex = false;
foreach (LocaleItem i in SourceLocale.LocaleItems)
{
NewLocale.LocaleItems.Add(new LocaleItem() { Key = i.Key, Display = i.Display });
@@ -165,11 +163,11 @@ namespace AyaNova.Biz
//Get the CJKIndex value for the locale specified
internal static async Task<bool> GetCJKIndex(long localeId, AyContext ct=null)
internal static async Task<bool> GetCJKIndex(long localeId, AyContext ct = null)
{
if(ct==null)
if (ct == null)
ct = ServiceProviderProvider.DBContext;
var ret = await ct.Locale.Where(x => x.Id == localeId).Select(m=>m.CjkIndex).SingleOrDefaultAsync();
var ret = await ct.Locale.Where(x => x.Id == localeId).Select(m => m.CjkIndex).SingleOrDefaultAsync();
return ret;
}
@@ -539,7 +537,7 @@ namespace AyaNova.Biz
ct.SaveChanges();
//Log now that we have the Id, note that there is no source created / modified for this so just attributing to current userId
EventLogProcessor.AddEntryToContextNoSave(new Event(userId, l.Id, AyaType.Locale, AyaEvent.Created), ct);
EventLogProcessor.AddEntryToContextNoSave(new Event(UserId, l.Id, AyaType.Locale, AyaEvent.Created), ct);
ct.SaveChanges();
}

View File

@@ -17,17 +17,15 @@ namespace AyaNova.Biz
internal class TagBiz : BizObject, IImportAyaNova7Object
{
private readonly AyContext ct;
public readonly long userId;
private readonly AuthorizationRoles userRoles;
public bool SeedOrImportRelaxedRulesMode { get; set; }
internal TagBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
internal TagBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
{
ct = dbcontext;
userId = currentUserId;
userRoles = UserRoles;
UserId = currentUserId;
CurrentUserRoles = userRoles;
BizType = AyaType.Tag;
SeedOrImportRelaxedRulesMode = false;//default
}
@@ -48,7 +46,7 @@ namespace AyaNova.Biz
Tag outObj = new Tag()
{
Name = inObj,
OwnerId = userId
OwnerId = UserId
};

View File

@@ -17,17 +17,18 @@ namespace AyaNova.Biz
internal class TagGroupBiz : BizObject
{
private readonly AyContext ct;
public readonly long userId;
private readonly AuthorizationRoles userRoles;
// private readonly AyContext ct;
// public readonly long userId;
// private readonly AuthorizationRoles userRoles;
public bool V7ValidationImportMode { get; set; }
internal TagGroupBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
internal TagGroupBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
{
ct = dbcontext;
userId = currentUserId;
userRoles = UserRoles;
UserId = currentUserId;
CurrentUserRoles = userRoles;
BizType=AyaType.TagGroup;
V7ValidationImportMode = false;//default
}
@@ -48,7 +49,7 @@ namespace AyaNova.Biz
TagGroup outObj = new TagGroup()
{
Name = inObj,
OwnerId = userId
OwnerId = UserId
};
@@ -229,10 +230,10 @@ namespace AyaNova.Biz
if (TagGroupTags.Count == 0) return ReturnObject;
//Tag each one separately via TagMap which handles cases where object is already tagged with that tag etc
var MapBiz = new TagMapBiz(ct, userId, userRoles);
var MapBiz = new TagMapBiz(ct, UserId, CurrentUserRoles);
foreach (NameIdItem TagInGroup in TagGroupTags)
{
var TagMapItem = await MapBiz.CreateAsync(new TagMapInfo { TagId = TagInGroup.Id, TagToObjectId=inObj.TagToObjectId, TagToObjectType=inObj.TagToObjectType });
var TagMapItem = await MapBiz.CreateAsync(new TagMapInfo { TagId = TagInGroup.Id, TagToObjectId = inObj.TagToObjectId, TagToObjectType = inObj.TagToObjectType });
ReturnObject.Add(TagInGroup);
}
await ct.SaveChangesAsync();

View File

@@ -17,16 +17,14 @@ namespace AyaNova.Biz
internal class TagGroupMapBiz : BizObject
{
private readonly AyContext ct;
public readonly long userId;
private readonly AuthorizationRoles userRoles;
internal TagGroupMapBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
internal TagGroupMapBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
{
ct = dbcontext;
userId = currentUserId;
userRoles = UserRoles;
UserId = currentUserId;
CurrentUserRoles = userRoles;
BizType = AyaType.TagGroupMap;
}
@@ -55,7 +53,7 @@ namespace AyaNova.Biz
{
TagId = inObj.TagId,
TagGroupId = inObj.TagGroupId,
OwnerId = userId
OwnerId = UserId
};

View File

@@ -17,16 +17,13 @@ namespace AyaNova.Biz
internal class TagMapBiz : BizObject
{
private readonly AyContext ct;
public readonly long userId;
private readonly AuthorizationRoles userRoles;
internal TagMapBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
internal TagMapBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
{
ct = dbcontext;
userId = currentUserId;
userRoles = UserRoles;
UserId = currentUserId;
CurrentUserRoles = userRoles;
BizType = AyaType.TagMap;
}
@@ -54,7 +51,7 @@ namespace AyaNova.Biz
TagId = inObj.TagId,
TagToObjectId = inObj.TagToObjectId,
TagToObjectType = inObj.TagToObjectType,
OwnerId = userId
OwnerId = UserId
};

View File

@@ -21,17 +21,12 @@ namespace AyaNova.Biz
/// </summary>
internal class TrialBiz : BizObject, IJobObject
{
private readonly AyContext ct;
public readonly long userId;
private readonly AuthorizationRoles userRoles;
// private readonly ApiServerState serverState;
internal TrialBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
internal TrialBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
{
ct = dbcontext;
userId = currentUserId;
userRoles = UserRoles;
//serverState = apiServerState;, ApiServerState apiServerState
UserId = currentUserId;
CurrentUserRoles = userRoles;
BizType=AyaType.TrialSeeder;
}
////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -18,19 +18,15 @@ namespace AyaNova.Biz
internal class UserBiz : BizObject, IJobObject, IImportAyaNova7Object
{
public static AyaType BizType = AyaType.User;
private readonly AyContext ct;
public readonly long UserId;
public readonly long UserLocaleId;
private readonly AuthorizationRoles userRoles;
public bool SeedOrImportRelaxedRulesMode { get; set; }
internal UserBiz(AyContext dbcontext, long currentUserId, long userLocaleId, AuthorizationRoles UserRoles)
internal UserBiz(AyContext dbcontext, long currentUserId, long userLocaleId, AuthorizationRoles userRoles)
{
ct = dbcontext;
UserId = currentUserId;
UserLocaleId = userLocaleId;
userRoles = UserRoles;
CurrentUserRoles = userRoles;
BizType = AyaType.User;
SeedOrImportRelaxedRulesMode = false;//default
}

View File

@@ -16,16 +16,13 @@ namespace AyaNova.Biz
internal class UserOptionsBiz : BizObject
{
private readonly AyContext ct;
public readonly long userId;
private readonly AuthorizationRoles userRoles;
internal UserOptionsBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
internal UserOptionsBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
{
ct = dbcontext;
userId = currentUserId;
userRoles = UserRoles;
UserId = currentUserId;
CurrentUserRoles = userRoles;
BizType = AyaType.UserOptions;
}

View File

@@ -16,19 +16,14 @@ namespace AyaNova.Biz
internal class WidgetBiz : BizObject, IJobObject
{
public static AyaType BizType = AyaType.Widget;
private readonly AyContext ct;
public readonly long UserId;
public readonly long UserLocaleId;
private readonly AuthorizationRoles userRoles;
internal WidgetBiz(AyContext dbcontext, long currentUserId, long userLocaleId, AuthorizationRoles UserRoles)
{
ct = dbcontext;
UserId = currentUserId;
UserLocaleId = userLocaleId;
userRoles = UserRoles;
CurrentUserRoles = UserRoles;
BizType = AyaType.Widget;
}
internal static WidgetBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext)