Hi,
For now you can try:
public static class RefreshEditionIdMiddlewareExtension { public static IApplicationBuilder UseRefreshEditionIdMiddleware(this IApplicationBuilder app) { return app.Use(async (ctx, next) => { var currentTenant = ctx.RequestServices.GetRequiredService<ICurrentTenant>(); var currentUser = ctx.RequestServices.GetRequiredService<ICurrentUser>(); if (!currentUser.IsAuthenticated || !currentUser.TenantId.HasValue) { await next(); return; } var tenantStore = ctx.RequestServices.GetRequiredService<ITenantRepository>(); var currentPrincipalAccessor = ctx.RequestServices.GetRequiredService<ICurrentPrincipalAccessor>(); var tenant = await tenantStore.FindAsync(currentTenant.GetId()); var claims = currentPrincipalAccessor.Principal.Claims.ToList(); claims.ReplaceOne(x => x.Type == AbpClaimTypes.EditionId, new Claim(AbpClaimTypes.EditionId, tenant.EditionId?.ToString() ?? string.Empty)); using (currentPrincipalAccessor.Change(claims)) { await next(); } }); } }
.... app.UseAuthorization(); app.UseRefreshEditionIdMiddleware(); // add behind to `UseAuthorization`
Perfect, worked a treat. Thankyou
So it gets the edition from the jwt and then uses it to get the features? And then the new changes would only use the tenant?
Are there any workarounds? How is this typically handled? I'm happy to reauthenticate the user in the backend but, but I can't really log them out and make them log in again just for changing plans.
Any help is appreciated
Currently we set the tenant edition in our product by setting the edition ID in the tenant, however the features that come back from application-configuration
still show the features from the previous edition, unless the user logs out and logs back in again. Page refreshes, and clearing the cache in the browser do not show the correct values, so I am assuming there is some sort of server side caching going on. How can I clear this and return the correct values without signing the user out?
Thanks for that.
Looks like that is the issue, I created a copy with the JToken
and got the same error, then removed it and it worked. Any further information on why this causes it or hope for a more permanent solution? It's used in a lot of the models for Chargebee and I would rather avoid the headaches of maintaining a copy of them all, especially when it comes to billing.
Item
is from Chargebee, below is what I get from the package, the souce can be found at https://github.com/chargebee/chargebee-dotnet/blob/master/ChargeBee/Models/Item.cs
#region Assembly ChargeBee, Version=2.9.1.0, Culture=neutral, PublicKeyToken=2efc9456dd1bdb9d
// C:\Users\xxxxxx\.nuget\packages\chargebee\2.10.0\lib\netstandard2.0\ChargeBee.dll
#endregion
using ChargeBee.Api;
using ChargeBee.Filters.Enums;
using ChargeBee.Internal;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
namespace ChargeBee.Models
{
public class Item : Resource
{
public Item();
public Item(Stream stream);
public Item(TextReader reader);
public Item(string jsonString);
public bool EnabledForCheckout { get; }
public bool EnabledInPortal { get; }
public bool? IncludedInMrr { get; }
public ItemApplicabilityEnum ItemApplicability { get; }
public string GiftClaimRedirectUrl { get; }
public bool Metered { get; }
public bool IsGiftable { get; }
public UsageCalculationEnum? UsageCalculation { get; }
public DateTime? ArchivedAt { get; }
public List<ItemApplicableItem> ApplicableItems { get; }
public JToken Metadata { get; }
public string Unit { get; }
public bool? IsShippable { get; }
public string RedirectUrl { get; }
public string ItemFamilyId { get; }
public DateTime? UpdatedAt { get; }
public long? ResourceVersion { get; }
public StatusEnum? Status { get; }
public string Description { get; }
public string Name { get; }
public string Id { get; }
public TypeEnum ItemType { get; }
public static CreateRequest Create();
public static EntityRequest<Type> Delete(string id);
public static ItemListRequest List();
public static EntityRequest<Type> Retrieve(string id);
public static UpdateRequest Update(string id);
public enum StatusEnum
{
UnKnown = 0,
Active = 1,
Archived = 2,
Deleted = 3
}
public enum TypeEnum
{
UnKnown = 0,
Plan = 1,
Addon = 2,
Charge = 3
}
public enum ItemApplicabilityEnum
{
UnKnown = 0,
All = 1,
Restricted = 2
}
public enum UsageCalculationEnum
{
UnKnown = 0,
SumOfUsages = 1,
LastUsage = 2,
MaxUsage = 3
}
public class CreateRequest : EntityRequest<CreateRequest>
{
public CreateRequest(string url, HttpMethod method);
public CreateRequest ApplicableItems(List<string> applicableItems);
public CreateRequest Description(string description);
public CreateRequest EnabledForCheckout(bool enabledForCheckout);
public CreateRequest EnabledInPortal(bool enabledInPortal);
public CreateRequest GiftClaimRedirectUrl(string giftClaimRedirectUrl);
public CreateRequest Id(string id);
public CreateRequest IncludedInMrr(bool includedInMrr);
public CreateRequest IsGiftable(bool isGiftable);
public CreateRequest IsShippable(bool isShippable);
public CreateRequest ItemApplicability(ItemApplicabilityEnum itemApplicability);
public CreateRequest ItemFamilyId(string itemFamilyId);
public CreateRequest Metadata(JToken metadata);
public CreateRequest Metered(bool metered);
public CreateRequest Name(string name);
public CreateRequest RedirectUrl(string redirectUrl);
public CreateRequest Type(TypeEnum type);
public CreateRequest Unit(string unit);
public CreateRequest UsageCalculation(UsageCalculationEnum usageCalculation);
}
public class UpdateRequest : EntityRequest<UpdateRequest>
{
public UpdateRequest(string url, HttpMethod method);
public UpdateRequest ApplicableItems(List<string> applicableItems);
[Obsolete]
public UpdateRequest ClearApplicableItems(bool clearApplicableItems);
public UpdateRequest Description(string description);
public UpdateRequest EnabledForCheckout(bool enabledForCheckout);
public UpdateRequest EnabledInPortal(bool enabledInPortal);
public UpdateRequest GiftClaimRedirectUrl(string giftClaimRedirectUrl);
public UpdateRequest IncludedInMrr(bool includedInMrr);
public UpdateRequest IsShippable(bool isShippable);
public UpdateRequest ItemApplicability(ItemApplicabilityEnum itemApplicability);
public UpdateRequest ItemFamilyId(string itemFamilyId);
public UpdateRequest Metadata(JToken metadata);
public UpdateRequest Name(string name);
public UpdateRequest RedirectUrl(string redirectUrl);
public UpdateRequest Status(StatusEnum status);
public UpdateRequest Unit(string unit);
}
public class ItemListRequest : ListRequestBase<ItemListRequest>
{
public ItemListRequest(string url);
public BooleanFilter<ItemListRequest> EnabledForCheckout();
public BooleanFilter<ItemListRequest> EnabledInPortal();
public StringFilter<ItemListRequest> Id();
public BooleanFilter<ItemListRequest> IsGiftable();
public EnumFilter<ItemApplicabilityEnum, ItemListRequest> ItemApplicability();
public StringFilter<ItemListRequest> ItemFamilyId();
public BooleanFilter<ItemListRequest> Metered();
public StringFilter<ItemListRequest> Name();
public ItemListRequest SortById(SortOrderEnum order);
public ItemListRequest SortByName(SortOrderEnum order);
public ItemListRequest SortByUpdatedAt(SortOrderEnum order);
public EnumFilter<StatusEnum, ItemListRequest> Status();
public EnumFilter<TypeEnum, ItemListRequest> Type();
public TimestampFilter<ItemListRequest> UpdatedAt();
public EnumFilter<UsageCalculationEnum, ItemListRequest> UsageCalculation();
}
public class ItemApplicableItem : Resource
{
public ItemApplicableItem();
public string Id();
}
}
}
I'm currently getting and issue when trying to run generate proxy on the cli after adding the chargebee package which crashes the application and fails to run the proxies. I have also tried creating a new project and get the same behaviour.
I've created a dummy entity and this simple function in it, as well as the interface and controller and it works successfully in swagger.
public virtual async Task<List<Item>> GetChargebeePlans()
{
ListResult chargebeePlans = await Item.List().Limit(10).RequestAsync();
List<Item> chargebeeItems = new List<Item>();
foreach (var item in chargebeePlans.List)
{
chargebeeItems.Add(item.Item);
}
return chargebeeItems;
}
Before this function generate-proxy works fine, but afterwards it crashes I get an error in the web server output, below is an extract:
[13:33:39 DBG] Executing HealthCheck collector HostedService.
[13:33:39 INF] Start processing HTTP request GET https://localhost:44348/health-status
[13:33:39 INF] Sending HTTP request GET https://localhost:44348/health-status
[13:33:39 INF] Request starting HTTP/1.1 GET https://localhost:44348/health-status - -
[13:33:39 INF] Executing endpoint 'Health checks'
[13:33:39 INF] Executed endpoint 'Health checks'
[13:33:39 INF] Received HTTP response headers after 17.0992ms - 200
[13:33:39 INF] End processing HTTP request after 17.2147ms - 200
[13:33:39 INF] Request finished HTTP/1.1 GET https://localhost:44348/health-status - - - 200 - application/json 18.0426ms
[13:33:39 DBG] HealthReportCollector - health report execution history saved.
[13:33:39 DBG] HealthReport history already exists and is in the same state, updating the values.
[13:33:39 DBG] HealthReportCollector has completed.
[13:33:39 DBG] HealthCheck collector HostedService executed successfully.
[13:33:40 INF] Request starting HTTP/1.1 GET https://localhost:44348/api/abp/api-definition?includeTypes=true - -
[13:33:40 INF] Executing endpoint 'Volo.Abp.AspNetCore.Mvc.ApiExploring.AbpApiDefinitionController.Get (Volo.Abp.AspNetCore.Mvc)'
[13:33:40 INF] Route matched with {area = "abp", action = "Get", controller = "AbpApiDefinition", page = ""}. Executing controller action with signature Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel Get(Volo.Abp.Http.Modeling.ApplicationApiDescriptionModelRequestDto) on controller Volo.Abp.AspNetCore.Mvc.ApiExploring.AbpApiDefinitionController (Volo.Abp.AspNetCore.Mvc).
[13:33:40 DBG] ActionApiDescriptionModel.Create: Dummy.GetListAsyncByInput
[13:33:40 DBG] ActionApiDescriptionModel.Create: Dummy.GetAsyncById
[13:33:40 DBG] ActionApiDescriptionModel.Create: Dummy.CreateAsyncByInput
[13:33:40 DBG] ActionApiDescriptionModel.Create: Dummy.UpdateAsyncByIdAndInput
[13:33:40 DBG] ActionApiDescriptionModel.Create: Dummy.DeleteAsyncById
[13:33:40 DBG] ActionApiDescriptionModel.Create: Dummy.GetChargebeePlans
Stack overflow.
at System.ReadOnlySpan`1[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ToArray()
at System.RuntimeType.GetInterfaces()
at Volo.Abp.Reflection.ReflectionHelper.AddImplementedGenericTypes(System.Collections.Generic.List`1<System.Type>, System.Type, System.Type)
at Volo.Abp.Reflection.ReflectionHelper.GetImplementedGenericTypes(System.Type, System.Type)
at Volo.Abp.Reflection.TypeHelper.IsEnumerable(System.Type, System.Type ByRef, Boolean)
at Volo.Abp.AspNetCore.Mvc.AspNetCoreApiDescriptionModelProvider.AddCustomTypesToModel(Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel, System.Type)
at Volo.Abp.AspNetCore.Mvc.AspNetCoreApiDescriptionModelProvider.AddCustomTypesToModel(Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel, System.Type)
at Volo.Abp.AspNetCore.Mvc.AspNetCoreApiDescriptionModelProvider.AddCustomTypesToModel(Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel, System.Type)
at Volo.Abp.AspNetCore.Mvc.AspNetCoreApiDescriptionModelProvider.AddCustomTypesToModel(Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel, System.Type)
at Volo.Abp.AspNetCore.Mvc.AspNetCoreApiDescriptionModelProvider.AddCustomTypesToModel(Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel, System.Type)
at Volo.Abp.AspNetCore.Mvc.AspNetCoreApiDescriptionModelProvider.AddCustomTypesToModel(Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel, System.Type)
...
Those errors repeat ~15000 times, I can provide the full output if it helps.