わかりました、私の前の質問/設定には変数が多すぎたので、これを必要最小限のコンポーネントに落としています。
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;
}
}
これはウォッチ ウィンドウでどのように可能ですか?
2.x から StructureMap 3.x を使用するようにアップグレードする Web アプリケーションがありますが、特定の依存関係で奇妙な動作が発生します。
ユーザーがページを要求したときにいくつかのことを確認するために使用する 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
が入力される前に発生するように見えるため、null です。
後でISecurityService
、現在のユーザーがサイトの利用規約の現在のバージョンに同意したかどうかを を介してチェックする ActionFilter があります。同意していない場合は、最初に同意するページにリダイレクトされます。
これはすべて、structuremap 2.x では問題なく機能しました。StructureMap3 への移行のために、Nuget パッケージ StructureMap.MVC5 をインストールして、作業を高速化しました。
使用条件を確認するためにコードが ActionFilter の行に到達すると、これがあります。
var securityService = DependencyResolver.Current.GetService<ISecurityService>();
agreed = securityService.CheckLoginAgreedToTermsOfUse();
の中でCheckLoginAgreedToTermsOfUse()
、私のインスタンスCurrentUser
はnullです。成功したとしても、 getCurrentUser() 内の私のブレークポイントはヒットしていないようです。今回は解決されていたとしても、前回は null だったので、それは当然の結論であるかのようです。
getCurrentUser()
のリクエストで が呼び出されない理由について、ちょっと困惑していISecurityService
ます。.LifecycleIs<UniquePerRequestLifecycle>()
フックアップにa を明示的に貼り付けてみましたが、ICurrentUser
効果はありませんでした。
更新: わかりましたので、頭を上げて、以下で受け入れられている方法を使い始めました。これまでのところうまくいきましたが、コアの問題は解決しませんでした. StructureMap.MVC5
に基づいて、新しいStructureMap3
が NestedContainers を使用することが判明しました。デフォルトが Transient であるかどうかに関係なく、NestedContainer の有効期間にリクエストのスコープを設定します。したがってHttpContextBase
、最初にリクエストしたとき、残りのリクエストに対して同じインスタンスが返されます(リクエストの存続期間の後半でコンテキストが変更されたとしても、NestedContainerを使用しない必要があります(私が理解しているように) ASP.NET vNext を複雑にするか、明示的にライフサイクルを設定します。For<>().Use<>()
リクエストごとに新しいインスタンスを提供するマッピング。NestedContainer ごとのこのスコープ設定は、MVC と同様にコントローラーで問題を引き起こすことに注意してください。StructureMap.MVC5
パッケージはこれを で処理しますが、ビューControllerConvention
は処理しません。また、再帰ビューまたは複数回使用されるビューも同様に問題を引き起こす可能性があります。ビューの問題の恒久的な修正をまだ探しています。今のところ、に戻しましたDefaultContainer
。