How can I use session variables in ASP MVC 6 ?
I couldn't find a working sample on how to store and use session variables . Can anyone help ?
add package "Microsoft.AspNet.Session": "1.0.0-beta8" to project.json and then using Microsoft.AspNet.Http;
inside that namespace you have extension methods for context.
you also need to use it with DI on Startup.cs :
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSession();
}
Here's a sample controller :
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc;
namespace MvcWebApp.Controllers
{
[Route("[controller]")]
public class SomeController : Controller
{
public async Task<IActionResult> Edit()
{
HttpContext.Session.SetInt("myVar", 35);
}
}
}
there is a sample on the session repo on github: https://github.com/aspnet/Session/tree/release
And you can access to the session by the Controler's Session property
Related
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.
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;
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>();
Building a custom IUserPasswordStore to connect to a legacy system's username/password table. The password is hashed with custom code in the table so I need to write custom code for PasswordSignInAsync.
Do I need to override PasswordSignInAsync or is there a method I can provide that just does the hashing of the password? If I do override the entire PasswordSignInAsync is there sample code somewhere showing me what needs to be done in the method?
That was easier than I thought.
Override CheckPasswordAsync in UserManager.
For someone who wants to see the complete setup in .NET 6, this is how it looks like:
Step 1:
Add CustomUserManager to override CheckPasswordAsync:
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
public class CustomUserManager<TUser> : UserManager<TUser> where TUser : IdentityUser
{
public CustomUserManager(IUserStore<TUser> store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TUser> passwordHasher, IEnumerable<IUserValidator<TUser>> userValidators,
IEnumerable<IPasswordValidator<TUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<TUser>> logger)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer,
errors, services, logger)
{
}
// THIS IS ONLY CALLED FOR USERS STORED IN YOUR IDENTITY DATABASE
public override Task<bool> CheckPasswordAsync(TUser user, string password)
{
// Add custom check using user.UserName and password
return Task.FromResult(true); // Replace this with your custom check
}
}
Step 2:
Register it in your Program.cs
builder.Services
.AddDefaultIdentity<ApplicationUser>(options =>
{
options.SignIn.RequireConfirmedAccount = false;
})
.AddUserManager<CustomUserManager<ApplicationUser>>() <----- THIS GUY
.AddEntityFrameworkStores<ApplicationDbContext>();
ApplicationUser and ApplicationDbContext look like this:
public class ApplicationUser : IdentityUser
{
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}
Step 3:
Try to Login using this:
var result = await _signInManager.PasswordSignInAsync("SomeUserNameInYourIdentityDatabase", "SomePassword", isPersistent: true, lockoutOnFailure: false);
I have an OWIN pipeline using Nancy:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseNancy();
}
}
The UseNancy() is actually a call to my own custom extension method defined in this gist: https://gist.github.com/TheFastCat/0b7635d9e5795b44e72e
This code is executed both as an Azure Website or an Azure Cloud Service. Based on the context it is executing within I want to use a particular favicon, loaded as an embedded resource from a separate assembly. I do this by specifying separate NancyBootstrappers (each loading the proper favicon for its context).
Is there a more elegant solution to determining the runtime application that is executing the OWIN pipeline? Currently I check app.Properties["host.AppName"] ; however while the Website's app name matches it's assembly configuration, the CloudService app is the name of the Owin startup assembly.class. (see gist). It's cloogey.
Is there a more elegant/simple solution for specifying a custom favicon within Nancy for each of my web applications than creating separate bootstrappers and doing runtime application context checks?
I solved this problem with the help of others on the https://jabbr.net/#/rooms/owin and https://jabbr.net/#/rooms/nancyfx chat boards
Yes. You can contextually check the OWIN host properties:
if (app.Properties.ContainsKey("System.Net.HttpListener"))
{
// self hosted application context
}
2.) Yes.
namespace ClassLib
{
public class Startup()
{
public Startup(byte[] favIcon) { ... }
public void Configuration(IAppBuilder app) { ... }
}
}
[assembly: OwinStartup(typeof(WebHost.Startup))]
namespace WebHost
{
public class Startup()
{
public voic Configuration(IAppBuilder app)
{
new ClassLib.Startup(webhostFavIcon).Configuration(app);
}
}
}
namespace SelfHost
{
private class Program()
{
public void Main(string[] args)
{
using(WebApp.Start(app => new ClassLib.Startup(selfHostFavIcon).Configuration(app))
{}
}
}
}