Azure DocumentDB client calls result in an error from Azure WebJob - c#

I have a Continuous Azure Webjob that checks DocumentDb on each message from QueueTrigger. Use DocumentDB SDK 1.10 for .NET. I keep getting errors like this from time to time:
Only one usage of each socket address (protocol/network address/port) is normally permitted :443
at Microsoft.Azure.Documents.Client.GatewayServiceConfigurationReader.d__0.MoveNext()
I have dependency injection (StructureMap) through the JobActivator and use non-static method to process queue triggers within Functions class. use
DocumentClient is wrapped in a static class so it should be one instance per WebJob.
Also some web apps (ASP.NET MVC) use their own document db connection with same connection string from time to time. I could not find any information about this issue. What could be go wrong here?
Changed internal code:
class Program
{
public static IReliableReadWriteDocumentClient Client { get; set; }
static void Main()
{
Client = // initialize client with settings from app config
}
}
public class Functions
{
public async Task ProcessQueueMessage([QueueTrigger("myqueuename")] CustomerRequest customerRequest,
TextWriter dashboardLogger)
{
// usage from some place which runs on QueueTrigger
var customerRepository = new DocumentDbRepository<Customer>(Program.Client, databaseId,
() => "Customers");
// additional logic
}
}
Repository class is taken from here: https://github.com/Crokus/documentdb-repo

Related

How to have global database connection across the application in .net core with mongodb?

I am new to .net core. I have to build rest apis with MongoDB. I am wondering how can i have a global database connection and global configuration to get any collection of the database. What i found on the internet is that i can have database name, connection string, collection name in the appsettings.json and create a class like this
public class MongoDBSettings {
public string ConnectionURI { get; set; } = null!;
public string DatabaseName { get; set; } = null!;
public string CollectionName { get; set; } = null!;
}
After this i can configure this database connection in the Program.cs
builder.Services.Configure<MongoDBSettings(builder.Configuration.GetSection("MongoDB"));
builder.Services.AddSingleton<MongoDBService>();
Now for querying on the collection i should do like this in the respective service file let say OrderService.cs
private readonly IMongoCollection<Playlist> _playlistCollection;
public OrderService(IOptions<MongoDBSettings> mongoDBSettings) {
MongoClient client = new MongoClient(mongoDBSettings.Value.ConnectionURI);
IMongoDatabase database = client.GetDatabase(mongoDBSettings.Value.DatabaseName);
_playlistCollection = database.GetCollection<Playlist>(mongoDBSettings.Value.CollectionName);
}
public async Task<List<Playlist>> GetAsync() { // my code here }
I understand all above mentioned approach. But the problem with this approach is that there is no global connection in the application. Every time i have to query on any collection then each entity service like orderService.cs will create a new database connection like i mentioned above like this
MongoClient client = new MongoClient(mongoDBSettings.Value.ConnectionURI);
So this is inefficient. And second problem with this approach is that to get each database collection's instance i have to write these 3 lines of code in every service.cs file to get instance of each collection like this
MongoClient client = new MongoClient(mongoDBSettings.Value.ConnectionURI);
IMongoDatabase database = client.GetDatabase(mongoDBSettings.Value.DatabaseName);
_playlistCollection = database.GetCollection<Playlist>(mongoDBSettings.Value.CollectionName);
So how can i overcome both the issues and can i solve these 2 problems?
How to have global database connection that will be generic and can be used from every?
How to have generic logic to get instance of database collection's instance?
You need a dbcontext class that will store all of your tables (dbsets) so you can access them anywhere on the application. I'll use this repo as a basic example.
You have the context class and it's interface which are later on injected via DI on to every controller or class constructor you need. (Check line 75 on Startup.cs).
Once that is done you might use your context interface anywhere. For example, in a repository class. As for your db configuration settings I don't see why you might need to have that all over the application. Maybe you only needed at Startup.cs but in case you do check out the options monitor object. It comes handy when you need configurations from appSettings.json into your objects anywhere on the application. Just make sure you're not exposing any app secrets publicly.

Does Transient Dependency Injection of an ServiceBus Azure Function will be injected for every run?

I have an Azure Function that listens for a ServiceBus and one of the roles of the process is to generate some GUIDs.
I can't share my code but it look something like this:
public class ServiceBusListenerFunction
{
private readonly IProcessService _processService;
public ServiceBusListenerFunction(IProcessService processService)
{
_processService = processService;
}
[FunctionName("MyServiceBusFunction")]
public async Task Run([ServiceBusTrigger("my-queue")] string message)
{
await _processService.Run(message);
}
}
I injected IProcessService as Transient in an atempt to inject for every Run call of my function.
My concern are all concurrent calls, even for a very little chance, generate duplicate GUID.
There is a way to manually inject IProccessService and all its dependencies for every call?
Thank you in advance!

How to get hold of the right SignalR hub in other part of application?

I am using SignalR v2.41, which is old, but I have to use it since I am also limited to using an old version of MVC. That aside, I am also using FluentScheduler to send targeted messages to clients at intervals.
Problem is, I am keeping a dictionary of user connections in my Hub:
public class MyHub: Hub
{
public Dictionary<string, User> Connections { get; set; }
public MyHub()
{
Connections = new Dictionary<string, User>();
}
public override Task OnConnected()
{
// add connection
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
// remove connection
return base.OnDisconnected(stopCalled);
}
}
Now in the FluentScheduler code I need to get hold of the hub for the connections list so I know which connection to send what to:
public class MyJob : IJob
{
public void Execute()
{
var hub = new DefaultHubManager(GlobalHost.DependencyResolver).ResolveHub("MyHub") as MyHub;
foreach (var conn in hub.Connections)
{
foreach (var msg in msgs)
{
hub.Clients.Client(conn.Key).send(msg);
}
}
}
}
Problem is, the hub instance I get using var hub = new DefaultHubManager(GlobalHost.DependencyResolver).ResolveHub("MyHub") as MyHub; is different from the one to which clients connect, as this one never has any connections.
How can I get the right hub instance?
The new is always a new instance so you will never get the hub where your clients are connected because you creating a new hub.
You should resolve the hub like this:
static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
You also can check this question.
Edit: Since you need to send messages to specific users, I would recommend to implement a class to add and remove the connections, or even better, map users to groups.
It's recommend that you always inject IHubContext than the Hub. Quote from a SignalR developer on github:
You generally shouldn't resolve the Hub out of DI. If you need to share code between your Hub and some other component, I'd suggest using either IHubContext or putting the shared code in a separate DI service instead.
Also you should not add the Hub as a singleton:
SignalR expects the Hub to be created separately for each message. You need to add it as a Transient service if you want your Hub to be in DI.
and
Because instances of the Hub class are transient, you can't use them to maintain state from one method call to the next. Each time the server receives a method call from a client, a new instance of your Hub class processes the message. To maintain state through multiple connections and method calls, use some other method such as a database, or a static variable on the Hub class, or a different class that does not derive from Hub.
More documentation about Hub object lifetime.

Instantiate SignalR Hub Object With IHubContext

It seems like a big use for SignalR Hubs is to display the actions of one client to all of the other clients. What I hope to use SignalR for is when a certain event happens in my server side code, I want to instantiate a hub object and invoke one of its methods to communicate with all of the clients. If you see my previous post (Route To Take With SqlDependency OnChange), I would like to do this in the OnChange method of SqlDependency. Upon researching it I have found some people talk about using an IHubContext object, though I haven't found many examples of instantiation and actual sending data to clients.
Is this possible to do (and what might sending data to all clients with IHubContext look like if possible), and if not, are there any ways I might be able to get around instantiating a hub like this?
SignalR for ASP.NET Core
You can create a class that has the IHubContext<T> injected in. Inject other dependencies if you want, or resolve the service from controllers or other classes.
public class NotificationService
{
private readonly IHubContext<MyHub> _myHubContext;
public NotificationService(IHubContext<MyHub> myHubContext)
{
_myHubContext= myHubContext;
}
public async Task SendMessage(string message)
{
await _myHubContext.Clients.All.SendAsync("Update", message);
}
}
Assuming you're using SqlDependency from an IHostedService:
public class MyHostedService : IHostedService
{
public MyHostedService(
NotificationService notificationService)
{
// TODO get reference to sqlDependency
sqlDependency.OnChange += (s, e) => _notificationService.SendMessage(e.Info.ToString());
}
}
SignalR for ASP.NET
var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
context.Clients.All.sendMessage(message);
You need to use using Microsoft.AspNet.SignalR library.
using Microsoft.AspNet.SignalR;
//Instantiating. SignalRHub is the hub name.
var context = GlobalHost.ConnectionManager.GetHubContext<SignalRHub>();
//sends message
context.Clients.Client(ClientId).sendMessage(data);

stub webserver for integration testing

I have some integration tests where I want to verify certain requires are made against a third-[arty webserver. I was thinking I would replace the third-party server with a stub server that simply logs calls made to it. The calls do not need to succeed, but I do need a record of the requests made (mainly just the path+querystring).
I was considering just using IIS for this. I could 1) set up an empty site, 2) modify the system's host file to redirect requests to that site 3) parse the log file at the end of each test.
This is problematic as for IIS the log files are not written to immediately, and the files are written to continuosly. I'll need to locate the file, read the contents before the test, wait a nondeterministic amount of time after the test, read the update contents, etc.
Can someone think of a simpler way?
You could use the System.Net.HttpListener ( MSDN LINK ).
It works as embedded WebServer, this means you can even check the access on-the-fly without having to parse log files.
A class i used in my Code recently:
class Listener
{
private HttpListener listener = null;
public event EventHandler CommandReceived;
public Listener()
{
this.listener = new HttpListener();
this.listener.Prefixes.Add("http://localhost:12345/");
}
public void ContextReceived(IAsyncResult result)
{
if (!this.listener.IsListening)
{
return;
}
HttpListenerContext context = this.listener.EndGetContext(result);
this.listener.BeginGetContext(this.ContextReceived, this.listener);
if (context != null)
{
EventHandler handler = this.CommandReceived;
handler(context, new EventArgs());
}
}
public void Start()
{
this.listener.Start();
this.listener.BeginGetContext(this.ContextReceived, this.listener);
}
public void Stop()
{
this.listener.Stop();
}
}
Yeah, I don't think you need a whole webserver. You don't need to test HTTP.
What you do need to test is the underlying data structure that you're sending and receiving. So just create tests for that (i.e. make a point at which you can validate your generate dataformat with what is expected, and also with what you intend to receive, etc).
Test the data, not the protocol (unless, obviously, the protocol is custom).
I've done something very similar to this in a number of projects.
You don't want to create stubbed web service. That's just adding a dependency you don't need. What I did was create an interface which mimics the web service's API. I then created a proxy class that will call the web service in the live system. For testing I used RhinoMocks to create mocked classes that return the results I wanted to test for. This was very useful for me, as I could then produce all sorts of 'unexpected' behaviour which wouldn't be possible with the live system.
public interface IServiceFacade {
string Assignments();
}
public class ServiceFacade : IServiceFacade {
private readonly Service _service;
public ServiceFacade(Service service) {
_service = service;
}
public string Assignments() {
return _service.Assignments();
}
}
Then my test code contained stuff like this:
var serviceFacade = MockRepository.GenerateMock<IServiceFacade>();
serviceFacade.Stub(sf => sf.Assignments()).Return("BLAH BLAH BLAH");
or
serviceFacade.Stub(sf => sf.Assignments()).Return(null);
or
serviceFacade.Stub(sf => sf.Assignments()).Throw(new Exception("Some exception"));
I found this very useful.

Categories