Question

J'ai un service WCF qui est à l'aide d'un custom UsernamePasswordValidator.Le validateur doit avoir accès à mon entity framework contexte.

Je voudrais créer un ObjectContext pour l'ensemble de l'appel de service et de les détruire/le disposer à la fin de l'appel.J'ai donc créé un singleton classe statique qui fourni cette fonctionnalité, cependant, ce qui se passe maintenant, c'est que si deux appels de service se produire simultanément, l'un des appels dispose le singleton.

Je l'ai garder une référence locale à la ObjectContext, auquel cas le deuxième service, il le considère comme éliminés et la lance et de l'erreur, ou, j'ai mis un wrapper autour de la propriété de la classe Singleton partout où j'en ai besoin et puis toutes mes modifications sont jetés parce que je suis une nouvelle instance de l'objet, si un autre appel a statué sur elle.

Donc en gros ma question est comment puis-je instancier un ObjectContext par appel de service?

NOTE:L'instance doit être accessible à la fois le code de service ET de la coutume UsernamePasswordValidator code.

Je ne peux pas le faire dans le constructeur ou l'utilisation d'une instruction d'utilisation car alors l' personnalisé UsernamePasswordValidator n'y ont pas accès.Est-il possible d'avoir une classe statique par appel?Il ne sembler impossible, mais ce qui est le moyen de contourner cela?Dois-je être mise en cache de l'objet dans une session?

Mon service est hébergé dans IIS.

Mise à JOUR:
J'ai donc cloué ce vers le bas pour le stockage de l'etat dans le InstanceContext à l'aide d'un IExtension objet.Mais Comment puis-je accéder à la InstanceContext dans un UsernamePasswordValidator?

Était-ce utile?

La solution

OK, alors à la fin, je l'ai résolu en utilisant la classe statique suivante et en s'appuyant sur ASP.NET pour mettre en cache le contexte pour moi.

Je ne sais pas si c'est la meilleure façon de faire des choses, mais cela me permet d'utiliser un objetContext par demande, donc je ne fais pas trop de choses et cela signifie aussi que je n'ai pas besoin d'utiliser une serruresur l'objet qui deviendrait un cauchemar si de nombreux utilisateurs utilisaient le service.

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;
            }
        }    
    }

Alors partout où j'ai besoin d'un objetContext dans l'application, je viens d'appeler

var context = MyContextProvider.Context;

Autres conseils

Vous en avez un exemple pour chaque appel, vous avez également 1 appel par exemple.

Donc, il devrait être très simple, utilisez une using () { } bloquer dans le niveau supérieur de votre OperationContract méthode.

OK, voici la classe avec une méthode statique de fil-sécurité qui fournit un objet de modèle d'entité d'objet ObjectContext pour tout appel de service de WCF et le disposer automatiquement à la fin de l'appel:

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];
        }
    }

Pour votre service, vous pouvez spécifier un comportement de service qui détaille le mode d'instance du service:

[ServiceBehaviour(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService {
    ObjectContext context;
}

D'une façon plus propre peut-être d'utiliser le ServiceAuthenticationManager, qui est dans .NET 4.

http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceauthenticationmanager.aspx

À partir de la Authenticate méthode (que vous pourrez remplacer) vous pouvez accéder à l'objet du Message et de définir des propriétés sur elle.Je ne l'ai pas utilisé en colère, donc, YMMV :)

MODIFIER le problème avec cette approche est que vous n'avez pas de nom d'utilisateur et Mot de passe, il aura encore besoin de l'Authentification personnalisée.

Jetez un oeil à la UsernameSecurityTokenAuthenticator...http://msdn.microsoft.com/en-us/library/system.identitymodel.selectors.usernamesecuritytokenauthenticator(v=vs. 90).aspx


Plus de la lecture de mes recherches:

Les réponses à cette question donne quelques conseils sur la façon de l'utiliser:

WCF personnalisés authentification avec le Système.ServiceModel.ServiceAuthenticationManager?

Si vous pouvez lire (ou ignorer) le russe, j'ai trouvé les conseils utiles à:

http://www.sql.ru/forum/actualthread.aspx?tid=799046

Cette plutôt bonne CodeProject l'article va plus loin (de cryptage et de compression ainsi que la coutume de l'autorisation)

http://www.codeproject.com/Articles/165844/WCF-Client-Server-Application-with-Custom-Authenti

Pourquoi ne pas passer dans le contexte dans votre CustomValidator lorsque vous affectez-le au service - Stockez votre contexte d'objet dans votre validateur et dans la méthode de validation remplacée NOUVEAU IL SI BESOIN.Ensuite, vous avez toujours accès à l'objet à travers les services CotomusernameValidator.

Selon ce que vous demandez: Créez votre objet ObjectContext séparé comme objet dynamique - ajoutez-le comme une propriété sur CustomValidator. Dans votre validateur personnalisé - vous pouvez maintenant vérifier si l'objet est disposé et crée l'objet à nouveau si besoin d'être. Sinon, si ce n'est pas ce que vous êtes après - stockez simplement le contexte dans le validateur - vous avez toujours accès au côté serveur. Le code ici est juste une idée généralisée - je viens de l'afficher comme un cadre de référence afin de pouvoir avoir une idée de ce dont je parle.

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");
                }
       }
   }
} 

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top