Base solution for your next web application
Ends in:
01 DAYS
01 HRS
01 MIN
01 SEC

Activities of "statuscast"

Greetings.

Has anyone had any success integrating EFSecondLevelCache.Core and their Redis setup? It's a recommended tool by Microsoft if you want to introduce caching on EntityFrameworkCore.

Abp/Az offers entity level caching out of the box, but it doesn't provide query result caching inherently, so it's either go write a lot of code or try to integrate something like EFSecondLevelCache.Core into Abp so that I can cache a query result easily like this:

var result = _repository.GetAll().Where(x=>x.Something>5).Cacheable().ToList();

That Cacheable extension is incredibly nice and simplifies me having to manually add items to Redis, manage unique key names for each query, etc.

I added their code to Startup as per their instructions:

`services.AddEFSecondLevelCache();

            // Add Redis cache service provider
            var jss = new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };

            const string redisConfigurationKey = "redis";
            string connectionString = _appConfiguration["Abp:RedisCache:ConnectionString"];
            services.AddSingleton(typeof(ICacheManagerConfiguration),
                new CacheManager.Core.ConfigurationBuilder()
                    .WithJsonSerializer(serializationSettings: jss, deserializationSettings: jss)
                    .WithUpdateMode(CacheUpdateMode.Up)
                    .WithRedisConfiguration(redisConfigurationKey, config =>
                    {                            
                        config.WithAllowAdmin()
                            .WithDatabase(0) // (int.Parse(_appConfiguration["Abp:RedisCache:DatabaseId"]))
                            .WithEndpoint(connectionString, 6379);                            
                    })
                    .WithMaxRetries(100)
                    .WithRetryTimeout(50)
                    .WithRedisCacheHandle(redisConfigurationKey)
                    .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(10))
                    .Build());
            services.AddSingleton(typeof(ICacheManager<>), typeof(BaseCacheManager<>));`
            

and

app.UseEFSecondLevelCache();

but as soon as try using the .Cacheable() like the above line is called I get CastleWindsor errors:

Exception thrown: 'Castle.MicroKernel.ComponentActivator.ComponentActivatorException' in System.Private.CoreLib.dll Abp.AspNetCore.Mvc.ExceptionHandling.AbpExceptionFilter: 2018-11-20 14:49:30,995 [12] ERROR Abp.AspNetCore.Mvc.ExceptionHandling.AbpExceptionFilter ComponentActivator: could not instantiate CacheManager.Core.BaseCacheManager1[[System.Object, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] Castle.MicroKernel.ComponentActivator.ComponentActivatorException: ComponentActivator: could not instantiate CacheManager.Core.BaseCacheManager1[[System.Object, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] ---> System.Exception: Could not instantiate CacheManager.Core.BaseCacheManager1[[System.Object, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Connection to 'statuscast-test.redis.cache.windows.net:6380,allowAdmin=True,connectTimeout=5000,password=****,ssl=False,abortConnect=False,connectRetry=10,proxy=None' failed. at CacheManager.Core.BaseCacheManager1..ctor(String name, ICacheManagerConfiguration configuration) at CacheManager.Core.BaseCacheManager1..ctor(ICacheManagerConfiguration configuration) --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions) at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) at Castle.Core.Internal.ReflectionUtil.Instantiate[TBase](Type subtypeofTBase, Object[] ctorArgs) --- End of inner exception stack trace --- at Castle.Core.Internal.ReflectionUtil.Instantiate[TBase](Type subtypeofTBase, Object[] ctorArgs) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType) --- End of inner exception stack trace --- at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, ConstructorCandidate constructor, Object[] arguments) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context) at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden) at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally) at Castle.MicroKernel.Lifestyle.SingletonLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy) at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden) at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.Handlers.DefaultGenericHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateConstructorArguments(ConstructorCandidate constructor, CreationContext context) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext context) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context) at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden) at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally) at Castle.MicroKernel.Lifestyle.SingletonLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy) at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden) at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy, Boolean ignoreParentContext) at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy, Boolean ignoreParentContext) at Castle.MicroKernel.DefaultKernel.Resolve(Type service, IDictionary arguments) at Castle.Windsor.MsDependencyInjection.ScopedWindsorServiceProvider.GetServiceInternal(Type serviceType, Boolean isOptional) in D:\Github\castle-windsor-ms-adapter\src\Castle.Windsor.MsDependencyInjection\ScopedWindsorServiceProvider.cs:line 55 at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider) at EFSecondLevelCache.Core.EFCachedQueryExtensions.configureProviders() at EFSecondLevelCache.Core.EFCachedQueryExtensions.Cacheable[TType](IQueryable1 query, String saltKey, EFCacheDebugInfo debugInfo) at StatusCast.EntityFrameworkCore.Repositories.IncidentRepository.GetFullAsync(Int64 id) in C:\src\statuscast\server.v3\src\StatusCast.EntityFrameworkCore\Incidents\IncidentsRepository.cs:line 30 at Abp.Threading.InternalAsyncHelper.AwaitTaskWithPostActionAndFinallyAndGetResult[T](Task1 actualReturnValue, Func1 postAction, Action1 finalAction) at StatusCast.Incidents.IncidentAppService.GetIncident(Int64 incidentId) in C:\src\statuscast\server.v3\src\StatusCast.Application\Incidents\IncidentAppService.cs:line 126 at Abp.Threading.InternalAsyncHelper.AwaitTaskWithPostActionAndFinallyAndGetResult[T](Task1 actualReturnValue, Func1 postAction, Action1 finalAction) at Abp.Threading.InternalAsyncHelper.AwaitTaskWithFinallyAndGetResult[T](Task1 actualReturnValue, Action1 finalAction) at StatusCast.Web.Controllers.IncidentController.GetIncident(Int64 id) in C:\src\statuscast\server.v3\src\StatusCast.Web.Core\Controllers\IncidentController.cs:line 39 at lambda_method(Closure , Object ) at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync() StatusCastExceptionHandler: Abp.AspNetCore.Mvc.ExceptionHandling.AbpExceptionFilter, 11/20/2018 7:49:31 PM, ComponentActivator: could not instantiate CacheManager.Core.BaseCacheManager`1[[System.Object, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor: 2018-11-20 14:49:31,048 [12] INFO Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor Executing ObjectResult, writing value of type 'Abp.Web.Models.AjaxResponse'.

What is the best practice for adding permissions to static roles? It seems like the way AZ is structured we should be doing it in

MyProject.Authorization.Roles.AppConfig.Configure where we create all our static roles, however, that method doesn't seem to have access to the RoleManager.

All documentation only refers to setting permissions via your admin app, but we have static roles and permissions that we need to set programmatically.

Where is the best place during startup of the app to call RoleManager.SetGrantedPermissionsAsync() ?

thanks!

Question

Hi,

Trying to build an entity that uses Abp.GeneralTree.

Step 1: Define entity

namespace StatusCast.Components
{
public interface IComponent : IEntity
{
}

public partial class Component : Entity<long>, IComponent, IGeneralTree<Component, long>, 
    IExtendableObject, ICreationAudited, IMustHaveTenant, ISoftDelete
{
    // Abp built in
    public string ExtensionData { get; set; }
    public virtual DateTime CreationTime { get; set; }
    public int TenantId { get; set; }
    public bool IsDeleted { get; set; }
    public long? CreatorUserId { get; set; }
    // more...

Step 2: Add to EF

public class MyDbContext : AbpZeroDbContext<Tenant, Role, User, StatusCastDbContext>, IAbpPersistedGrantDbContext
{
        // StatusCast Entities
        public virtual DbSet<Component> Components { get; set; }
}

Step 3: Create basic AppService:

public class ComponentAppService : MyAppServiceBase, IComponentAppService
{
        private readonly IGeneralTreeManager<Component, long> _componentTreeManager;

        public ComponentAppService(IGeneralTreeManager<Component, long> componentTreeManager)
        {
            _componentTreeManager = componentTreeManager;
        }

        public async Task<long> CreateComponentAsync(ComponentCreateDto input)
        {
            var component = ObjectMapper.Map<Component>(input);
            await _componentTreeManager.CreateAsync(component);
            return component.Id;
        }
 }

Step 4: Call it via a controller:

[Route("api/[controller]/[action]")]
    public class ComponentsController : StatusCastControllerBase
    {
        private readonly IComponentAppService _componentsService;

        public ComponentsController(
            IComponentAppService componentsService
        )
        {
            _componentsService = componentsService;
        }

        [ApiExplorerSettings(GroupName = "public")]
        [HttpPost]
        [Route("/api/Component")]
        public async Task<long> Create(ComponentCreateDto input)
        {
            return await _componentsService.CreateComponentAsync(input);

        }

    }

=============================================== When calling the controller, I am getting the following error:

Exception thrown: 'Castle.MicroKernel.Handlers.HandlerException' in Castle.Windsor.dll Exception thrown: 'Castle.MicroKernel.Handlers.HandlerException' in Castle.Windsor.dll Exception thrown: 'Castle.MicroKernel.Handlers.HandlerException' in System.Private.CoreLib.dll 'dotnet.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.5\System.Diagnostics.StackTrace.dll'. Cannot find or open the PDB file. 'dotnet.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.5\System.Reflection.Metadata.dll'. Cannot find or open the PDB file. Abp.AspNetCore.Mvc.ExceptionHandling.AbpExceptionFilter: 2018-10-28 10:30:37,119 [20] ERROR Abp.AspNetCore.Mvc.ExceptionHandling.AbpExceptionFilter Can't create component 'StatusCast.Components.ComponentAppService' as it has dependencies to be satisfied.

'StatusCast.Components.ComponentAppService' is waiting for the following dependencies:

  • Service 'Abp.GeneralTree.IGeneralTreeManager`2[[StatusCast.Components.Component, StatusCast.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Int64, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]' which was not registered.

Castle.MicroKernel.Handlers.HandlerException: Can't create component 'StatusCast.Components.ComponentAppService' as it has dependencies to be satisfied.

'StatusCast.Components.ComponentAppService' is waiting for the following dependencies:

  • Service 'Abp.GeneralTree.IGeneralTreeManager`2[[StatusCast.Components.Component, StatusCast.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Int64, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]' which was not registered. at Castle.MicroKernel.Handlers.DefaultHandler.AssertNotWaitingForDependency() at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden) at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateConstructorArguments(ConstructorCandidate constructor, CreationContext context) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext context) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context) at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden) at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally) at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy) at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden) at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy) at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy) at Castle.Windsor.MsDependencyInjection.ScopedWindsorServiceProvider.GetServiceInternal(Type serviceType, Boolean isOptional) in D:\Github\castle-windsor-ms-adapter\src\Castle.Windsor.MsDependencyInjection\ScopedWindsorServiceProvider.cs:line 55 at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<&gt;c__DisplayClass5_0.g__CreateController|0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()

============================================================

I have a feeling there is some additional startup code I need to do to get Abp.TreeManager properly available, but don't really know what that would be as there is very little documentation. Any help would be appreciated.

thanks! jasen

Question

Hi,

Is there a working or up to date document that walks thru the set up of a second database / dbcontext? We have high-transaction / high-volume data we do not want to store in to main tenant databases and prefer to offload it to a secondary db. The most current information I can find is this:

https://stackoverflow.com/questions/49243891/how-to-use-multiples-databases-in-abp-core-zero

But even that looks out of date relative to the current project structure of 6.1.

Any updated documentation or working sample project that is compatible with 6.1?

Hi,

In Abp we can change the default length of the AbpSettings column by adding this line of code to the EntityFramework.Core\EntityFrameworkCore\CompanyNameDbContext.cs:

 protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
      base.OnModelCreating(modelBuilder);

     //Increase your Setting Value to 4000 chars (translates to NVARCHAR(MAX) 
     modelBuilder.Entity<Abp.Configuration.Setting>().Property(u => u.Value).HasColumnType("nvarchar(max)");

However, in AZ this line of code seems to have no effect. The DB is still being created with column width of 2000. Does this code have to sit in a dfferent project in AspNetZero? We put this line of code in, rebuilt, blew away the database, then run Update-Databse to ensure it was not working.

Sorry for a second post but I'm trying to work through these startup exceptions. I get this during startup of a freshly downloaded copy of the DotNetCore jQuery+MVC app when running the Web.MVC project.

Am I the only one getting these? I haven't updated any packages (which I thought may have been the issue with my previous post -- it wasn't)

Exception thrown: 'Castle.MicroKernel.CircularDependencyException' in Castle.Windsor.dll Dependency cycle has been detected when trying to resolve component 'Microsoft.AspNetCore.Razor.Language.RazorProjectEngine_342f322e-12a2-43fa-bd2c-b3d7a11fea5b'. The resolution tree that resulted in the cycle is the following: Component 'Microsoft.AspNetCore.Razor.Language.RazorProjectEngine_342f322e-12a2-43fa-bd2c-b3d7a11fea5b' resolved as dependency of component 'Microsoft.AspNetCore.Razor.Language.RazorEngine_84465d71-0335-4164-9caa-a7b1825160ce' resolved as dependency of component 'Microsoft.AspNetCore.Mvc.Razor.Internal.LazyMetadataReferenceFeature_fadeed8d-908f-4f1a-929e-671e0fac0468' resolved as dependency of component 'Microsoft.AspNetCore.Razor.Language.RazorProjectEngine_342f322e-12a2-43fa-bd2c-b3d7a11fea5b' resolved as dependency of component 'Microsoft.AspNetCore.Mvc.Razor.Compilation.IViewCompilerProvider_b4901d29-7df1-4715-a1a4-3a3e6614f9c4' resolved as dependency of component 'Microsoft.AspNetCore.Mvc.Razor.IRazorPageFactoryProvider_41441bd0-e3c9-4ab3-9194-b43dbf35817b' resolved as dependency of component 'Microsoft.AspNetCore.Mvc.Razor.IRazorViewEngine_77e94e9f-46af-4866-bb10-767d8ccd0218' resolved as dependency of component 'Microsoft.Extensions.Options.IConfigureOptions1[[Microsoft.AspNetCore.Mvc.MvcViewOptions, Microsoft.AspNetCore.Mvc.ViewFeatures, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]]_5aae7c05-6172-497b-9d95-463f42a3f065' resolved as dependency of component 'Microsoft.Extensions.Options.IOptionsFactory1_845669a6-a7eb-4e97-89c9-e07cc667f74c' resolved as dependency of component 'Microsoft.Extensions.Options.IOptionsFactory1_845669a6-a7eb-4e97-89c9-e07cc667f74c' resolved as dependency of component 'Microsoft.Extensions.Options.IOptions1_9314a2d7-cc59-44a6-937c-0ec01e523717' resolved as dependency of component 'Microsoft.Extensions.Options.IOptions`1_9314a2d7-cc59-44a6-937c-0ec01e523717' resolved as dependency of component 'Microsoft.AspNetCore.Mvc.ApplicationModels.IPageApplicationModelProvider_b29b5f53-be79-469c-91cb-30a963369e9d' resolved as dependency of component 'Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.IPageLoader_ffd49a92-ac4c-455b-812b-b319374e8df2' resolved as dependency of component 'Microsoft.AspNetCore.Mvc.Abstractions.IActionInvokerProvider_adecbe20-f382-4dfd-8c1e-d5a534c872d7' resolved as dependency of component 'Microsoft.AspNetCore.Mvc.Infrastructure.IActionInvokerFactory_1aa4e594-8f55-43fa-a5c8-2d1501735feb' resolved as dependency of component 'Microsoft.AspNetCore.Mvc.Internal.MvcRouteHandler_6ba755e4-c2c4-42f6-a842-398731985a14' which is the root component being resolved.

take care, jasen

Does anyone else experience a large number of exceptions during startup in AppNameCoreModule.cs:

line 109: IocManager.Resolve<ChatUserStateWatcher>().Initialize();

Exception thrown: 'System.ArgumentException' in System.Private.CoreLib.dll
System.ArgumentException: 'Null is not a valid constant value for this type.'

I'm trying to debug the MVC app startup time and just happened to notice this.. probably not related but figured it would be worth reporting.

Hi,

We are using the DotNetCore MVC/jQuery solution..

We find that having all our API calls only be accessible via the path domain.com/api/services/app/Component/Method very inconvenient for our customers. We also realize that as most the API calls are dynamically generated from our AppServices, we are kind of locked in to this.

Since the actual API set we want to expose is fairly small, what we would like to do as a work around, so our customers can simply access the api from domain.com/api/Component/Method is create a small WebApi proxy layer that literally acts as a 100% passthru to the subset of AppService Api calls. My question is 3 fold:

  1. what project do we implement this so that these WebAPI calls will be accessible within both the MVc and the Host proect

  2. How do we set a custom route for these calls? I can't seem to get custom routes working in any Abp or AspNetZero projects

  3. How do we ensure these calls are included in our Swagger UI?

Also, if there are already some example of custom non-AppService API's being exposed like this, I could probably figure this out, happy to be pointed to the right area if I'm just missing it...

thanks! jasen

Showing 11 to 18 of 18 entries