現在のInstanceContextにWCF UserNamePasswordValidatorにアクセスします
-
27-09-2020 - |
質問
カスタムUserNamePasswordValidatorを使用しているWCFサービスを持っています。バリデータは私のエンティティフレームワークコンテキストにアクセスする必要があります。
サービスコール全体のために1つのObjectContextを作成し、それからそれを呼び出し終了時にそれを破棄/処分したいと思います。だから私はこの機能を提供したシングルトン静的クラスを作成しましたが、今何が起こっているのは、2つのサービス呼び出しが同時に起こるならば、呼び出しの1つがシングルトンを処分します。
ObjectContextをローカル参照しておくと、2番目のサービスが廃棄され、スローしてエラーが表示されていること、または、必要な場所に、シングルトンクラスの周囲にラッパープロパティを入れてから、他の呼び出しがそれを廃棄した場合、オブジェクトの新しいインスタンスを取得しているため、変更が遅くなります。
基本的に私の質問は、サービス通話ごとにObjectContextをインスタンス化する方法ですか?
注:インスタンスは、サービスコードとカスタムusernamePasswordValidatorコードの両方でアクセシブルする必要があります。
コンストラクターでは、または使用文を使用することも、カスタムUserNamePasswordValidatorはにアクセスできません。電話ごとに静的クラスを持つ方法はありますか?それは不可能だが、これを回避する方法は何ですか?セッションでオブジェクトをキャッシュする必要がありますか?
私のサービスはIISでホストされています。
更新:
だから私はISTANCESCONTEXTの状態を保存するためにこれを釘付けにしました。しかし、UserNamePasswordValidatorの現在のInstanceContextにアクセスする方法は?
解決
OK、そのため、次の静的クラスを使用して、私のコンテキストをキャッシュするためにASP.NETに頼ってそれを解決しました。
これが物事をやるための最良の方法であるかどうかわからないが、これは要求ごとに1つのObjectContextを使うことができ、私はあまりにも多くを回転させていないので、私はロックを使う必要がないという意味でもあります多くのユーザーがサービスを使用していた場合、悪夢になるオブジェクトに。
public static class MyContextProvider
{
public static MyModel Context
{
get
{
if (HttpContext.Current.Items["context"].IsNull())
{
HttpContext.Current.Items["context"] = new MyModel();
}
return HttpContext.Current.Items["context"] as MyModel;
}
}
}
.
それでは私がアプリでObjectContextが必要なのところならどこでも私はちょうど
を呼び出すだけですvar context = MyContextProvider.Context;
. 他のヒント
呼び出しごとに1つのインスタンスがあり、インスタンスごとに1回のコールがあります。
だからそれは非常に簡単であるべきです、あなたのOperationContractionメソッドのトップベルでusing () { }
ブロックを使用してください。
OK、ここでは、任意のWCFサービス呼び出しに対して単一のObjectContextエンティティモデルオブジェクトを提供し、呼び出しの最後にそれを自動的に配置するスレッドセーフスタティックメソッドを備えたクラスです。
public static class EntityModelProvider
{
private static readonly Dictionary<OperationContext, MyEntityModel> _entityModels = new Dictionary<OperationContext, MyEntityModel>();
public static MyEntityModel GetEntityModel()
{
if (OperationContext.Current == null)
throw new Exception("OperationContext is missing");
lock (_entityModels)
{
if (!_entityModels.ContainsKey(OperationContext.Current))
{
_entityModels[OperationContext.Current] = new MyEntityModel();
OperationContext.Current.OperationCompleted += delegate
{
lock (_entityModels)
{
_entityModels[OperationContext.Current].Dispose();
_entityModels.Remove(OperationContext.Current);
}
};
}
return _entityModels[OperationContext.Current];
}
}
. あなたのサービスの場合は、サービスのインスタンスモードを詳細に指定するサービス動作を指定できます。
[ServiceBehaviour(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService {
ObjectContext context;
}
. よりきれいな方法は、.NET 4.
にあるServiceAuthenticationManagerを使用することです。http://msdn.microsoft.com/jp -US / Library / System.ServiceModel.ServeAuthEntericationManager.aspx
Authenticate
メソッド(上書きする)から、メッセージオブジェクトにアクセスしてプロパティを設定できます。私は怒りでそれを使わないので、ymmv :)
問題を編集この方法では、ユーザー名とパスワードがないので、まだカスタム認証が必要です。
UserNameseCurityTokenAuthenticatorを見てください... http:// msdn. .microsoft.com / en-us / library / system.identityModel.Selectors.UsernameseCurityTokenAuthenticator(V= vs.90).aspx
私の研究からのさらなる読書:
この質問に対する回答を使う方法についてのヒントを与えます:
System.ServiceModel.ServiceAuthenticationManager? < / P>
ロシア語を読むことができる(または無視する)場合は、
で便利なヒントを見つけましたhref="http://www.sql.ru/forum/actualthread.aspx?tid=799046" REL="AnFollowNoreferrer"> http://www.sql.ru/forum/actualthread.aspx. ?TID= 799046
このむしろ大変なCodeProjectの記事はさらに進んでいます(暗号化と圧縮、およびカスタム承認)
http://www.codeproject .com /記事/ 165844 / WCF-Client-Server-application-with-custom-authenti
サービスに割り当てるときに、CustomValidatorにコンテキストを渡しないのは、オブジェクトコンテキストをバリデータに保存し、必要に応じてオーバーライドされた検証メソッドでは、新しい検証メソッドで新しいものを保存します。それでは、SutomUserNameValidatorを通じてオブジェクトにアクセスできます..
あなたが尋ねているものに応じて: 別々のObjectContextクラスを動的オブジェクトとして作成します - CustomValidatorにプロパティとして追加します。 カスタムバリデータで - 必要に応じてオブジェクトが配置されているかどうかを確認できるようになりました。 それ以外の場合、これがあなたが後にあるものである場合 - バリデータにコンテキストを格納するだけです - それでもサーバー側でアクセスできます。 ここのコードは単なる一般化されたアイデアです - 私はそれを参照の枠として投稿するだけで、あなたが私が話していることのアイデアを持つことができます。
public DynamicObjectContextObjectClass
{
ObjectContext internalObjectContext;
}
public class ServiceUserNamePasswordValidator : UserNamePasswordValidator
{
public DynamicObjectContextObjectClass dynamiccontext;
public override void Validate(string userName, string password)
{
if(dynamiccontext.internalObjectContext.isdisposed)
{
dynamiccontext.internalObjectContext = new Context;
}
try
{
if (string.IsNullOrEmpty(userName) || password == null)
{
//throw new ArgumentNullException();
throw new FaultException("Username cannot be null or empty; Password cannot be null and should not be empty");
}
}
}
}
.