How do you add notifcationhubs library - azure-notificationhub

How do you include notificationhubs library to azure function? This is my attempt and it doesn't work
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.Azure.NotificationHubs;
public static void Run(string myQueueItem, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
Notification a;
}

We'll add NotificationHubs to the list of built in assemblies, but for now you can add a package reference to NoficationHubs by adding a project.json file for your Function (as described in the documentation here).
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.Azure.NotificationHubs": "1.0.5"
}
}
}
}
With that in place you can add a using statement for NotificationHubs, e.g.:
using System.Net;
using Microsoft.Azure.NotificationHubs;
public static HttpResponseMessage Run(
HttpRequestMessage req,
TraceWriter log,
out Notification notification)
{
log.Info($"C# HTTP trigger function RequestUri={req.RequestUri}");
// TODO
notification = null;
return req.CreateResponse(HttpStatusCode.OK);
}

Related

Create Timer Azure Function which use CSOM to integrate with SharePoint Online, locally and deployed inside Azure

I have created an Azure Function which runs on schedule bases >> it worked locally and also when i deploy it to Azure >> the function uses PnP core. Here is my startup.cs:-
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using PnP.Core.Auth;
using System.Security.Cryptography.X509Certificates;
[assembly: FunctionsStartup(typeof(FunctionApp2.Startup))]
namespace FunctionApp2
{
class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
var config = builder.GetContext().Configuration;
var azureFunctionSettings = new AzureFunctionSettings();
config.Bind(azureFunctionSettings);
builder.Services.AddPnPCore(options =>
{
options.DisableTelemetry = true;
var authProvider = new X509CertificateAuthenticationProvider(azureFunctionSettings.ClientId,
azureFunctionSettings.TenantId,
StoreName.My,
StoreLocation.CurrentUser,
azureFunctionSettings.CertificateThumbprint);
options.DefaultAuthenticationProvider = authProvider;
options.Sites.Add("Default", new PnP.Core.Services.Builder.Configuration.PnPCoreSiteOptions
{
SiteUrl = azureFunctionSettings.SiteUrl,
AuthenticationProvider = authProvider
});
});
}
}
}
and the function class:-
using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using PnP.Core.Services;
using PnP.Core.Model.SharePoint;
using System.Collections.Generic;
namespace FunctionApp2
{
public class Function1
{
private readonly IPnPContextFactory pnpContextFactory;
public Function1(IPnPContextFactory pnpContextFactory)
{
this.pnpContextFactory = pnpContextFactory;
}
[FunctionName("Function1")]
public void Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
using (var context = pnpContextFactory.Create("Default"))
{
var myList = context.Web.Lists.GetByTitle("Tracking");
Dictionary<string, object> values = new Dictionary<string, object>
{
{ "Title", System.DateTime.Now }
};
//code goes here
}
}
}
}
and finally the localsetting.json :-
{ "IsEncrypted": false,
"Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet",
"SiteUrl": "https://**.sharepoint.com/",
"TenantId": "**",
"ClientId": "**",
"CertificateThumbPrint": "**",
"WEBSITE_LOAD_CERTIFICATES": "**" } }
where i am able to test the function ,locally since i am using the Azure Storage locally + i am able to secure my call to azure active directory App using certificate (self-signed).
now i am trying to do the same project, but instead of using PnP, to use the CSOM library. i search the net but i could not find a complete code, i tried the following from an old post on the net:-
starup.cs code:-
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Identity.Client;
using System.IO;
using System;
using System.Security.Cryptography.X509Certificates;
using Microsoft.SharePoint.Client;
using System.Threading.Tasks;
[assembly: FunctionsStartup(typeof(FunctionApp2.Startup))]
namespace FunctionApp2
{ class Startup :
FunctionsStartup {
public override void Configure(IFunctionsHostBuilder builder)
{private static string ClientId = "(Application ID)";
private static string Cert = "(filename).pfx";
private static string CertPassword = "(password)";
private static string Authority = "https://login.windows.net/(tenantName).onmicrosoft.com/";
private static string Resource = "https://(tenantName).sharepoint.com/";
public async static Task<ClientContext> GetClientContext(string siteUrl)
{
var authenticationContext = new AuthenticationContext(Authority, false);
var certPath = Path.Combine(Environment.GetEnvironmentVariable("HOME"), "site\\wwwroot\\<FunctionName>\\", Cert);
var cert = new X509Certificate2(System.IO.File.ReadAllBytes(certPath),
CertPassword,
X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
var authenticationResult = await authenticationContext.AcquireTokenAsync(Resource, new (ClientId, cert));
var token = authenticationResult.AccessToken;
var ctx = new ClientContext(siteUrl);
ctx.ExecutingWebRequest += (s, e) =>
{
e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + authenticationResult.AccessToken;
};
return ctx;
}
}}
the function code:-
using System; using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using PnP.Core.Services;
using PnP.Core.Model.SharePoint;
using System.Collections.Generic;
namespace FunctionApp2 { public class Function1{
private readonly IPnPContextFactory pnpContextFactory;
public Function1(IPnPContextFactory pnpContextFactory)
{
this.pnpContextFactory = pnpContextFactory;
}
[FunctionName("Function1")]
public void Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
using (var context = pnpContextFactory.Create("Default"))
{
var myList = context.Web.Lists.GetByTitle("Tracking");
Dictionary<string, object> values = new Dictionary<string, object>
{
//code goes here
};
}
}
}}
but currently i am facing these issue:-
inside my startup class for the CSOM project, i am getting an error that AuthenticationContext can not be found and its reference Microsoft.IdentityModel.client.ActiveDirectory is obsolete now
how i can define to use the local storage to be able to debug my code when using CSOM.
what i need to do inside my Function class to replace PnP code with CSOM ?
Thanks

How to execute RPC calls on all clients when this method sent from one client?

How to execute RPC calls on all clients when this method sent from one client? Is it exists some solution in Unity netcode like RPCTargets.All in Photon?
There you go
using UnityEngine;
using Mirror;
public class ExampleChangeSomething : NetworkBehaviour // ->Inherit from NetworkBehaviour
{
void Start()
{
UI_ChangeSomething();
}
//Attach this to the Button click or call this function from somewhere(e.g. I call this on Start)
public void UI_ChangeSomething()
{
//Client Send command to the Server
Cmd_ChangeSomething("Please Print this Text");
}
//Execute this on Server
[Command]
void Cmd_ChangeSomething(string _text)
{
//The server then tell every Clients to execute the "Rpc_ChangeSomething" Function
Rpc_ChangeSomething(_text);
}
[ClientRpc]
void Rpc_ChangeSomething(string _text)
{
ChangeSomething(_text);
}
//the logic that needs to be executed by Every Client
private void ChangeSomething(string _text)
{
//your logic here.
Debug.Log(_text); // every client will print "Please Print this Text" in their Console
}
}

Capture Events From Microsoft.Identity.Web Login/Logout

I am using Microsoft's Authentication/Authorization platform to allow User Sign-ins from Azure AD. I would like to log these events into a database. Issue is, since this type of authentication leverages middleware I am not sure how to inject code to trigger a log event.
Please let me know if there exists documentation I haven't yet found and/or how to write up a custom injection to log these events.
Thanks!
I solved my own problem. For any potential usefulness to anyone else in the future I will add what I did below..
I set up my database according to this documentation: https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-model?view=aspnetcore-5.0&tabs=visual-studio
I created this Middleware Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Identity.Web;
using Application.Models;
using Application.Data;
namespace Application.Middleware
{
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class EventLogCaptureMiddleware
{
private readonly RequestDelegate _next;
private readonly EventLogContext _context;
public EventLogCaptureMiddleware(RequestDelegate next, EventLogContext context)
{
_next = next;
_context = context;
}
public Task Invoke(HttpContext httpContext)
{
var eventLogModel = new EventLogViewModel
{
Timestamp = DateTime.Now,
Type = "TEST",
Method = httpContext.Request.Method,
Upn = httpContext.User.Identity.Name,
Resource = $"{httpContext.Request.Scheme}://{httpContext.Request.Host}{httpContext.Request.Path}"
};
_context.Add(eventLogModel);
var tasks = new Task[] { _context.SaveChangesAsync() };
Task.WaitAll(tasks);
return _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class EventLogCaptureMiddlewareExtensions
{
public static IApplicationBuilder UseEventLogCaptureMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<EventLogCaptureMiddleware>();
}
}
}
And injected into Startup.cs likeso:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
//Production Exception Handler ex: API connection failed will trigger exception routed to /Home/Error
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//Handles User Error: 401, 403, 404, etc. Errors caught must land Application side. Errors occured in API with return 500 and be routed via Exception Handler
app.UseStatusCodePagesWithReExecute("/Home/Error", "?status={0}");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
//Must include Authentication/Authorization under routing
app.UseAuthentication();
app.UseAuthorization();
app.UseEventLogCaptureMiddleware();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}

Chat Application using SignalR and Ionic

I am developing a chat application.I use SignalR and Ionic for this.And I get an error on the Ionic side.
Startup.cs
using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SignalR.Startup))]
namespace SignalR
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
ChatHub.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace SignalR
{
public class ChatHub : Hub
{
public void Send(string username,string message)
{
Clients.All.sendMessage(username,message);
}
}
}
controller.js
angular.module('starter.controllers', [])
.controller('DashCtrl', function ($scope) {
$scope.name = 'Onur'; // holds the user's name
$scope.message = ''; // holds the new message
$scope.messages = []; // collection of messages coming from server
$scope.chatHub = null; // holds the reference to hub
$scope.chatHub = $.connection.chatHub; // initializes hub
$.connection.hub.start(); // starts hub
// register a client method on hub to be invoked by the server
$scope.chatHub.client.broadcastMessage = function (name, message) {
var newMessage = name + ' says: ' + message;
// push the newly coming message to the collection of messages
$scope.messages.push(newMessage);
$scope.$apply();
};
$scope.newMessage = function () {
// sends a new message to the server
$scope.chatHub.server.sendMessage($scope.name, $scope.message);
$scope.message = '';
};
})
Faield to load resource
hubs(0,0)
TypeError: Cannot read property 'chatHub' of undefined
I'm getting errors.Where am I doing wrong.Help me
You need to start the hub after registering client methods. It should work.

Reactive Extensions: Why does this exit immediately?

I am reading IntroToRx and I'm having a bit of trouble with the sample code. Here is the sum total of my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace LearningReactiveExtensions
{
public class Program
{
static void Main(string[] args)
{
var observable = Observable.Interval(TimeSpan.FromSeconds(5));
observable.Subscribe(
Console.WriteLine,
() => Console.WriteLine("Completed")
);
Console.WriteLine("Done");
Console.ReadKey();
}
}
}
If I understand the book correctly, this should write a sequence of numbers to the console, once every five seconds forever since I never Dispose() of the sequence.
However, when I run the code, all I get is the "Done" at the end. No numbers, no "completed", nothing but "Done".
What am I doing wrong here?
I am assuming you haven't had the patience to wait for 5 seconds to elapse otherwise you would have seen that the code is working.
The main idea to keep in mind with Rx is that Observable.Subscribe will return control to calling method almost immediately. In other words, Observable.Subscribe does not block until the results are produced. Thus the call to Console.WriteLine will be invoked only after five seconds.
You need some way to make the main thread wait for what you are doing. You can use a semaphore if you like
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace LearningReactiveExtensions
{
public class Program
{
static void Main(string[] args)
{
SemaphoreSlim ss = new SemaphoreSlim(1);
var observable = Observable.Interval(TimeSpan.FromSeconds(5));
observable.Subscribe(
Console.WriteLine,
() => {
Console.WriteLine("Completed");
ss.Release();
}
);
ss.Wait();
Console.WriteLine("Done");
Console.ReadKey();
}
}
}
Though probably better in this case just to write
static void Main(string[] args)
{
SemaphoreSlim ss = new SemaphoreSlim(1);
Observable.Interval(TimeSpan.FromSeconds(5)).Wait();
Console.WriteLine("Completed");
Console.WriteLine("Done");
Console.ReadKey();
}