Есть проект WebForms (legacy) + ASP.NET MVC + SimpleInjector
public abstract class CustomBaseController : Controller
{
protected User user;
protected IAppDbContext repo;
public CustomBaseController(User user, IAppDbContext repo)
{
this.user = user;
this.repo = repo;
}
}
// my controller
[MyCustomAuthorize]
public class MyCustomController : CustomBaseController
{
public MyCustomController(User user, IAppDbContext repo) : base(user, repo)
{
}
[HttpPost]
public ActionResult PostMethod()
{
try
{
// Какое-то обращение к полю user
// Получаю NullReferenceException
user.Name = "NewUserName";
}
catch (Exception ex)
{
// логирование
}
}
}
// user entity
public class User
{
public Guid Id { get; protected set; }
public string Email { get; protected set; }
public string DisplayName { get; protected set; }
public string FirstName { get; protected set; }
public string LastName { get; protected set; }
// and other properties
}
// Инициализация DI
private static void InitializeContainer()
{
var container = new Container();
container.Register<IUserSessionManagement, UserSessionManagement >(Lifestyle.Scoped);
container.Register<User>(() => container.GetInstance<UserSessionManagement>().UserSession, Lifestyle.Scoped);
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
// Wrapper for User
public class UserSessionManagement : IUserSessionManagement
{
public User UserSession { get; }
public UserSessionManagement(IAppDbContext repo)
{
UserSession = (HttpContext.Current.Session[SESSION_AUTHENTICATED_USER] as User) ?? new User(Guid.Empty, null, null);
}
}
user и везде только запрашиваю, а пишут только 1 раз в конструкторе CustomBaseController. 1) Пробовал подождать пока сессия экспарируется.
2) Пробовал залогиниться. Открыть еще одну вкладку в браузере. Выйти из первой. Сделать запрос со второй (ничего).
3) Сымитировать долгий запрос через thread sleep (но это фигня по-моему)
NOTE: Спрашивал на англоязычном SO, но мой английский слаб и у меня не получилось с первого раза объяснить проблему, когда к ней еще был интерес.
UPD:
Текст ошибки получается таким, где UserID пустой, потому что там через null propagation сделано. Соответственно user был null.
An exception occured. Error id: c90dfe71-c608-4412-9805-c1cb9bf92bc6. UserID:;
Полное содержание вызываемого метода.
[HttpPost]
public ActionResult PostMethod()
{
try
{
var provider = repo.GetProviderInfo(user.Id);
return Json(provider);
}
catch (Exception ex)
{
var internalErrorId = Guid.NewGuid();
MSSQLLogger.Instance.GetLogger(MethodBase.GetCurrentMethod())
.Error($"An exception occured. Error id: {internalErrorId}. UserID:{user?.Id};", ex);
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError, $"Error id: {internalErrorId}");
}
}
В общем, что бы я посоветовал:
// Инициализация DI
private static void InitializeContainer()
{
var container = new Container();
container.Register<IUserSessionManagement, UserSessionManagement>(Lifestyle.Scoped);
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
Базовый класс
public abstract class CustomBaseController : Controller
{
protected IUserSessionManagement SessionManagement;
protected IAppDbContext repo;
public CustomBaseController(IUserSessionManagement sessionManagement, IAppDbContext repo)
{
this.SessionManagement = sessionManagement;
this.repo = repo;
}
}
Котроллер
// my controller
[MyCustomAuthorize]
public class MyCustomController : CustomBaseController
{
public MyCustomController(IUserSessionManagement sessionManagement, IAppDbContext repo) : base(sessionManagement, repo)
{
}
[HttpPost]
public ActionResult PostMethod()
{
try
{
var user = SessionManagement.UserSession;
// Какое-то обращение к полю user
// Получаю NullReferenceException
user.Name = "NewUserName";
}
catch (Exception ex)
{
// логирование
}
}
}
Проблема оказалась в следующем: так как все хранилось в сессии и после перезагрузки IIS (или обновления web.config) там ничего не лежит.
В сессию информация о юзере попадает после того как происходит обращение к любой странице написанной на WebForm, то бишь отрабатывает логика Admin.Master, но т.к. присутствует лапша из разных технологий, то при прямом обращении через ajax запрос логика из Admin.Master не отрабатывала. Проще говоря забыли добавить это в кастомные атрибуты авторизации.
Продвижение своими сайтами как стратегия роста и независимости