Base solution for your next web application

Activities of "devinedon"

Perfect, done :)

Using background tasks with hosted services in ASP.NET Core it works well. https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&tabs=visual-studio

Beautiful repo explaining all this -> https://github.com/Daniel-Krzyczkowski/AzureDeveloperTemplates/tree/34394d365a72c0325a5e155d7bc0b4547f8ded9e

if anyone needs.

Sorry, me again. From a consumer point of view, do you think this is a good idea? https://damienbod.com/2019/04/23/using-azure-service-bus-queues-with-asp-net-core-services/

Using service bus queues (or event hub) to consume and then make use of AppNotifier (and mobile app push) from within web.host.

Hey,

Thanks so much for the kind offer. We have decided to rather push the telemetry messages to the web host using Azure Service Bus and then from there out to all the users via AppNotifier. We are very familiar with Service Bus it and it will streamline better with ABP imo. We also wont need Azure Signal R either.

Going to close this question. Thanks all.

Great stuff, thanks. I will get going and prepare a solution for you. You will need access to an Azure account regarding an Azure Signal R resource so either if you have a dev one to use yours or we can expose ours all already done in the solution.

In fact the entire process will be easier if you just had full access. Let me get that for you thanks!

Hey @ismcagdas

I will demo the process using appNotifier.SendMessageAsync

I have an Azure function which gets triggered by a cosmosDB changefeed (on insert). This is where I would like to push to the relevent user with information about the relevent IoT Message. The problem comes how to setup Signal R/Azure Signal R within an Azure function and even more so, in order to reuse existing logic and abp modules etc etc.

As it stands registering Signal R like this wont work based on the Azure function design:

builder.Services
.AddSignalR(options => { options.EnableDetailedErrors = true; })
.AddAzureSignalR(options => options.Endpoints = new ServiceEndpoint[]
{
    new ServiceEndpoint(_appConfiguration["Azure:SignalR:PrimaryConnectionString"], EndpointType.Primary, "Name1"),
    new ServiceEndpoint(_appConfiguration["Azure:SignalR:SecondaryConnectionString"], EndpointType.Secondary, "Name2"),
});

Azure Function : Microsoft.Azure.WebJobs.Extensions.SignalRService is the package that I attempted with [SignalRConnectionInfo(HubName = "chathub")] SignalRConnectionInfo connectionInfo - https://github.com/Azure/azure-functions-signalrservice-extension

namespace SynapWare.AzureFunction.IoT
{
    public class CosmosdbChangeFeed
    {
        private readonly LatestDeviceDataRepository _latestdeviceDataRepository;

        public CosmosdbChangeFeed(ICosmosDbClientFactory latestdeviceDataRepository)
        {
            _latestdeviceDataRepository = new LatestDeviceDataRepository(latestdeviceDataRepository);
        }

        [FunctionName("CosmosdbChangeFeed")]
        public async Task Run([CosmosDBTrigger(
            databaseName: "synap-staging-db",
            collectionName: "devicedata",
            ConnectionStringSetting = "ConnectionString",
            LeaseCollectionName = "lease-latestdevicedata",
            CreateLeaseCollectionIfNotExists = true)]IReadOnlyList<Document> input, ILogger log,
            //SignalR output Binding
            //[SignalR(HubName = "chat")] IAsyncCollector<SignalRMessage> signalRMessages)
            [SignalRConnectionInfo(HubName = "chathub")] SignalRConnectionInfo connectionInfo)
        {
            if (input != null && input.Count > 0)
            {
                //Build connection with token
                HubConnection _connection = new HubConnectionBuilder()
                .WithUrl(connectionInfo.Url, option =>
                {
                    option.Headers.Add("Authorization", $"Bearer {connectionInfo.AccessToken}");
                })
                .Build();

                //Start the hub connection
                await _connection.StartAsync();

                //My Hub has a BroadcastMessage method that receives 2 arguments
                //await _connection.SendAsync("getChatMessage", "test", "test", default);
                //ChatMessageDto tst = new ChatMessageDto()
                //{
                //    TenantId = null,
                //    UserId = 1,
                //    Message = "test",
                //    CreationTime = DateTime.UtcNow,
                //    TargetUserId = 5,
                //    TargetTenantId = null
                //};
                //await _connection.SendAsync("getChatMessage", tst);
                
                await _connection.SendAsync("App.SimpleMessage", "test");

                foreach (var document in input)
                {
                    //TODO : Only use the latest event for each device 

                    var jsonSer = new JsonSerializerSettings
                    {
                        NullValueHandling = NullValueHandling.Ignore,
                        DefaultValueHandling = DefaultValueHandling.Ignore,
                        ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() }
                    };
                    var deviceData = JsonConvert.DeserializeObject<DeviceData>(document.ToString(), jsonSer);
                    deviceData.Id = deviceData.Serial;
                    await _latestdeviceDataRepository.UpsertAsync(deviceData);

                    // broadcast through SignalR
                    //var signalR = new AzureSignalR("Endpoint=https://synap-staging-signalr-              service.service.signalr.net;AccessKey=abc=;Version=1.0;");
                    //await signalR.SendAsync("chathub", "updateSignInStats", "hello world");

                    //await signalRMessages.AddAsync(new SignalRMessage
                    //{
                    //    Target = "getChatMessage",//"newMessage",
                    //    Arguments = new[] { deviceData }
                    //});

                    using (var obj = Startup.iocManager.ResolveAsDisposable<AzFunctionAbpExecuter>())
                    {
                        //await obj.Object.AddNewDeviceEventAppNotifier(deviceData);

                        await obj.Object.SendTestMessageAppNotifier();
                    }
                }
            }
        }
    }
}

The function above updates a cosmosdb collection and then I would love to push telemetry messages to the UI.

The ABP module for the Azure Function is defined as

namespace SynapWare.AzureFunction.IoT
{
    [DependsOn
        (typeof(AbpZeroCoreEntityFrameworkCoreModule),
        typeof(SynapWareEntityFrameworkCoreModule),
        typeof(AbpAspNetZeroCoreModule),
        typeof(SynapWareCoreModule),
        typeof(SynapWareClientModule), 
        typeof(AbpAutoMapperModule),
        typeof(AbpZeroCoreModule),
        typeof(AbpAspNetCoreSignalRModule))]
    public class SynapWareAzFuncIoTModule : AbpModule
    {
        private readonly IConfigurationRoot _appConfiguration;
        private readonly IServiceCollection _serviceCollection;

        public SynapWareAzFuncIoTModule()
        {
            _appConfiguration = Startup._appConfiguration;
            _serviceCollection = Startup.serviceCollection;
        }

        public override void PreInitialize()
        {
            Configuration.Localization.IsEnabled = false;
            Configuration.BackgroundJobs.IsJobExecutionEnabled = false;
            Configuration.Modules.AspNetZero().LicenseCode = _appConfiguration["AbpZeroLicenseCode"];
            //set time zone
            Clock.Provider = ClockProviders.Utc;

            Configuration.DefaultNameOrConnectionString = _appConfiguration.GetConnectionString(
            SynapWareConsts.ConnectionStringName
            );

            Configuration.ReplaceService(typeof(IEventBus), () =>
            {
                IocManager.IocContainer.Register(
                    Component.For<IEventBus>().Instance(NullEventBus.Instance)
                );
            });
        }

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(SynapWareAzFuncIoTModule).GetAssembly());
            Register(IocManager);
        }

        public static void Register(IIocManager iocManager)
        {
            var services = new ServiceCollection();
            IdentityRegistrar.Register(services);
            WindsorRegistrationHelper.CreateServiceProvider(iocManager.IocContainer, services);
        }
    }
}

And finally the AbpExecutor

namespace SynapWare.AzureFunction.IoT
{
    public class AzFunctionAbpExecuter : ITransientDependency
    {
        private readonly IRepository<Tenant> _tenantRepository;
        private readonly UserManager _userManager;
        private readonly IAppNotifier _appNotifier;

        public AzFunctionAbpExecuter(IRepository<Tenant> tenantRepository, IAppNotifier appNotifier, UserManager userManager)
        {
            _tenantRepository = tenantRepository;
            _appNotifier = appNotifier;
            _userManager = userManager;
        }

        public async Task AddNewDeviceEventAppNotifier(SynapWare.CosmosDB.DeviceData data)
        {
            await _appNotifier.NewDeviceEventAsync(data);
        }

        public async Task SendTestMessageAppNotifier()
        {
            var user = await _userManager.FindByEmailAsync("[email protected]");

            await _appNotifier.SendMessageAsync(
                user.ToUserIdentifier(), "test", Abp.Notifications.NotificationSeverity.Warn);
        }
    }
}

The UI updates (with the relevenet db changes) when using await _appNotifier.SendMessageAsyn for example but nothing real time (as signal r not setup or pushed correctly)

Goodluck for that and thanks for responding guys :)

Yeah Im still puzzled about how to best push messages into Azure Signal R from outside the web host whilst still using as much of the abp/anz framework/work as possible. I can do it manually but would love to stream line it as best as possible - such as using AppNotifier?

BTW on default mode it now works with web.host. It might have been me flipping too often and breaking Azure :)

For anyone that is interested, you need to create a storyboard in VS under resource and set this under the info.plist as per image below

ANZ 9.3 - .NET Core + Angular

I am aware that to change the splash screen to resemble your logo you would do the following:

iOS uses an image to display a splash screen depending on which screen size the application is running on. Replace the images Default*.png in \Resources\ folder with the same sizes. You can also change Icon*.png according to your custom icon.

However how would I go about filling the screen throughout the application for devices such as iPhone x. I attempted setting SafeAreaLayoutGuide in the storyboard however nothing helped.

I also attempted adding these values to the info.plist file but didnt change anything:

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

Thanks!

If you dont mind explaining your Azure Signal R setup - Settings and how you are pushing messages outside the web.host that would be greatly appreciated. I want to try utilize the core libs (abp framework in general) as much as possible without bringing in too much of my own code hence why pushing on with this.

Hey @rickfrankel

Thanks for the awesome info!

So what you said got me digging into the service mode. What is yours? Default, serverless, classic?

In Serverless: Azure SignalR Service is not connected yet, please try again later.

In Default Connection count reaches limit.

However, surely Serverless is the correct approach if I plan on utilizing an Azure Function to push messages (IoT device telemetry messages) as well, outside of the web host?

...Im now starting to think not, 2 seperate Azure Signal R resources. One default for abp and a serverless for azure function?

EDIT:

Its working! However, needs to be in classic mode. Azure functions need to be set in serverless mode. Trigger off say a cosmosdb insert, would love to utilize appnotifier to push deviceeventdata through the system.

Showing 1 to 10 of 46 entries