Following the advice I have been given in this thread [Ninject UOW pattern, new ConnectionString after user is authenticated I now understand that I should not use the following line...
var applicationConfiguration =
(IApplicationConfiguration)
DependencyResolver.Current.GetService(typeof(IApplicationConfiguration));
...as a Service Locator is an anti-pattern.
But in the case of the following procedure how can I instantiate my concrete object that implements "IApplicationConfiguration" so that I can use that object to get the unknown user role name, or use it to assign to the "ApplicationConfiguration" property of my principle?
Global.asax
public class MvcApplication : NinjectHttpApplication
{
/// <summary>
/// Handles the PostAuthenticateRequest event of the Application control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
String[] roles;
var applicationConfiguration =
(IApplicationConfiguration)
DependencyResolver.Current.GetService(typeof(IApplicationConfiguration));
var identity = HttpContext.Current.User.Identity;
if (Request.IsAuthenticated)
{
roles = Roles.GetRolesForUser(identity.Name);
}
else
{
roles = new[] { applicationConfiguration.UnknownUserRoleName };
}
var webIdentity = new WebIdentity(identity, roles);
var principal = new WebsitePrincipal(webIdentity)
{
ApplicationConfiguration = applicationConfiguration
};
HttpContext.Current.User = principal;
}
.
.
.
}
Resolution Mapping Code
public class ApplicationConfigurationContractMapping : NinjectModule
{
public override void Load()
{
Bind<IApplicationConfiguration>()
.To<ApplicationConfiguration>();
}
}
ApplicationConfiguration
public class ApplicationConfiguration : IApplicationConfiguration
{
.
.
.
.
}
I am using Ninject as my Dependency Injection framework. Any suggestions appreciated.
EDIT: Full code can be seen here:
https://github.com/dibley1973/Dibware.Template.Presentation.Web
You can't prevent having to call either the DI Container or an abstraction over it in your Application_PostAuthenticateRequest, but that shouldn't be a problem, since this Application_PostAuthenticateRequest can be considered to be part of your Composition Root. Or in other words: you have to resolve it somewhere.
The problem in your case, however, is that this method contains an awful lot of code, and the real problem is that you are missing an abstraction. To resolve this, extract all logic of this method into a new class and hide it behind an abstraction. What will be left is the following code:
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
var provider = (IPostAuthenticateRequestProvider)
DependencyResolver.Current.GetService(typeof(IPostAuthenticateRequestProvider));
provider.ApplyPrincipleToCurrentRequest();
}
The code can be built up by your DI Container, and will have the following signature:
public class MvcPostAuthenticateRequestProvider : IPostAuthenticateRequestProvider
{
private readonly IApplicationConfiguration configuration;
public MvcPostAuthenticateRequestProvider(IApplicationConfiguration configuration)
{
this.configuration = configuration;
}
public void ApplyPrincipleToCurrentRequest()
{
// ...
}
}
Following Steven's suggestion, the final code was:
A new interface "IPostAuthenticateRequestProvider"
/// <summary>
/// Defines the expected members of a PostAuthenticateRequestProvider
/// </summary>
internal interface IPostAuthenticateRequestProvider
{
/// <summary>
/// Applies a correctly setup principle to the Http request
/// </summary>
/// <param name="httpContext"></param>
void ApplyPrincipleToHttpRequest(HttpContext httpContext);
}
A concrete class that implements "IPostAuthenticateRequestProvider"
/// <summary>
/// Provides PostAuthenticateRequest functionality
/// </summary>
public class MvcPostAuthenticateRequestProvider : IPostAuthenticateRequestProvider
{
#region Declarations
private readonly IApplicationConfiguration _configuration;
#endregion
#region Constructors
public MvcPostAuthenticateRequestProvider(IApplicationConfiguration configuration)
{
_configuration = configuration;
}
#endregion
#region IPostAuthenticateRequestProvider Members
/// <summary>
/// Applies a correctly setup principle to the Http request
/// </summary>
/// <param name="httpContext"></param>
public void ApplyPrincipleToHttpRequest(HttpContext httpContext)
{
// declare a collection to hold roles for the current user
String[] roles;
// Get the current identity
var identity = HttpContext.Current.User.Identity;
// Check if the request is authenticated...
if (httpContext.Request.IsAuthenticated)
{
// ...it is so load the roles collection for the user
roles = Roles.GetRolesForUser(identity.Name);
}
else
{
// ...it isn't so load the collection with the unknown role
roles = new[] { _configuration.UnknownUserRoleName };
}
// Create a new WebIdenty from the current identity
// and using the roles collection just populated
var webIdentity = new WebIdentity(identity, roles);
// Create a principal using the web identity and load it
// with the app configuration
var principal = new WebsitePrincipal(webIdentity)
{
ApplicationConfiguration = _configuration
};
// Set the user for the specified Http context
httpContext.User = principal;
}
#endregion
}
And in global.asax...
public class MvcApplication : NinjectHttpApplication
{
/// <summary>
/// Handles the PostAuthenticateRequest event of the Application control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
// Get a PostAuthenticateRequestProvider and use this to apply a
// correctly configured principal to the current http request
var provider = (IPostAuthenticateRequestProvider)
DependencyResolver.Current.GetService(typeof(IPostAuthenticateRequestProvider));
provider.ApplyPrincipleToHttpRequest(HttpContext.Current);
}
.
.
}
Related
I have been struggling on this issue for weeks now.
I have an app where i have configured owin backend with web api and autofac DI with background handfire jobs. I have alsmost looked at every question on Stackoveflow regarding this but nothing seems to work.
My app regarding OWIN/Hangfire/WebAPI all seems to work okay. Until it comes to SignalR push messages.
If i call any notification hub endpoint from js client push messages go okay and i can receive push messages on any other connected client. But when i wan to send message from my api controller or hangfire job it never reaches to any client.
Startup.cs
public void Configuration(IAppBuilder app)
{
//var signalRHelper = new SignalRHelper(GlobalHost.ConnectionManager.GetHubContext<NotificationHub>());
var constants = new Constants();
constants.Set(ConstantTypes.AllyHrNoReplyEmailAddress, Util.Constants.AllyHrNoReplyEmailAddress);
constants.Set(ConstantTypes.SendGridKey, Util.Constants.SendGridKey);
constants.Set(ConstantTypes.EncryptionKey, Util.Constants.EncryptionKey);
constants.Set(ConstantTypes.ApiUrl, Util.Constants.ApiUrl);
constants.Set(ConstantTypes.RootFolder, Util.Constants.RootFolder);
constants.Set(ConstantTypes.FrontEndUrl, Util.Constants.FrontEndUrl);
GlobalConfiguration.Configuration
.UseSqlServerStorage("AllyHrDb");
var config = System.Web.Http.GlobalConfiguration.Configuration;
var builder = new ContainerBuilder();
var jobBuilder = new ContainerBuilder();
var signalRBuilder = new ContainerBuilder();
var hubConfig = new HubConfiguration();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
builder.Register(x => constants);
builder.RegisterModule(new ServiceModule());
jobBuilder.Register(x => constants);
jobBuilder.RegisterModule(new HangfireServiceModule());
signalRBuilder.RegisterModule(new SignalRServiceModule());
signalRBuilder.Register(x => constants);
signalRBuilder.RegisterType<AutofacDependencyResolver>().As<IDependencyResolver>().SingleInstance();
signalRBuilder.RegisterType<ConnectionManager>().As<IConnectionManager>().ExternallyOwned().SingleInstance();
signalRBuilder.RegisterType<NotificationHub>().ExternallyOwned().SingleInstance();
signalRBuilder.RegisterType<SignalRHelper>().PropertiesAutowired().ExternallyOwned().SingleInstance();
signalRBuilder.Register(context => context.Resolve<IDependencyResolver>().Resolve<IConnectionManager>().GetHubContext<NotificationHub, INotificationHub>()).ExternallyOwned().SingleInstance();
var hubContainer = signalRBuilder.Build();
builder.RegisterInstance(hubContainer.Resolve<IConnectionManager>());
builder.RegisterInstance(hubContainer.Resolve<IHubContext<INotificationHub>>());
builder.RegisterInstance(hubContainer.Resolve<NotificationHub>());
builder.RegisterInstance(hubContainer.Resolve<SignalRHelper>());
jobBuilder.RegisterInstance(hubContainer.Resolve<IHubContext<INotificationHub>>());
jobBuilder.RegisterInstance(hubContainer.Resolve<NotificationHub>());
jobBuilder.RegisterInstance(hubContainer.Resolve<SignalRHelper>());
var container = builder.Build();
var jobContainer = jobBuilder.Build();
var idProvider = new SignalRCustomUserIdProvider();
hubConfig.Resolver = new AutofacDependencyResolver(hubContainer);
hubConfig.Resolver.Register(typeof(IUserIdProvider), () => idProvider);
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
Provider = new QueryStringOAuthBearerProvider()
});
map.RunSignalR(hubConfig);
});
GlobalConfiguration.Configuration.UseAutofacActivator(jobContainer);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseHangfireServer();
app.UseHangfireDashboard();
ConfigureAuth(app);
app.UseWebApi(config);
}
I had to use different container because i have db set to InstancePerRequest scope.
All my services are being resolved in notification hub class, no problems there. The only issues is when i try and send message from hangfire service or even from api controller using hub context it never reaches to any client.
NotificationHub.cs
public interface INotificationHub
{
/// <summary>
///
/// </summary>
void pushNotification(string message);
/// <summary>
///
/// </summary>
/// <param name="model"></param>
void getNotification(object model);
void getMessage(object model);
}
/// <summary>
/// Notification Hub
/// </summary>
[HubName("NotificationHub")]
[Authorize]
public class NotificationHub : Hub<INotificationHub>
{
/// <summary>
///
/// </summary>
public static IHubContext<INotificationHub> GlobalContext { get; private set; }
private readonly IChatMessagingService _chatMessagingService;
private readonly IUserService _userService;
private Guid LoggedInUserId
{
get
{
var claims = ((ClaimsIdentity)Context.User.Identity).Claims.ToArray();
var userIdClaim = claims.FirstOrDefault(x => x.Type.Equals("UserId"));
if (userIdClaim == null) return Guid.Empty;
return Guid.Parse(userIdClaim.Value);
}
}
/// <summary>
/// Consructor
/// </summary>
/// <param name="lifetimeScope"></param>
/// <param name="context"></param>
public NotificationHub(ILifetimeScope lifetimeScope, IHubContext<INotificationHub> context)
{
GlobalContext = context;
try
{
var childScope = lifetimeScope.BeginLifetimeScope();
_chatMessagingService = childScope.Resolve<IChatMessagingService>();
_userService = childScope.Resolve<IUserService>();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
/// <summary>
/// Notifications
/// </summary>
public void Notifications()
{
Clients.All.pushNotification("AllyHr" + LoggedInUserId);
}
/// <summary>
/// Send Message
/// </summary>
/// <param name="model"></param>
public void SendMessage(SendChatMessageBindingModel model)
{
var chatMessage = _chatMessagingService.SendMessageToGroup(LoggedInUserId, model.GroupId, model.Message);
var recipientIds = _chatMessagingService.GetChatMembersByGroupId(LoggedInUserId, model.GroupId);
var stringUserIds = new List<string>();
var chatGroup = _chatMessagingService.GetChatGroupById(model.GroupId);
foreach (var recipientId in recipientIds)
{
stringUserIds.Add(recipientId.ToString());
}
Clients.Users(stringUserIds).getNotification(new
{
message = "A new Message is Recieved in Chat Group: " + chatGroup.Name,
groupId = chatGroup.Id
});
var chatMessageVm = chatMessage.Map<ChatMessage, ChatMessageViewModel>();
chatMessageVm.Sender = _userService.Get(chatMessageVm.SenderId).Map<User, UserViewModel>();
stringUserIds.Add(LoggedInUserId.ToString());
Clients.Users(stringUserIds).getMessage(chatMessageVm);
}
}
signalRhelper.cs use to call from api or from Hangfire services
public class SignalRHelper
{
public IConnectionManager ConnectionManager { get; set; }
public IHubContext<INotificationHub> HubContext { get; set; }
/// <summary>
/// Send Notifications to Users
/// </summary>
/// <param name="message"></param>
/// <param name="userIds"></param>
public void GetNotification(object message, IList<string> userIds)
{
HubContext.Clients.Users(userIds).getNotification(message);
}
/// <summary>
/// Get LoggedInUser Id for SignalR
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public static Guid GetLoggedInUserId(IPrincipal user)
{
var claim = GetLoggedinUserClaim(user);
if (claim == null) return Guid.Empty;
return Guid.Parse(claim.Value);
}
private static Claim GetLoggedinUserClaim(IPrincipal user)
{
var claim = ((ClaimsIdentity)user.Identity).Claims.ToArray();
return claim.FirstOrDefault(x => x.Type.Equals("UserId"));
}
}
Could this be related to Autofac creating a new lifetimescope for your call, but you were expecting to continue using the existing scope? Maybe check your autofac registrations for singleinstance / instanceperlifetimescope
Just saying, but have you registered any static classes? They can keep your scope alive for far too long.
I see you're using multiple containerbuilders - that's not something we do over here, we have one 'massive' containerbuilder for each app. I'm curious why you're doing that? To satisfy my curiosity, could you try using a single containerbuilder and registering everything on that single builder? (Although it looks like this is a pattern for SignalR and autofac)
The documentation says: " a common error in OWIN integration is the use of GlobalHost."
It looks like you're doing exactly that.
I'm trying to save my objects to my local database. We are using Microsoft Entity Framework and Ninject. Currently when I try to save my object I get the 'An entity object cannot be referenced by multiple instances of IEntityChangeTracker.' error. We are able to get data from the database currently, it is saving data that is causing problems.
The error is given the moment the savetickets function is called, Visual studio displays the error in the repository at context.Tickets.add(ticket). I have tried passing a single object instead of a list and saving that, this has however caused the same error.
We apply the same principle of creating repositories in other controllers as well for getting data from the database before we get to this part of the code where I'm trying to save tickets.
We have added a Ninject binding
kernel.Bind<ITicketRepository>().To<TicketRepository>();
Our EFDBContext looks like this
public class EFDbContext : DbContext
{
public DbSet<Ticket> Tickets { get; set; }
// Other Entities
public EFDbContext() : base("EFDbContext"){
}
}
The interface for the ticketrepository looks like this
public interface ITicketRepository
{
// Other functions
void SaveTickets(List<Ticket> tickets);
}
The repository implementing this interface looks like this
public class TicketRepository : ITicketRepository
{
private EFDbContext context = new EFDbContext();
// Other functions
public void SaveTickets(List<Ticket> tickets)
{
foreach (var item in tickets)
{
context.Tickets.Add(item);
}
context.SaveChanges();
}
}
The moment all of this is called is in my printtickets function. This is the only time the ticketrepository is created and called for in the code.
public class ReservationController : Controller
{
// Other repositories
private ITicketRepository ticketRepository;
public ReservationController(IMovieOverviewRepository movieRepository, IShowRepository showRepository, ITicketRepository ticketRepository)
{
// Other repositories
this.ticketRepository = ticketRepository;
}
// Other code
[HttpGet]
public ActionResult PrintTickets()
{
List<Ticket> tickets = (List<Ticket>)TempData["TicketList"];
ticketRepository.SaveTickets(tickets);
// Irrelevant stuff
}
}
EDIT: Our full ninject configuration. NinjectWebCommon.cs
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
System.Web.Mvc.DependencyResolver.SetResolver(new Sprint123.WebUI.Infrastructure.NinjectDependencyResolver(kernel));
}
}
And NinjectDependencyResolver.cs
namespace Sprint123.WebUI.Infrastructure
{
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernelParam)
{
kernel = kernelParam;
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
kernel.Bind<IShowRepository>().To<ShowRepository>();
kernel.Bind<ITicketRepository>().To<TicketRepository>();
kernel.Bind<IMovieOverviewRepository>().To<MovieOverviewRepository>();
}
}
}
I have Google authentication working in my app through OAuthWebSecurity. Every time I login, Google re-prompts for permissions. How can I prevent Google from re-prompting every time?
I am currently using a custom OpenIdClient to get extra data from Google (source), but this also happens with the default client.
internal static class AuthConfig
{
public static void RegisterOpenAuth(ConfigurationWrapper configuration)
{
//OAuthWebSecurity.RegisterGoogleClient(); // using this has the exact same problem as my custom code
OAuthWebSecurity.RegisterClient(new GoogleCustomClient(), "Google", null);
}
}
/// <summary>
/// Represents Google OpenID client.
/// </summary>
public class GoogleCustomClient : OpenIdClient
{
#region Constructors and Destructors
public GoogleCustomClient()
: base("google", WellKnownProviders.Google)
{
}
#endregion
#region Methods
/// <summary>
/// Gets the extra data obtained from the response message when authentication is successful.
/// </summary>
/// <param name="response">
/// The response message.
/// </param>
/// <returns>A dictionary of profile data; or null if no data is available.</returns>
protected override Dictionary<string, string> GetExtraData(IAuthenticationResponse response)
{
var fetchResponse = response.GetExtension<FetchResponse>();
if (fetchResponse == null) return null;
var extraData = new Dictionary<string, string>
{
{"email", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.Email)},
{"country", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.HomeAddress.Country)},
{"firstName", fetchResponse.GetAttributeValue(WellKnownAttributes.Name.First)},
{"lastName", fetchResponse.GetAttributeValue(WellKnownAttributes.Name.Last)}
};
return extraData;
}
/// <summary>
/// Called just before the authentication request is sent to service provider.
/// </summary>
/// <param name="request">
/// The request.
/// </param>
protected override void OnBeforeSendingAuthenticationRequest(IAuthenticationRequest request)
{
// Attribute Exchange extensions
var fetchRequest = new FetchRequest();
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Contact.Email);
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Contact.HomeAddress.Country);
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Name.First);
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Name.Last);
request.AddExtension(fetchRequest);
}
#endregion
}
I am using the newest version of ASP.NET Identity, using the sample project as a base template.
My changes are simple: Adding a FIRM Properyt to the application user.
Thus, the application User looks like this:
public class ApplicationUser : IdentityUser
{
/// <summary>
/// Gets or sets the firm.
/// </summary>
/// <value>
/// The firm.
/// </value>
public virtual Firm Firm { get; set; }
/// <summary>
/// Generates the user identity asynchronous.
/// </summary>
/// <param name="manager">The manager.</param>
/// <returns>A claims identity</returns>
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
//// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
//// Add custom user claims here
return userIdentity;
}
}
Also, I do have a Unit Of Work implented, which is responsible for Firm and other entities.
/// <summary>
/// This contains a Unit of Work pattern Implementation. Provides access to all Elements used in this Application.
/// </summary>
public class UnitOfWork : IDisposable, IUnitOfWork
{
/// <summary>
/// The database context
/// </summary>
private PriorityDBContext dbContext = new PriorityDBContext();
public UnitOfWork(ApplicationDbContext dbContext)
{
this.dbContext = (PriorityDBContext)ApplicationDbContext;
}
private GenericRepository<Firm> firmRepository;
public IGenericRepository<Firm> FirmRepository
{
get
{
if (this.firmRepository == null)
{
this.firmRepository = new GenericRepository<Firm>(this.dbContext);
}
return this.firmRepository;
}
}
}
Now to my problem: I have an Account Controller, which can create new Users (among other things). When a new User is created, the Firm is silently doubled. E.g. I had a Firm called "Example1" in the database before. Now I create a new User and suddenly the Database contains "Example1" two times.
As far I can tell, the root cause is that Asp.net Identity uses one DbContext, my UnitOfWork another. I am unsure why, I tried to set up Ninject in a way that the same DbContext is used in all parts. But it simply have enormous problems getting the same db Context into the UserManager and the unit of work :(
[Authorize]
public class AccountController : Controller
{
/// <summary>
/// The Unit of Work
/// </summary>
private IUnitOfWork uoW;
/// <summary>
/// The _user manager
/// </summary>
private ApplicationUserManager userManager;
public AccountController(IUnitOfWork uow)
{
this.uoW = uow;
}
/// <summary>
/// Gets the user manager.
/// </summary>
/// <value>
/// The user manager.
/// </value>
public ApplicationUserManager UserManager
{
get
{
if (this.userManager == null)
{
this.userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
return this.userManager;
}
private set
{
this.userManager = value;
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
bool success = true;
if (ModelState.IsValid)
{
var firm = this.uoW.FirmRepository.GetRaw().Where(f => f.FirmName == newUser.Firm).First();
var user = new ApplicationUser { FirstName = newUser.FirstName, LastName = newUser.LastName, Email = newUser.Email, UserName = newUser.Email, PreferredLanguage = newUser.Language, Firm = firm };
var password = Guid.NewGuid().ToString();
var result = await this.UserManager.CreateAsync(user, password);
if (result.Succeeded)
{
this.logger.Info("Created user for {0} successfully", newUser.Email);
}
}
}
}
}
}
Ninject, registering the Bindings:
private static void RegisterServices(IKernel kernel)
{
/// loading the ApplicationDbContext here because the UserManager uses it from the OwinContext and if the
/// Unit of Work defines it's own DBContext, bad things happen, e.g. duplicated objects when working with users AND our own pocos here.
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().WithConstructorArgument("dbContext", ninjectContext => HttpContext.Current.GetOwinContext().Get<ApplicationDbContext>());
kernel.Bind<IGenericRepository<Firm>>().To<GenericRepository<Firm>>();
//kernel.Bind<ApplicationUserManager>().To(HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>());
}
The ApplicationUserManager:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
//// Konfigurieren der Überprüfungslogik für Benutzernamen.
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// snipped
return manager;
}
}
Several of our internal apps are MVC3 and all use Ninject.MVC.
We're running into an issue that affects all the tools at one point. First we get the error:
Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.
Followed by:
Execution of the command requires an open and available connection. The connection's current state is broken.
This can happen at any time when the tool is used. We've updated our ninjects to the latest versions and it helped a LOT, errors have been much more seldom but still happen when the tools are heavily used. I've been simply setting up Ninject.MVC3 via the nuget package manager and registering the proper services to the NinjectWebCommon.cs.
Here's our our controllers, NinjectWebCommon and global.asax are setup, is there something we're doing wrong here?
One we we know for sure will fix this is to simply get rid of Ninject altogether and instantiate our repositories on each controller. But that's not a good solution I'm guessing.
Global.asax (removed some routes):
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Index", // Route name
"", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
NinjectWebCommon.cs:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IToolRepository>().To<ToolRepository>();
}
}
HomeController:
public class HomeController : Controller
{
private IBattleStationRepository _repository;
private LoginEntities _loginEntities;
private SpecialLib _speclib;
private AccessManager _accessManager;
public HomeController(IBattleStationRepository repository)
{
_repository = repository;
_speclib = new SpecialLib();
_loginEntities = new LoginEntities();
_accessManager = new AccessManager();
}
public virtual ActionResult Index()
{
var byPassHomePage = false;
var urlReferrer = HttpContext.Request.UrlReferrer;
var user = _accessManager.GetUserByUserName(User.Identity.Name);
if (urlReferrer == null)
{
byPassHomePage = true;
}
if (user.TeamId != null && byPassHomePage == true)
{
return RedirectToAction("Release", "Release", new { shortTeamName = user.Team.ShortName });
}
return View();
}
}