Доступ к текущему InstanceContext в WCF - PullRequest
3 голосов
/ 23 июля 2010

У меня есть служба WCF, использующая пользовательский UsernamePasswordValidator.Валидатору необходим доступ к контексту моей сущности.

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

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

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

ПРИМЕЧАНИЕ. Экземпляр должен быть доступен как всервисный код И пользовательский код UsernamePasswordValidator.

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

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

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

Ответы [ 6 ]

2 голосов
/ 23 июля 2010

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

Я не уверен, что это лучший способ сделать что-то, но это позволяет мне использовать один 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 голос
/ 03 августа 2013

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

1 голос
/ 23 июля 2010

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

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

0 голосов
/ 17 ноября 2015

Почему бы не передать контекст в свой CustomValidator при назначении службе - сохраните свой объектный контекст в своем валидаторе, а в переопределенном методе валидации измените его, если необходимо. Тогда у вас все еще есть доступ к объекту через Сервисы CutomUserNameValidator ..

В зависимости от того, что вы спрашиваете: Создайте свой отдельный класс ObjectContext как динамический объект - добавьте его в качестве свойства в CustomValidator. В вашем собственном 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");
                }
       }
   }
} 
0 голосов
/ 12 декабря 2012

Более чистым способом может быть использование ServiceAuthenticationManager, который находится в .NET 4.

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

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

РЕДАКТИРОВАТЬ Проблема с этим подходом заключается в том, что у вас нет имени пользователя и пароля, поэтому все равно потребуется пользовательская аутентификация.

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


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

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

Пользовательская аутентификация WCF с System.ServiceModel.ServiceAuthenticationManager?

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

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

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

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

0 голосов
/ 23 июля 2010

Для вашего сервиса вы можете указать поведение сервиса, которое подробно описывает режим экземпляра сервиса:

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