Ошибка «Объект доступен только для чтения» при установке ClientCredentials в WCF - PullRequest
18 голосов
/ 14 октября 2008

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

InstanceContext context = new InstanceContext(this);

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

Как только код попадает в строку UserName, происходит сбой с ошибкой «Объект доступен только для чтения». Я знаю, что это может произойти, если соединение уже открыто или повреждено, но на данный момент я еще не вызвал context.Open ().

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

Есть идеи?

Ответы [ 11 ]

12 голосов
/ 03 ноября 2012

Я заметил, что после создания экземпляра прокси-класса для службы, я могу один раз без ошибок установить имя пользователя и пароль и выполнить успешный вызов моего веб-сервиса. Затем, когда я снова пытаюсь установить имя пользователя и пароль для существующего экземпляра (разумеется, ненужного), я получаю ошибку «Объект доступен только для чтения», о которой вы упоминали. Установка значений один раз за время жизни экземпляра работала для меня.

8 голосов
/ 14 октября 2008

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

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

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

4 голосов
/ 29 июня 2009

вот решение:

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);
1 голос
/ 11 октября 2018

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

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

    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";
    }
1 голос
/ 04 апреля 2018

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

1 голос
/ 24 октября 2013

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

// 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

У меня это сработало.

1 голос
/ 29 апреля 2009

У меня есть похожий код, который передает UserName отлично:

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

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

0 голосов
/ 03 февраля 2015

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

вот решение,

ProductClient Manager = new  ProductClient();    
Manager.ClientCredentials.UserName.UserName = txtUserName.Text;
Manager.ClientCredentials.UserName.Password = txtPassword.Text;
0 голосов
/ 12 апреля 2010

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

0 голосов
/ 31 декабря 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...