Нулевой пользователь на HttpContext, полученный из StructureMap

Хорошо, в моем предыдущем вопросе / настройке было слишком много переменных, так что я разбираю это до простых компонентов.

Учитывая код ниже, используя StructureMap3 ...

//IoC setup
For<HttpContextBase>().UseSpecial(x => x.ConstructedBy(y => HttpContext.Current != null ? new HttpContextWrapper(HttpContext.Current) : null ));
For<ICurrentUser>().Use<CurrentUser>();

//Classes used
public class CurrentUser : ICurrentUser
{
    public CurrentUser(HttpContextBase httpContext)
    {
        if (httpContext == null) return;
        if (httpContext.User == null) return;
        var user = httpContext.User;
        if (!user.Identity.IsAuthenticated) return;
        UserId = httpContext.User.GetIdentityId().GetValueOrDefault();
        UserName = httpContext.User.Identity.Name;
    }

    public Guid UserId { get; set; }
    public string UserName { get; set; }
}

public static class ClaimsExtensionMethods
    public static Guid? GetIdentityId(this IPrincipal principal)
    {
        //Account for possible nulls
        var claimsPrincipal = principal as ClaimsPrincipal;
        if (claimsPrincipal == null)
            return null;
        var claimsIdentity = claimsPrincipal.Identity as ClaimsIdentity;
        if (claimsIdentity == null)
            return null;
        var claim = claimsIdentity.FindFirst(x => x.Type == ClaimTypes.NameIdentifier);
        if (claim == null)
            return null;

        //Account for possible invalid value since claim values are strings
        Guid? id = null;
        try
        {
            id = Guid.Parse(claim.Value);
        }
        catch (ArgumentNullException) { }
        catch (FormatException) { }
        return id;
    }
}

Как это возможно в окне Watch?

У меня есть веб-приложение, которое я обновляю для использования StructureMap 3.x из 2.x, но у меня странное поведение в зависимости от конкретной зависимости.

У меня есть ISecurityService, который я использую для проверки некоторых вещей, когда пользователь запрашивает страницу. Этот сервис зависит от небольшого интерфейса, который я назвал ICurrentUser. Реализация класса довольно проста, на самом деле это может быть структура.

public interface ICurrentUser
{
    Guid UserId { get; }
    string UserName { get; }
}

Это получается путем внедрения зависимости с использованием приведенного ниже кода.

For<ICurrentUser>().Use(ctx => getCurrentUser(ctx.GetInstance<HttpContextBase>()));
For<HttpContextBase>().Use(() => getHttpContext());

private HttpContextBase getHttpContext()
{
    return new HttpContextWrapper(HttpContext.Current);
}

private ICurrentUser getCurrentUser(HttpContextBase httpContext)
{
    if (httpContext == null) return null;
    if (httpContext.User == null) return null; // <---
    var user = httpContext.User;
    if (!user.Identity.IsAuthenticated) return null;
    var personId = user.GetIdentityId().GetValueOrDefault();
    return new CurrentUser(personId, ClaimsPrincipal.Current.Identity.Name);
}

Когда приходит запрос, сначала происходит проверка подлинности моего сайта, что зависит отISecurityService, Это происходит внутри OWIN и, кажется, происходит раньшеHttpContext.User был заселен, так что это ноль, пусть будет так.

Позже у меня есть ActionFilter, который проверяет, черезISecurityService, если текущий пользователь согласился с текущей версией TermsOfUse для сайта, в противном случае они перенаправляются на страницу, чтобы сначала согласиться с ними.

Все это прекрасно работало в Structuremap 2.x. Для перехода на StructureMap3 я установил пакет Nuget StructureMap.MVC5, чтобы ускорить процесс.

Когда мой код попадает в строку в моем ActionFilter для проверки условий использования, у меня есть это.

var securityService = DependencyResolver.Current.GetService<ISecurityService>();
agreed = securityService.CheckLoginAgreedToTermsOfUse();

ВнутриCheckLoginAgreedToTermsOfUse()мой примерCurrentUser нулевой. Несмотря на то, что это было бы успешно, и моя точка останова внутри getCurrentUser (), похоже, никогда не была достигнута. Это почти так, как если бы это было предрешено, так как в прошлый раз оно было нулевым, хотя на этот раз все решилось бы.

Я немного сбит с толку, почемуgetCurrentUser() никогда не вызывается по запросуISecurityService, Я даже пытался явно придерживаться.LifecycleIs<UniquePerRequestLifecycle>() на моей связи для обработкиICurrentUser без эффекта.

ОБНОВЛЕНИЕ: Хорошо, только наперед, я начал использовать метод, принятый ниже, и, хотя до сих пор он работал отлично, он не решил мою основную проблему. Оказывается, новыйStructureMap.MVC5на основеStructureMap3, использует NestedContainers. Какие области их запросов на время жизни NestedContainer, независимо от того, что по умолчанию Transient. Поэтому, когда я просилHttpContextBase в первый раз он затем вернет тот же экземпляр для остальной части запроса (хотя позже в течение срока службы запроса контекст изменился. Вам нужно либо не использовать NestedContainer (что, как я понимаю, усложнит ситуацию) ASP.NET vNext) или вы явно задаете жизненный циклFor<>().Use<>() отображение, чтобы дать вам новый экземпляр для каждого запроса. Обратите внимание, что эта область видимости для NestedContainer также вызывает проблемы с контроллерами в MVC. В то время какStructureMap.MVC5 пакет обрабатывает это сControllerConvention, он не обрабатывает представления, и рекурсивные представления или представления, используемые несколько раз, могут также вызвать проблемы. Я все еще ищу постоянное решение проблемы с представлениями, на данный момент я вернулся кDefaultContainer.

Ответы на вопрос(1)

Ваш ответ на вопрос