Introducing ASP.Net OWIN to an existing TopShelf Windows Service - c#

I have an existing Windows Service that starts up, reads some configs, spins up some threads and does some useful work.
Currently I log that work (through TopShelf.Log4Net / Log4Net) to disk (or console).
I was thinking it would be nice to expose an API to allow people to query the service (and in the future maybe even config it on the fly)
I'm having difficulty figuring out an appropriate way to plumb the two together though. My existing windows service has a bunch of worker threads and it knows the context of what work is being done, stats and progress and things like that.
But in the context of an ApiController actually handling a request I can't see an obvious/easy means of getting at those stats. I tried passing some object references in the Properties of the IAppBuilder in my Startup class, but any time I explicitly do the config myself I seem to lose the default MVC routes that I had.
Anyone have any suggestions on integrating OWIN into/on top of an existing service?
EDIT: Added code:
So I have a very basic TopShelf runner;
HostFactory.Run(x =>
{
x.Service<MyService>(s =>
{
s.ConstructUsing(name => new MyService());
s.WhenStarted(lb => lb.Start());
s.WhenStopped(lb => lb.Stop());
});
x.RunAsLocalSystem();
And within MyService I had a method StartWorkers() that goes off, starts up a bunch of workers, and keeps track of them.
public class MyService
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List<Worker> workers { get; set; }
private List<Thread> _threads { get; set; }
public MyService()
{
StartWorkers();
}
Now, I want to be able to query for the status of those workers from API requests, so I was thinking I could do something like;
public class MyService
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List<Worker> workers { get; set; }
private List<Thread> _threads { get; set; }
private IDisposable _webServer { get; set; }
public MyService()
{
StartWorkers();
StartWebServer();
}
private void StartWebServer()
{
const string baseAddress = "http://localhost:10281/";
_webServer = WebApp.Start<Startup>(url: baseAddress);
log.DebugFormat("Loaded webserver at address={0}", baseAddress);
}
All of the OWIN code right now is vanilla from the samples.
When I test this code, I can hit the /api/values sample endpoint which is served from the ValuesController, and all is well.
Now where I'm missing a piece of glue is how to access anything useful in my application from my controller. I can do something naive like making the Worker list public static;
public class MyService
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static List<Worker> workers { get; set; }
In which case from my controller I can do something like;
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
// nonsense/test code
return MyService.workers.Select(i => i.ErrorsEncountered.ToString()).ToArray();
}
There must be a better way of access the internals of my application without manipulation visbility.
What I've seen is that I can pass objects into the Properties of the IAppBuilder when using WebApp.Start(). These are visible then from the route configuration, and I see to be able to access them from within my ApiController, e.g.;
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
var someWorker = base.ControllerContext.Configuration.Properties["someWorkerReference"];
The problem I have when I go down that route is that 'WebApp.Start(url: baseAddress);' works and my routes all function, but using the WebApp.Start() method and passing in an Action causes my routes to break
So instead of spending time fixing the routes, I wanted to see if there's an obvious/known/official means of passing "context" into the web server

So this is where having a container is super helpful. If you have something like public class MyService : IStatusProvider {} then you can register both MyService and IStatusProvider to the same instance you. How to use DI container when OwinStartup talks about using OWIN & dependency injection. And you would add the container setup to start of the program, changing s.ConstructUsing(name => new MyService()); to
s.ConstructUsing(name => {
var container = new Container();
// container setup
return container.resolve<MyService>(); // method depends on your container
});

Related

How to inject dependencies from IHostedService before creating scope

I have a multi tenant system with background job. The tenancy details are stored in database and based on the tenant adding request in service bus, I want to resolve the dependencies based on tenant.
For this I would have to add dependencies to service collection before creating scope. When trying to inject IServiceCollection, it gives me error.
I am looking for the best way to inject dependencies from HostedService
public async Task MessageHandler(object sender, Message message)
{
// Inject dependencies
services.AddScoped<IMyService,Myservice>(); // No way to get services here
using (var scope = serviceProvider.CreateScope())
{
var ... = scope.ServiceProvider.GetService<...>();
//...
}
}
I had a similar need a while back. I created my own service bus handler.
You could try something like the below, where you inject a service (here as an example I'm using IMessageService) to the ServiceeBusHandler that itself has a dbcontext injected.
Then where ever you implement IServiceBusHandler you can specify for which tenant (and their queues) you want the connection built.
public class ServiceBusHandler : IServiceBusHandler
{
private readonly ServiceBusSender _serviceBusSender;
private readonly IMessageService _messageService;
public ServiceBusHandler(
ServiceBusSender serviceBusSender,
IMessageService messageService)
{
_serviceBusSender = serviceBusSender;
_messageService = messageService;
}
public async Task PublishMessageAsync<T>(T message)
{
var jsonString = JsonConvert.SerializeObject(message);
var serviceBusMessage = new ServiceBusMessage(jsonString);
await _serviceBusSender.SendMessageAsync(serviceBusMessage);
}
internal static IServiceBusHandler Create(ServiceBusSender sender)
{
return new ServiceBusHandler(sender);
}
}
public class ServiceBusHandlerFactory : IServiceBusHandlerFactory
{
private readonly IAzureClientFactory<ServiceBusClient> _serviceBusClientFactory;
public ServiceBusHandlerFactory(
IAzureClientFactory<ServiceBusClient> serviceBusClientFactory)
{
_serviceBusClientFactory = serviceBusClientFactory;
}
public IServiceBusHandler GetClient(string tenantId)
{
var tenantDetails = _messageService.GetTenantDetails(tenantId); // Call to your DB to get details about the Tenant
var client = GetServiceBusClient(tenantDetails.QueueName);
var sender = client.CreateSender(tenantDetails.QueueName);
return ServiceBusHandler.Create(sender);
}
protected virtual ServiceBusClient GetServiceBusClient(string queueName)
{
var client = _serviceBusClientFactory.CreateClient(queueName);
return client;
}
}
What you are trying to achieve is to change the set of registrations after the Container was built. MS.DI does not support this, and while historically, more mature DI Containers tended to support this behavior, most modern DI Containers stopped supporting this, because there are too many negative consequences in allowing this. Autofac, for instance, obsoleted its Update method in 2016 and described the issues with updating the Container in details. Ninject has gone through a similar process, although development stopped before the final release that removed the possibility to update the Container. The Simple Injector DI Container never supported updating, and its documentation has some clear texts that describe what the issue is.
You might find a DI Container that supports this, but I would urge you to abbondon this path, because of the negative consequences that it can (and probably will) cause, as the previous links described.
Instead, you will have to find a different way to get tenant-specific behavior, with one single set of registrations. The trick here, typically lies in creating a Proxy implementation of your IMyService that can forward the call to the correct tenant implementation.
This might look something like this:
public class ProxyMyService : IMyService
{
public IMyService Service { get; set; }
// IMyService methods
public void SomeMethod() => this.Service.SomeMethod();
}
This proxy class can be registered at startup, together with other IMyService implementations, as follows:
services.AddScoped<IMyService, ProxyMyService>();
services.AddTransient<MyServiceTenant1>();
services.AddTransient<DefaultMyServiceTenant>();
With this, your hosted service can become the following:
private ProxyMyService service;
public MyHostedService(IMyService service)
{
this.service = (ProxyMyService)service;
}
public async Task MessageHandler(object sender, Message message)
{
using (var scope = serviceProvider.CreateScope())
{
var p = scope.ServiceProvider;
var proxy = (ProxyMyService)p.GetRequiredService<IMyService>();
proxy.Service = IsTentant1
? p.GetRequiredService<MyServiceTenant1>()
: p.GetRequiredService<DefaultMyServiceTenant>();
var ... = p.GetRequiredService<...>();
//...
}
}
A more evolved solution would entail a Proxy implementation that allows to switch between tenant-specific implementations internally. That would likely mean moving part of the logic that's currently inside MessageHandler into the ProxyMyService.
Do notice that the solutions I suggested do not require an abstract factory. Abstract factories are typically not needed.

Implementing Airbrake into a ASP.NET MVC 5 project

I have an older .NET 4.8 project that needs to use Airbrake. The project is using Unity for its IoC container, implementing the standard Repository Service pattern.
There's very little in the way of ASP.NET examples.
I am looking to do something like this:
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType(typeof(ILogger<>), typeof(ILogger<>));
container.RegisterType<IMyService, MyService();
}
public class MyController
{
private readonly ILogger<MyController> _logger;
private readonly IMyService _myService;
public MyController(ILogger<MyController> logger, IMyService _myService)
{
_logger = logger;
_myService = myService;
}
public MyMethod()
{
try
{
var x = _myService.DoThis();
}
catch (Exception ex)
{
_logger.LogError(e, e.Message);
}
}
}
I believe I need to either somehow register Airbrake with ILogger or perhaps create my own logging service.
public class Logging : ILogging
{
public void LogError(Exception e, string message)
{
var airbrake = new AirbrakeNotifier(new AirbrakeConfig
{
ProjectId = // pulled from web.config somehow
ProjectKey = // pulled from web.config somehow
});
var notice = airbrake.BuildNotice(ex);
airbrake.NotifyAsync(notice).Result;
}
}
I have tried using this as starting point: https://github.com/airbrake/sharpbrake/blob/master/docs/asp-net-http-module.md
This is excellent, but I need to extend it somehow to be able to use it within my services and not just the .Web project.
I know there's the ASP.NET module that will automatically capture the errors but I am wanting to manually log when I see fit, and avoid having to call the airbrake client every time I want to log an error.
Is there a way to do this or am I completely misunderstanding how this should be working?
You don't actually need to wire it up as part of the .NET ILogger. I am sure there is a way (probably via OWIN) but you nothing stops you from writing a basic logging service as you would any other service and using that via bog standard DI. The answer was pretty much in the question to begin with.

How do you inject an arbitrary/changing set of services into an object using Autofac?

Using Autofac, given multiple interfaces in constructor parameters which is not what I want to achieve, let's say I have;
public class SomeController : ApiController
{
private readonly IDomainService _domainService;
private readonly IService1 _service1;
private readonly IService2 _service2;
private readonly IService3 _service3;
public SomeController(IDomainService domainService,
Iservice1 service1,
IService2 service2,
IService2 service3, ...)
{
_domainService = domainService;
_service1 = service1;
_service2 = service2;
_service3 = service3;
...
}
}
Or, we may do one interface and has multiple properties, e.g.;
public interface IAllServices
{
IDomainService DomainService { get; set; }
IService1 Service1 { get; set; }
IService2 Service2 { get; set; }
IService3 Service3 { get; set; }
}
public class SomeController : ApiController
{
private readonly IAllServices _allServices;
public SomeController(IAllServices allServices)
{
_allServices = allServices;
var domainService1 = _allServices.DomainService;
var service1 = _allServices.Service1;
etc...
}
}
However, I would like to have a list of services, and this code works for me, i.e.;
public interface IMyApp
{
IEnumerable<dynamic> Services { get; set; }
}
public class SomeController : ApiController
{
private readonly IMyApp _myapp;
public SomeController(IMyApp myapp)
{
_myapp = myapp;
foreach (var item in _myapp.Services)
{
if (item is IService1) { // do something... }
if (item is IService2) { // do something... }
if (item is IWhatever) { // do whatever something... }
}
}
}
But, I don't have a better best practice how to create the module, here is my module;
public class MainModule : Autofac.Module
{
private readonly string[] _serviceNames;
private readonly IDomainService _domainService;
public MainModule(IDomainService domainService, params string[] serviceNames)
{
_serviceNames = serviceNames;
_domainService = domainService;
}
protected override void Load(ContainerBuilder builder)
{
List<dynamic> _services = new List<dynamic>();
_services.Add(_domainService);
foreach (var serviceName in _serviceNames)
{
switch (serviceName)
{
case "MyService1":
IService1 service1 = new Service1();
_modules.Add(service1);
break;
case "MyService2":
IService2 service2 = new Service2();
_modules.Add(service2);
break;
case "SomeWhateverService":
IWhatever whateverService = new WhateverService();
_modules.Add(whateverService);
break;
}
}
builder.RegisterType<MyApp>()
.As<IMyApp>()
.WithParameter(new TypedParameter(typeof(IEnumerable<dynamic>), _services));
}
}
So, this code works, but I would like to make my DomainService and all of the Services registered in the container as well. That is, I want to replace whatever inside the switch statement without new keyword.
IService1 service1 = new Service1();
_modules.Add(service1);
And I would like to register the domain service as well. So, inside my Bootstrapper is like this;
public static class Initializer
{
public static IContainer BuildContainer(
HttpConfiguration config, Assembly assembly, IDomainService domainService, params string[] services)
{
var builder = new ContainerBuilder();
builder.RegisterApiControllers(assembly);
builder.RegisterWebApiFilterProvider(config);
builder.RegisterModule(new MainModule(domainService, services));
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
return container;
}
}
And what happen is, I need to create the domain service in the startup, i.e.;
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
MyDomainService domainService = new MyDomainService();
var container =
Initializer.BuildContainer(
GlobalConfiguration.Configuration,
Assembly.GetExecutingAssembly(),
domainService,
"MyService1", "MyService2", "SomeWhateverService");
}
}
You can see that I have to create the domain service first, which is not using IoC;
MyDomainService domainService = new MyDomainService();
and add to the module.
The big question, how to do this in proper way using Autofac. My Bootstrapper is in another project and all of the interfaces are in other project as well.
Many thanks for the help. And sorry for the long question.
Solution:
After testing several model, it seems the best way is to use domain events model for this type of scenario instead of injecting the services into the domain.
The proper way of doing dependency injection is using Constructor Injection. Constructor Injection should always your preferred choice, and only under high exception, you should fall back to another method.
You proposed property injection as an alternative, but this causes Temporal Coupling which means that classes can be initialized while a required dependency is missing, causing null reference exceptions later on.
The method where you inject a collection containing all services where the constructor is responsible of getting the dependencies it needs, is a variation of the Service Locator pattern. This pattern is littered with problems and is considered to be an anti-pattern.
Grouping dependencies into a new class and injecting that is only useful in case that class encapsulates logic and hides the dependencies. This pattern is called Facade Service. Having one big service that exposes the dependencies for others to use can be considered a form of the Service Locator anti-pattern, especially when the number of services that this class exposes starts to grow. It will become the common go-to object for getting services. Once that happens, it exhibits the same downsides as the other form of Service Locator does.
Extracting dependencies into a different class while allowing the consumer to use those dependencies directly doesn't help in reducing complexity of the consumer. That consumer will keep the same amount of logic and the same number of dependencies.
The core problem here seems that your classes get too many dependencies. The great thing about constructor injection though is that it makes it very clear when classes have too many dependencies. Seeking other methods to get dependencies doesn't make the class less complex. Instead of trying other methods of injection, try the following:
Apply the Single Responsibility Principle. Classes should have one reason to change.
Try extracting logic with its dependencies out of the class into a Facade Service
Remove logic and dependencies that deals with cross-cutting concerns (such as logging and security checks) from the class and place them in infrastructure (such as decorators, interceptors or depending on your framework into handlers, middleware, message pipeline, etc).
After testing several model, it seems the best way is just use domain events pattern for this type of scenario instead of injecting the services into the domain.
I refer to Udi Dahan article on domain events:
http://udidahan.com/2009/06/14/domain-events-salvation/

Use factory to resolve dependencies

We have a websolution with autofac. Now we want to reuse things in a windows service/console app where things are only available when a message comes in from an enterprise bus.
I have the following service to reuse
public SettingsService : ISettingsService {
public readonly ITenantIdentifer _tenantIdentifier
public SettingsService (ITenantIdentifier tenantIdentifier) {
this._tenantIdentifier =tenantIdentifier;
}
// do other stuff
}
The current working setup
the ITenantIdentifier for the webcontext is simply registered for the webapplication using builder.RegisterType<WebTenantIdentifier>().As<ITenantIdentifier>();.
Evething works fine.
Our enterprise bus
The enterprise bus can not resolve the ITenantIdentifier until the message is available. So we created a MessageTenantIdentifier and registered a factory.
public class MessageTenantIdentifier : ITenantIdentifier
{
public delegate MessageTenantIdentifier Factory(int tenantId);
public MessageTenantIdentifier(int tenantId, IOtherDependency stuff)
{
_tenantId = tenantId;
// ...
}
}
// somewhere else the this is registered
builder.RegisterType<MessageTenantIdentifier >().As<ITenantIdentifier>().AsSelf();
builder.RegisterGeneratedFactory<MessageTenantIdentifier.Factory>();
The problem
The factory can only be used when the message is being handled in a
public class MsgTypeHandler : IHandleMessages<MsgType>
{
public MsgTypeHandler(ISettingsService settingsService, MessageTenantIdentifier factory) { ...}
public async Task Handle(MsgType message)
{
var tenantId = message.TenantId;
// THIS IS THE MOMENT I CAN CONFIGURE THE MessageTenantIdentifier
var tenantIdentifier = factory.Invoke(tenantId);
// but this factory is not used against the ISettingsService. The service to be reused. <== THE REAL PROBLEM
}
}
The question
So, how can I solve this issue? E.g. how should I setup the registration of the MessageTenantIdentifier in the servicebus?
Or is my dependency setup just plain wrong?
If the MsgTypeHandler class needs an ISettingsService, but the entire object graph can't be resolved until the tenant ID is available, that means that the MsgTypeHandler is the Composition Root. That's OK, but that means that this is where you resolve your entire object graph, so don't inject individual services here; instead, inject the factory you need:
public class MsgTypeHandler : IHandleMessages<MsgType>
{
public MsgTypeHandler(ISettingsServiceFactory factory) {...}
public async Task Handle(MsgType message)
{
var tenantId = message.TenantId;
ISettingsService svc = this.factory.Create(tenantId);
// User svc here...
}
}

How to register Drum.UriMaker<> using Simple Injector?

I'm using Drum which provides a generic class `UriMaker:
public class UriMaker<TController>
{
// I need use this one
public UriMaker(UriMakerContext context, HttpRequestMessage request) { }
public UriMaker(Func<MethodInfo, RouteEntry> mapper, UrlHelper urlHelper) { }
}
Used like this:
public class UserController : ApiController
{
public UserController(UriMaker<UserController> urlMaker) {}
}
I've used to register it with Unity:
container.RegisterType(typeof(UriMaker<>),
new InjectionConstructor(typeof(UriMakerContext), typeof(HttpRequestMessage)));
but now migrating to Simple Injector. I already have this:
UriMakerContext uriMaker = config.MapHttpAttributeRoutesAndUseUriMaker();
container.RegisterSingle(uriMakerContext);
So how now register UriMaker<> itself?
Although it is possible to configure Simple Injector to allow injecting an UriMaker<TController> directly into your controllers, I strongly advice against this for multiple reasons.
First of all, you should strive to minimize the dependencies your application takes on external libraries. This can easily be done by defining an application specific abstraction (conforming the ISP).
Second, injecting the UriMaker directly makes your extremely hard to test, since the UriMaker is pulled into your test code, while it assumes an active HTTP request and assumes the Web API route system to be configured correctly. These are all things you don't want your test code to be dependent upon.
Last, it makes verifying the object graph harder, since the UriMaker depends on an HttpRequestMessage, which is a runtime value. In general, runtime values should not be injected into the constructors of your services. You should build up your object graph with components (the stuff that contains the application's behavior) and you send runtime data through the object graph after construction.
So instead, I suggest the following abstraction:
public interface IUrlProvider
{
Uri UriFor<TController>(Expression<Action<TController>> action);
}
Now your controllers can depend on this IUrlProvider instead of depending on an external library:
public class UserController : ApiController
{
private readonly IUrlProvider urlProvider;
public UserController(IUrlProvider urlProvider)
{
this.urlProvider = urlProvider;
}
public string Get()
{
this.urlProvider.UriFor<HomeController>(c => c.SomeFancyAction());
}
}
Under the covers you of course still need to call Drum, and for this you need to define a proxy implementation for IUrlProvider:
public class DrumUrlProvider : IUrlProvider
{
private readonly UriMakerContext context;
private readonly Func<HttpRequestMessage> messageProvider;
public DrumUrlProvider(UriMakerContext context,
Func<HttpRequestMessage> messageProvider)
{
this.context = context;
this.messageProvider= messageProvider;
}
public Uri UriFor<TController>(Expression<Action<TController>> action)
{
HttpRequestMessage message = this.messageProvider.Invoke();
var maker = new UriMaker<TController>(this.context, message);
return maker.UriFor(action);
}
}
This implementation can be registered as singleton in the following way:
container.EnableHttpRequestMessageTracking(config);
UriMakerContext uriMakerContext =
config.MapHttpAttributeRoutesAndUseUriMaker();
IUrlProvider drumProvider = new DrumUrlProvider(uriMakerContext,
() => container.GetCurrentHttpRequestMessage());
container.RegisterSingle<IUrlProvider>(drumProvider);
This example uses the Simple Injector Web API integration package to allow retrieving the current request's HttpRequestMessage using the EnableHttpRequestMessageTracking and GetCurrentHttpRequestMessage extension methods as explained here.

Categories

Resources