Automapper Compile Mappings asp.net core - automapper

I'm using the following syntax in my asp.net core startup class to configure automapper:
services.AddAutoMapper(c => c.AllowNullCollections = true, AppDomain.CurrentDomain.GetAssemblies());
I'd like to be able to compile the mappings at startup.
According to the Automapper docs, I should be able to do so via:
var configuration = new MapperConfiguration(cfg => {});
configuration.CompileMappings();
How do I get access to the mapping configuration using AddServices syntax?

You can inject an instance of IConfigurationProvider from the AutoMapper assembly and configure AutoMapper this way. For example, you could use the Configure() Startup Method like this:
public void Configure(IApplicationBuilder app, IConfigurationProvider mapperConfiguration)
{
mapperConfiguration.CompileMappings();
}
Or do it programmatically:
public void Configure(IApplicationBuilder app)
{
var mapperConfiguration = app.ApplicationServices
.GetRequiredService<IConfigurationProvider>();
mapperConfiguration.CompileMappings();
}

Related

How to inject IHttpClientFactory in Container servicestack.net?

I'm working on a solution that interacts with Redis, using the servicestack.net library.
I have a class that inherits from ServiceStack.AppHostBase and asks me for an override of the Configure method. This method has as a parameter a Funq.Container that I see is an implementation of IServiceProvider, IResolver and IContainer, and none of these interfaces have the AddHttpClient method that is provided by the IServiceCollection. Method I need to be able to inject the IHttpClientFactory. Any idea how to solve my problem?
To do it in ASP.NET (not .NET Core), the quick way would be to:
install Microsoft.Extensions.DependencyInjection package and call .AppHttpClient() extension
Build the Service Provider you would normally see in .NET Core
Get the instance of IHttpClientFactory from the Service Provider
Register the instance of IHttpClientFactory with Funq.Container again
using Microsoft.Extensions.DependencyInjection;
public class AppHost : AppHostBase
{
public override void Configure(Container container)
{
...
RegisterHttpClientFactory(container);
}
private container RegisterHttpClientFactory(Container container)
{
var services = new ServiceCollection()
.AddHttpClient();
// You can kind of inspect services returned.
// You can see this extension registers lot of other things too beside
// IHttpClientFactory.
// Also you can see the lifetime of IHttpClientFactory is Singleton.
var serviceProvider = services.BuildServiceProvider();
container.AddSingleton(serviceProvider.GetService<IHttpClientFactory>());
return container;
}
}
If you happen to use Unity Adaptor
Unity has a package to give you an extension as well to build the Service Provider directly into the Unity Container:
using Microsoft.Extensions.DependencyInjection;
using Unity;
using Unity.Microsoft.DependencyInjection;
public static class UnityConfig
{
public static void RegisterTypes(IUnityContainer container)
{
...
container.RegisterServices();
container.RegisterHttpClientFactory();
}
private static IUnityContainer RegisterHttpClientFactory(
this IUnityContainer unityContainer)
{
new ServiceCollection()
.AddHttpClient()
.BuildServiceProvider(unityContainer);
return unityContainer;
}
}
This is the interface definition of IServiceCollection from IServiceCollection.cs:
public interface IServiceCollection : IList<ServiceDescriptor>
{
}
AddHttpClient is just an extension method from Microsoft.Extensions.DependencyInjection that wraps adding a number of additional dependencies to ASP.NET Core IOC.
So you should continue to register it on ASP.NET Core IOC, i.e:
public class Startup : ModularStartup
{
public new void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseServiceStack(new AppHost
{
AppSettings = new NetCoreAppSettings(Configuration)
});
}
}
As any dependencies registered .NET Core Startup are also available to ServiceStack.

ASP.NET Core - StartUp class and Dependency Injection with ILoggerFactory

I'm using ASP.NET Core 2.1 and NLog. If I add a constructor in StartUp that has a dependency on ILoggerFactory it resolves it to a different instance than the one I get in Configure method. In Configure method I call AddNLog and because it's a different instance, the instance I used in ConfigureServices is not ready for NLog.
Any ideas how can I access ILoggerFactory in ConfigureService and have the same instance in Configure so I can call AddNLog? Calling AddNLog in ConfigureServices doesn't work.
I am not sure if I understood the problem, but can't you just do as explained here:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
//...
loggerFactory.AddLog4Net(); // << Add this line
I solved it by registering some code in the application started event.
In Configure method:
appLifetime.ApplicationStarted.Register(() =>
{
InitializeSingletonObjects(app, loggerFactory);
});
At that point everything is initialized correctly and you can do whatever you want in InitializeSingletonObjects. In my case, this is what I did.
private void InitializeSingletonObjects(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
// email template processor
var emailRepository = app.ApplicationServices.GetService<IEmailRepository>();
IEmailTemplateProcessor emailTemplateProcessor = app.ApplicationServices.GetService<IEmailTemplateProcessor>();
string containerName = appConfiguration.AzureBlobStorage.BlobStorageContainerEmailTemplates;
var emailTemplates = emailRepository.GetEmailTemplates(true);
emailTemplateProcessor.Initialize(containerName, emailTemplates);
}
More info about IApplicationLifetime on https://www.khalidabuhakmeh.com/looking-at-asp-net-cores-iapplicationlifetime

Access SignalR Hub without Constructor Injection

With AspNetCore.SignalR (1.0.0 preview1-final) and AspNetCore.All (2.0.6), how can I invoke a method on a hub in server code that is not directly in a Controller and is in a class that cannot be made via Dependency Injection?
Most examples assume the server code is in a Controller and should 'ask' for the hub via an injectable parameter in a class that will created by DI.
I want to be able to call the hub's method from server code at any time, in code that is not injected. The old SignalR had a GlobalHost that enabled this approach. Basically, I need the hub to be a global singleton.
Now, everything seems to be dependent on using Dependency Injection, which is introducing a dependency that I don't want!
I've seen this request voiced in a number of places, but haven't found a working solution.
Edit
To be more clear, all I need is to be able to later access the hubs that I've registered in the Configure routine of the Startup class:
app.UseSignalR(routes =>
{
routes.MapHub<PublicHubCore>("/public");
routes.MapHub<AnalyzeHubCore>("/analyze");
routes.MapHub<ImportHubCore>("/import");
routes.MapHub<MainHubCore>("/main");
routes.MapHub<FrontDeskHubCore>("/frontdesk");
routes.MapHub<RollCallHubCore>("/rollcall");
// etc.
// etc.
});
If I register them like this:
services.AddSingleton<IPublicHub, PublicHubCore>();
it doesn't work, since I get back an uninitiated Hub.
No It's not possible. See "official" answer from david fowler https://github.com/aspnet/SignalR/issues/1831#issuecomment-378285819
How to inject your hubContext:
Best solution is to inject your hubcontext like IHubContext<TheHubWhichYouNeedThere> hubcontext
into the constructor.
See for more details:
Call SignalR Core Hub method from Controller
Thanks to those who helped with this. Here's what I've ended up on for now...
In my project, I can call something like this from anywhere:
Startup.GetService<IMyHubHelper>().SendOutAlert(2);
To make this work, I have these extra lines in Startup.cs to give me easy access to the dependency injection service provider (unrelated to SignalR):
public static IServiceProvider ServiceProvider { get; private set; }
public static T GetService<T>() { return ServiceProvider.GetRequiredService<T>(); }
public void Configure(IServiceProvider serviceProvider){
ServiceProvider = serviceProvider;
}
The normal SignalR setup calls for:
public void Configure(IApplicationBuilder app){
// merge with existing Configure routine
app.UseSignalR(routes =>
{
routes.MapHub<MyHub>("/myHub");
});
}
I don't want all my code to have to invoke the raw SignalR methods directly so I make a helper class for each. I register that helper in the DI container:
public void ConfigureServices(IServiceCollection services){
services.AddSingleton<IMyHubHelper, MyHubHelper>();
}
Here's how I made the MyHub set of classes:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
public class MyHub : Hub { }
public interface IMyHubHelper
{
void SendOutAlert(int alertNumber);
}
public class MyHubHelper : IMyHubHelper
{
public IHubContext<MyHub> HubContext { get; }
public MyHubHelper(IHubContext<MyHub> hubContext)
{
HubContext = hubContext;
}
public void SendOutAlert(int alertNumber)
{
// do anything you want to do here, this is just an example
var msg = Startup.GetService<IAlertGenerator>(alertNumber)
HubContext.Clients.All.SendAsync("serverAlert", alertNumber, msg);
}
}
This is a nice solution. In .NET Core 2.1 the service provider is disposed and you get cannot access disposed object. The fix is to create a scope:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider.CreateScope().ServiceProvider;

AspNet Core CookieAuthentication with injected SessionStore

During migration of an ASPNetCore 1.1 Project to ASPNetCore 2.0, we stumbled upon a Problem with the Cookie-AuthN and its SessionStore.
ASP.NET Core 1 allowed us to do something like that:
public void ConfigureServices(...) {
Services.AddDistributedSqlServerCache(...);
Services.AddSingleton<DistributedCookieSessionStore>(); /// SQL based store
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory) {
var cookieOptions = app.ApplicationServices.GetRequiredService<IOptions<CookieAuthenticationOptions>>().Value;
cookieOptions.SessionStore = app.ApplicationServices.GetRequiredService<DistributedCookieSessionStore>();
app.UseCookieAuthentication(cookieOptions);
}
Messy, but doing its Job.
Now with ASP.NET Core 2 app.UseAuthentication() does not have a signature allowing to modify the options, and I am not able to use DI, to get a hold of the session store.
After long search I came accross this discussion https://github.com/aspnet/Security/issues/1338 where they mentioned IPostConfigureOptions interface. I put that together and this works for me:
1) Implement interface IPostConfigureOptions<CookieAuthenticationOptions>
public class PostConfigureCookieAuthenticationOptions : IPostConfigureOptions<CookieAuthenticationOptions>
{
private readonly ITicketStore _ticketStore;
public PostConfigureCookieAuthenticationOptions(ITicketStore ticketStore)
{
_ticketStore = ticketStore;
}
public void PostConfigure(string name, CookieAuthenticationOptions options)
{
options.SessionStore = _ticketStore;
}
}
2) Register this implementation to the container in Startup.ConfigureServices method
services.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>();

ASP.NET Web Api 2, Ninject, OWIN, and IIS

I'm using Ninject for dependency injection in my ASP.NET Web Api 2 project. Everything is working perfectly locally through Visual Studio and IIS Express, but when I deploy to IIS, the dependency's are not resolved. Below is my Startup.cs
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var webApiConfiguration = new HttpConfiguration();
webApiConfiguration.EnableCors();
webApiConfiguration.SuppressDefaultHostAuthentication();
webApiConfiguration.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
webApiConfiguration.MapHttpAttributeRoutes();
app.UseNinjectMiddleware(CreateKernel).UseNinjectWebApi(webApiConfiguration);
ConfigureAuth(app);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
app.Run(async context =>
{
await context.Response.WriteAsync("Welcome to Web API");
});
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Load(new CourseModule(), new DataPullModule(), new DegreeModule(), new ResponseModule(), new RestSharpModule());
return kernel;
}
}
The error I get is when trying to access one of my controllers is below:
An error occurred when trying to create a controller of type 'DegreeController'. Make sure that the controller has a parameterless public constructor.
Here is my constructor for the DegreeController:
public DegreeController(IDegreeMapper degreeMapper, IDegreeRepository degreeRepository)
{
_degreeMapper = degreeMapper;
_degreeRepository = degreeRepository;
}
And here is the DegreeModule where I bind interfaces to classes.
public class DegreeModule : NinjectModule
{
public override void Load()
{
Bind<IDegreeController>().To<DegreeController>().InRequestScope();
Bind<IDegreeMapper>().To<DegreeMapper>().InRequestScope();
Bind<IDegreeRepository>().To<DegreeRepository>().InRequestScope();
Bind<IDegreeRatingCalculator>().To<DegreeRatingCalculator>().InRequestScope();
}
}
var kernel = CreateKernel();
app.UseNinjectMiddleware(() => kernel).UseNinjectWebApi(configuration);

Resources