I have some experience with Windows Services and am just getting my feet wet with IdentityServer3. My current solution works fine in IISExpress but I can't get it to work in IIS. So, I thought it might be easier to host it in a Windows Service, but I have not been able to find any samples to get up and running. Has anyone taken this approach?
My first though is I will need to instantiate my IS3 Startup class in my OnStart method and then call the Configuration method to create my authentication server, but that method takes an IAppBuilder parameter and I don't know how to create this. Any ideas would be appreciated.
I am doing something similar to this...
public partial class ServiceHost : ServiceBase
{
private IDisposable _service;
public ServiceHost()
{
InitializeComponent();
}
public void Start(string[] args) { OnStart(args); }
protected override void OnStart(string[] args)
{
var options = new StartOptions("https://localhost:44331/");
_service = WebApp.Start(options, Configuration);
}
protected override void OnStop()
{
_service?.Dispose();
}
private static void Configuration(IAppBuilder app)
{
var factory = new IdentityServerServiceFactory()
.UseInMemoryUsers(Users.Get())
.UseInMemoryClients(Clients.Get())
.UseInMemoryScopes(Scopes.Get());
var idsrvOptions = new IdentityServerOptions
{
Factory = factory,
SigningCertificate = Cert.Load(),
AuthenticationOptions = new AuthenticationOptions
{
// This is where we configure External Identity Providers
IdentityProviders = ConfigureIdentityProviders
}
};
app.UseIdentityServer(idsrvOptions);
}
private static void ConfigureIdentityProviders(IAppBuilder app, string signInAsType)
{
}
}
Related
I am having an ASP.net core 3.0 app and I want to see if I can register some of my Orleans Cluster Clients asynchronously on app startup, due to the fact the creation and making the connections to Orleans Cluster are heavy. According to this article I created my own IHostedService, but when I implemented startAsync method I am not sure how to get the autofac container which I am using in Startup.cs and update it with my clients registrations. I have read this but see my below code, still I don't see the clients are getting registered. Is it doable or am I missing anything here? thanks!
Startup.cs
...
public static IServiceProvider ConfigureServices(IServiceCollection services)
{
var coreBuilder = new ContainerBuilder();
// other autofac registrations...
services.AddHostedService<MyService>();
coreBuilder.populate(services);
var container = coreBuilder.Build();
var serviceProvider = new AutofacServiceProvider(container);
return serviceProvider;
}
MyService.cs
public MyService : IHostedService
{
private readonly IServiceProvider _serviceProvider;
public MyService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
// get the autofac container from Startup.cs and update with cluster client registrations?
using(var scope = this._serviceProvider.GetRequiredService<ILifeTimeScope>()
.BeginLifeTimeScope(builder => do registration here...)) {}
}
// noop
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
You cannot update the DI container on-the-fly like that. Once it's built, it's built.
You have another option: make a factory class that caches the clients, initialize them in the background, then retrieve them from the factory.
class MyService
{
// ...
}
class MyServiceFactory
{
private ConcurrentDictionary<string, MyService> _instances = new ConcurrentDictionary<string, MyService>();
public async Task<MyService> CreateAsync(string key)
{
if (_instances.TryGetValue(key, out var service))
{
return service;
}
// perform expensive initialization
// ...
service = new MyService();
_instances[key] = service;
return service;
}
}
class MyServiceInitializer: BackgroundService
{
private MyServiceFactory _serviceFactory;
public MyServiceInitializer(MyServiceFactory serviceFactory)
{
_serviceFactory = serviceFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await _serviceFactory.CreateAsync("first instance");
await _serviceFactory.CreateAsync("second instance");
}
}
Register the factory as singleton, (or make Instances a static property).
services.AddSingleton<MyServiceFactory>();
services.AddHostedService<MyServiceInitializer>();
Then resolve an instance you need. It will resolve instantly, because it's been initialized in the background.
class MyController
{
private MyServiceFactory _serviceFactory;
public MyController(MyServiceFactory serviceFactory)
{
_serviceFactory = serviceFactory;
}
[HttpGet]
public async Task<ActionResult> Index()
{
var service = await _serviceFactory.CreateAsync("first instance");
// use the service
}
}
Umbraco v7.5.8
I have bunch of problems with DI setup (shown below).
1) Neither OnApplicationInitialized, nor OnApplicationStarted (and other) events firing if constructor takes parameter(s).
2) Backoffice is broken. It's not possible to access a content node. Exception message is:
An error occurred when trying to create a controller of type 'ContentController'. Make sure that the controller has a parameterless public constructor.
// Application handlers
public class UmbracoApplicationEventHandler : IApplicationEventHandler
{
private IMenuManager _menuManager;
public UmbracoApplicationEventHandler(IMenuManager menuManager)
{
_menuManager = menuManager;
}
public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
ContentService.Saving += UpdateMenu;
}
private void UpdateMenu(IContentService sender, SaveEventArgs<IContent> saveEventArgs)
{
_menuManager.UpdateMenu();
}
}
// Unity config:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IMenuManager, MenuManager>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
// Owin Startup:
public class UmbracoStandardOwinStartup : UmbracoDefaultOwinStartup
{
public override void Configuration(IAppBuilder app)
{
//ensure the default options are configured
base.Configuration(app);
UnityConfig.RegisterComponents();
}
}
Please read: https://our.umbraco.org/documentation/reference/using-ioc.
You need to register and build your container on OnApplicationStarted event, not earlier if you want to make it work with Umbraco.
Below is the code for controller I want to instantiate using Windsor Castle.
public class TestController : ApiController
{
private ITestService _testService = null;
public TestController(ITestService testService)
{
_testService = testService;
}
public IList<TestClass> Get()
{
IList<TestClass> testObjects = _testService.GetAll().ToList();
return testObjects;
}
}
I've written following code in Global.asax.cs
protected void Application_Start()
{
........................
InitializeServiceLocator();
}
private static void InitializeServiceLocator()
{
_container = new WindsorContainer().Install(FromAssembly.This());
var controllerFactory = new WindsorControllerFactory(_container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
Here is the code for installer =>
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
if (store == null)
{
throw new ArgumentNullException("store");
}
//All MVC controllers
container.Register(Classes.FromThisAssembly().BasedOn<IHttpController>().LifestylePerWebRequest());
AddComponentsTo(container);
}
private void AddComponentsTo(IWindsorContainer container)
{
container.Register(
///DBContext
Component.For<DbContext>().ImplementedBy<SCFEntities>().LifestyleTransient());
container.Register(
Classes.FromAssemblyNamed("MyProject.ApplicationServices").Pick().WithService.DefaultInterfaces().LifestylePerWebRequest(),
Classes.FromAssemblyNamed("MyProject.Data").Pick().WithService.DefaultInterfaces().LifestylePerWebRequest());
}
}
The problem is the controller instance is not created using parameterized constructor. It is expecting a parameterless constructor. Could anybody point out where I am going wrong? Thanks.
Be sure to read all the articles regarding WEB API that Mark Seemann wrote.
You can start here and then traverse the archive for Web API here.
Read the first article and then traverse the archive. Everything is here.
Right now I've got my validators hooked up and building in my app, but every time we add a new validator we need to manually go into our Unity configuration and register the type. I'd like to do this automatically, much like this blog post describes doing with StructureMap, only for Unity instead.
Right now I've got something like this:
// in global.asax.cs
protected void Application_Start(Object sender, EventArgs e)
{
// some irrelevant registrations (area registrations, route config, etc)
var container = new UnityContainer();
UnityConfig.RegisterComponents(container);
FluentValidationModelValidatorProvider.Configure(c => c.ValidatorFactory = new UnityValidatorFactory(container));
}
public class UnityValidatorFactory : ValidatorFactoryBase
{
private readonly IUnityContainer container;
public UnityValidatorFactory(IUnityContainer container)
{
this.container = container;
}
public override IValidator CreateInstance(Type validatorType)
{
if (container.IsRegistered(validatorType))
{
return container.Resolve(validatorType) as IValidator;
}
return null;
}
}
public static class UnityConfig
{
public static void RegisterComponents(IUnityContainer container)
{
container.RegisterTypes(
AllClasses.FromAssemblies(
Assembly.GetAssembly(typeof (UnityConfig)),
WithMappings.FromMatchingInterface, WithName.Default);
RegisterValidators(container);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static void RegisterValidators(IUnityContainer container)
{
container.RegisterType<IValidator<MyFirstViewModel>, MyFirstViewModelValidator>();
container.RegisterType<IValidator<MySecondViewModel>, MySecondViewModelValidator>();
}
}
What I have is working, but I have to keep adding registrations to RegisterValidators() every time a new validator is created. Is there a way I can set this up to automatically detect and register all validators?
This turned out to be pretty easy once I figured out what I was doing, which maybe explains why Googling for the answer was yielding no results. I rewrote RegisterValidators as follows:
private static void RegisterValidators(IUnityContainer container)
{
var validators = AssemblyScanner.FindValidatorsInAssemblyContaining<OneOfMyValidators>();
validators.ForEach(validator => container.RegisterType(validator.InterfaceType, validator.ValidatorType));
}
You can let FV setup do the job for you, please refer to 1st comment here for more details from the contributers
public IServiceProvider ConfigureServices( IServiceCollection services )
{
services.AddAuthorization(options =>...);
services.AddMvc()
.AddFluentValidation( o =>
{
o.RegisterValidatorsFromAssemblyContaining<Startup>();
} );
I think I'm missing something very simple and maybe just need a new set of eyes. I have an ASP.NET MVC application. In that app, I am using Unity for my IoC to handle dependency injection. Each of my repositories need to have a database factory injected into it and each database factory needs to have a principal injected into it. So far, I've been utilizing the PerRequestLifetimeManager to register these.
//Repositories
container.RegisterType<ChatMessageRepository>(new PerRequestLifetimeManager());
container.RegisterType<SignalRConnectionRepository>(new PerRequestLifetimeManager());
//Context
container.RegisterType<IPrincipal, Principal>(new PerRequestLifetimeManager());
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new PerRequestLifetimeManager());
container.RegisterType<UnitOfWork>(new PerRequestLifetimeManager());
Logically, I've tried to register my Hub in the same fashion.
container.RegisterType<ChatHub>(new PerRequestLifetimeManager());
However, whenever I run my app and navigate away from my chat page, I get a "Resolution of the dependency failed" exception and the InnerException tells me "Operation is not valid due to the current state of the object." I've also tried using the default (Transient), PerResolve, and ContainerControlled lifetime Unity managers when registering these guys and cannot seem to get resolve my issue.
Could someone just provide me some demo code with how you used Unity in an ASP.NET MVC application to handle dependency injection into your signalr hubs?
Here's where Unity will inject parameters into my SignalR Hub
public class ChatHub : Hub
{
private readonly ChatMessageRepository _chatMessageRepository;
private readonly SignalRConnectionRepository _signalRConnectionRepository;
private readonly UnitOfWork _unitOfWork;
public ChatHub(ChatMessageRepository chatMessageRepository,
SignalRConnectionRepository signalRConnectionRepository,
UnitOfWork unitOfWork)
{
_chatMessageRepository = chatMessageRepository;
_signalRConnectionRepository = signalRConnectionRepository;
_unitOfWork = unitOfWork;
} ... }
Thanks!
Do it in 3 steps
First. Create UnityHubActivator class
public class UnityHubActivator : IHubActivator
{
private readonly IUnityContainer _container;
public UnityHubActivator(IUnityContainer container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
return (IHub)_container.Resolve(descriptor.HubType);
}
}
Second. Create Unity container and register your dependency resolver before run Startup class
unityContainer = new UnityContainer();
var unityHubActivator = new UnityHubActivator(_unityContainer);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => unityHubActivator);
//register some types in container
WebApp.Start<Startup>(startOptions);
Third. Use it in your Hub
public class MyHub : Hub
{
public MyHub(Logger logger)
{
logger.Info("hub constructor");
}
}
Note. I do not change anything in my Startup class
There's a trick to do that. You will need to do something like this:
container.RegisterType< ChatHub >(new InjectionFactory(CreateChatHub));
......
and then create a private method CreateChatHub
private static object CreateChatHub(IUnityContainer container)
{
return new ChatHub();
}
1 Create "UnitySignalRDependencyResolver.cs"
public class UnitySignalRDependencyResolver : DefaultDependencyResolver
{
protected IUnityContainer Container;
private bool IsDisposed = false;
public UnitySignalRDependencyResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
Container = container.CreateChildContainer();
}
/// <summary>
/// Gets the Autofac implementation of the dependency resolver.
/// </summary>
public static UnitySignalRDependencyResolver Current
{
get { return GlobalHost.DependencyResolver as UnitySignalRDependencyResolver; }
}
public override object GetService(Type serviceType)
{
if (Container.IsRegistered(serviceType))
{
return Container.Resolve(serviceType);
}
return base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
if (Container.IsRegistered(serviceType))
{
return Container.ResolveAll(serviceType);
}
return base.GetServices(serviceType);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (IsDisposed)
{
return;
}
if (disposing)
{
Container.Dispose();
}
IsDisposed = true;
}
}
2.Add your resolver to Owin pipeline
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Get container
IUnityContainer container = UnityConfig.Container;
// Create resolver
var resolver = new UnitySignalRDependencyResolver(container);
// Create SignalR Configuration
var config = new HubConfiguration
{
Resolver = resolver
};
// Start SignalR
app.Map("/signalr", map =>
{
map.RunSignalR(config);
});
}
}
3.Inject your dependency in your controller's constructor
public class ValuesController : ApiController
{
private readonly IMyDependency _myDependency;
public ValuesController(IMyDependency myDependency)
{
_myDependency= myDependency;
}
}