Получите доступ к текущему экземпляру Context в WCF UserNamePasswordValidator

StackOverflow https://stackoverflow.com/questions/3317000

  •  27-09-2020
  •  | 
  •  

Вопрос

У меня есть служба WCF, которая использует пользовательский UserNamePasswordValidator.Валидатору необходимо получить доступ к контексту моей entity framework.

Я хотел бы создать один ObjectContext для всего вызова службы, а затем уничтожить / утилизировать его в конце вызова.Итак, я создал статический класс singleton, который предоставлял эту функциональность, однако сейчас происходит то, что если два вызова службы происходят одновременно, один из вызовов удаляет синглтон.

Я либо сохраняю локальную ссылку на ObjectContext, и в этом случае вторая служба, использующая его, видит его как удаленный и выдает ошибку, либо я помещаю свойство-оболочку вокруг класса Singleton везде, где мне это нужно, и тогда все мои изменения отбрасываются, потому что я получаю новый экземпляр класса Singleton. объект, если другой вызов удалил его.

Итак, в основном мой вопрос заключается в том, как мне создать экземпляр ObjectContext для каждого вызова службы?

записка:Экземпляр должен быть доступен как в служебном коде, так и в пользовательском коде UserNamePasswordValidator.

Я не могу просто сделать это в конструкторе или использовать оператор using, потому что тогда пользовательский UserNamePasswordValidator не имеет к нему доступа.Есть ли способ создать статический класс для каждого вызова?Это действительно звучит невозможно, но как это можно обойти?Должен ли я кэшировать объект в сеансе?

Мой сервис размещен в IIS.

ОБНОВЛЕНИЕ:
Итак, я свел это к сохранению состояния в InstanceContext, используя объект IExtension.Но как мне получить доступ к текущему InstanceContext в UserNamePasswordValidator?

Это было полезно?

Решение

ОК, поэтому в конце я решил его, используя следующий статический класс и полагаясь на ASP.NET, чтобы кэшировать контекст для меня.

Я не уверен, что это лучший способ сделать вещи, но это позволяет мне использовать один объектContext на запрос, поэтому я не спирал слишком много, и это также означает, что мне не нужно использовать замокНа объекте, который стал бы кошмаром, если многие пользователи использовали сервис.

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

Тогда везде, где мне нужен объектContext в приложении, я просто звоню

var context = MyContextProvider.Context;
.

Другие советы

У вас есть один экземпляр на вызов, у вас также есть 1 вызов на экземпляр.

Таким образом, это должно быть очень просто, используйте using () { } заблокируйте на верхнем уровне вашего метода OperationContract.

OK, вот класс с безопасным статическим методом, который предоставляет один объект модели объекта ObjectContext для любого вызова службы WCF и автоматически располагается его в конце вызова:

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.

http://msdn.microsoft.com/ru -US / Library / System.ServiceModel.serviceauthenticationmanager.aspx

от метода Authenticate (который вы переопределите), вы можете получить доступ к объекту сообщения и установить его на свойствах. Я не использовал это в гневе, так что YMMV :)

Отредактируйте проблему с таким подходом - это то, что у вас нет имени пользователя и пароля, поэтому все равно понадобится пользовательская аутентификация.

Посмотрите на usernamesecurityTokenauthenticator ... http:// msdn .microsoft.com / en-us / library / system.identitymodel.selectors.usernamesecurityTokenauthenticator (v= vs.90) .aspx


Дальнейшее чтение из моих исследований:

Ответы на этот вопрос дает некоторые намеки о том, как его использовать:

Пользовательская аутентификация WCF с System.servicemodel.ServiceAuthenticanmanager? / P >.

Если вы можете прочитать (или игнорировать) русский, я нашел полезные советы по адресу:

http://www.sql.ru/forum/actualThread.aspx ? TID= 799046

Это довольно хорошая артикул CodeProject идет дальше (шифрование и сжатие, а также пользовательское разрешение)

http://www.codeProject .com / starles / 165844 / wcf-client-server-application-с-custom-atugeti

Почему бы не пройти в контексте в ваш substlevalidator, когда вы назначаете на сервис - сохраните свой объект контекста в валидатере, а в разделе «Переопределенный метод проверки», если это необходимо.Тогда у вас все еще есть доступ к объекту через службы CutomusernameValidator ..

В зависимости от того, что вы спрашиваете: Создайте свой отдельный класс ObjectContext в качестве динамического объекта - добавьте это в качестве свойства для вас AuStryValidator. В вашем пользовательском валидатере - теперь вы можете проверить, будет ли объект расположен и снова создать объект, если это необходимо. В противном случае, если это не то, что вы после того, как вы, просто храните контекст в Validator - у вас все еще есть доступ на стороне сервера. Кодекс здесь просто обобщенная идея - я просто размещаю его как кадр отсчета, чтобы вы могли иметь представление о том, о чем я говорю.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top