Получение ошибки "Object is read only" при установке ClientCredentials в WCF - программирование
Подтвердить что ты не робот

Получение ошибки "Object is read only" при установке ClientCredentials в WCF

У меня есть прокси-объект, созданный Visual Studio (клиентской стороной) с именем ServerClient. Я пытаюсь установить ClientCredentials.UserName.UserName/Password, прежде чем открывать новое соединение с помощью этого кода:

InstanceContext context = new InstanceContext(this);

m_client = new ServerClient(context);
m_client.ClientCredentials.UserName.UserName = "Sample";

Как только код попадает в строку UserName, он терпит неудачу с ошибкой "Object is only-only". Я знаю, что это может произойти, если соединение уже открыто или повреждено, но на данный момент я еще не вызвал context.Open().

Я настроил Bindings (который использует netTcpBinding) для использования Message в качестве режима безопасности, а MessageClientCredentialType - в UserName.

Любые идеи?

4b9b3361

Ответ 1

Похоже, вы можете получить доступ к этим свойствам довольно рано в цикле instanciation. Если я переопределяю конструктор в прокси-классе (ServerClient), я могу установить эти свойства:

base.ClientCredentials.UserName.UserName = "Sample";

Я начинаю ценить людей, которые предлагают не использовать автоматически созданные прокси, предоставленные VS.

Ответ 2

Я заметил, что после создания экземпляра класса proxy для службы я могу установить имя пользователя и пароль один раз без ошибок и сделать успешный вызов в моем веб-сервисе. Когда я затем попытаюсь снова установить имя пользователя и пароль на существующий экземпляр (ненужно, конечно), я получаю сообщение об ошибке "Object is Read-Only". Установка значений один раз на один экземпляр жизни работала для меня.

Ответ 3

вот решение:

using SysSvcmod = System.ServiceModel.Description;

SysSvcmod.ClientCredentials clientCredentials = new SysSvcmod.ClientCredentials();
clientCredentials.UserName.UserName = "user_name";
clientCredentials.UserName.Password = "pass_word";

m_client.ChannelFactory.Endpoint.Behaviors.RemoveAt(1);
m_client.ChannelFactory.Endpoint.Behaviors.Add(clientCredentials);

Ответ 4

У меня есть аналогичный код, передающий UserName fine:

  FooServiceClient client = new FooServiceClient("BasicHttpBinding_IFooService");
  client.ClientCredentials.UserName.UserName = "user";
  client.ClientCredentials.UserName.Password = "password";

Попробуйте создать прокси с именем привязки в app.config.

Ответ 5

Этого не произойдет, если ссылка на службу будет добавлена через → Добавить ссылку на службу → Advanced-> Добавить Web Reference-> Url/wsdl (файл локального диска).

Ответ 6

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

Вот как я этого добился.

    public static T CreateClient<T>(string url) where T : class
    {
        EndpointAddress endPoint = new EndpointAddress(url);
        CustomBinding binding = CreateCustomBinding();

        T client = (T)Activator.CreateInstance(typeof(T), new object[] { binding, endPoint });
        SetClientCredentials(client);

        return client;
    }

    public static void SetClientCredentials(dynamic obj)
    {
        obj.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
        obj.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials());

        obj.ClientCredentials.UserName.UserName = "UserId";
        obj.ClientCredentials.UserName.Password = "Password";
    }

Ответ 7

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

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

Что заставляет использовать InstanceContext?

Ответ 8

При использовании двустороннего клиента при его создании DuplexChannelFactory в DuplexClientBase, из которого происходит ваш клиент, инициализируется существующими учетными данными, поэтому он может открыть канал обратного вызова, поэтому учетные данные будут считаны только.

Я задаю второй вопрос Майку, а также спрошу, почему вы используете NetTcpBinding, если вы не собираетесь использовать встроенную безопасность на уровне транспортного уровня? Возможно, привязка на основе HTTP будет лучше подходит? Это позволит вам использовать защиту на основе сертификатов, которая, как мне кажется, может быть изменена после создания экземпляра (http://msdn.microsoft.com/en-us/library/ms576164.aspx).

Ответ 9

Кадр в темноте, но netTcpBinding позволяет проверять имя пользователя и пароль? Попробуйте использовать защиту уровня приложения (SOAP) с помощью привязки http

Ответ 10

Правильный синтаксис:

// Remove the ClientCredentials behavior.
client.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();

// Add a custom client credentials instance to the behaviors collection.
client.ChannelFactory.Endpoint.Behaviors.Add(new MyClientCredentials());

http://msdn.microsoft.com/en-us/library/ms730868.aspx

Это сработало для меня.

Ответ 11

У меня возникла такая же проблема, мой код начал работать, когда я изменил свой код, то есть присвоил значения учетным данным клиента сразу после инициализации объекта Client.

вот решение,

ProductClient Manager = new  ProductClient();    
Manager.ClientCredentials.UserName.UserName = txtUserName.Text;
Manager.ClientCredentials.UserName.Password = txtPassword.Text;