visual-studio 在 WCF 中设置 ClientCredentials 时出现“对象为只读”错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/199014/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 09:46:00  来源:igfitidea点击:

Getting "Object is read only" error when setting ClientCredentials in WCF

visual-studiowcf

提问by Paul Mrozowski

I have a proxy object generated by Visual Studio (client side) named ServerClient. I am attempting to set ClientCredentials.UserName.UserName/Password before opening up a new connection using this code:

我有一个由 Visual Studio(客户端)生成的名为 ServerClient 的代理对象。我试图在使用以下代码打开新连接之前设置 ClientCredentials.UserName.UserName/Password:

InstanceContext context = new InstanceContext(this);

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

As soon as the code hits the UserName line it fails with an "Object is read-only" error. I know this can happen if the connection is already open or faulted, but at this point I haven't called context.Open() yet.

一旦代码到达 UserName 行,它就会失败并显示“对象为只读”错误。我知道如果连接已经打开或出现故障,就会发生这种情况,但此时我还没有调用 context.Open() 。

I have configured the Bindings (which uses netTcpBinding) to use Message as it's security mode, and MessageClientCredentialType is set to UserName.

我已将绑定(使用 netTcpBinding)配置为使用 Message 作为其安全模式,并将 MessageClientCredentialType 设置为 UserName。

Any ideas?

有任何想法吗?

采纳答案by Paul Mrozowski

It appears that you can only access these properties pretty early in the instanciation cycle. If I override the constructor in the proxy class (ServerClient), I'm able to set these properties:

看来您只能在实例化周期的早期访问这些属性。如果我覆盖代理类 (ServerClient) 中的构造函数,我就可以设置这些属性:

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

I'm beginning to appreciate the people who suggest not using the automatically built proxies provided by VS.

我开始感谢那些建议不要使用 VS 提供的自动构建的代理的人。

回答by Gerhard

I noticed that after creating an instance of the proxy class for the service, I can set the Username and Password once without errors and do a successful call to my webservice. When I then try to set the Username and Password again on the existing instance (unnecessary of course) I get the 'Object is Read-Only' error you mentioned. Setting the values once per instance lifetime worked for me.

我注意到在为服务创建代理类的实例后,我可以设置用户名和密码一次而不会出错,并成功调用我的网络服务。然后,当我尝试在现有实例上再次设置用户名和密码时(当然是不必要的),我收到您提到的“对象为只读”错误。每个实例生命周期设置一次值对我有用。

回答by Paul Mrozowski

here is the solution:

这是解决方案:

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

回答by Eugene Yokota

I have similar code that's passing UserNamefine:

我有类似的代码,通过的UserName很好:

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

Try creating the proxy with binding name in app.config.

尝试在 app.config 中使用绑定名称创建代理。

回答by savitha

I was facing same problem, my code started working when I changed my code i.e. assigning values to Client credential immediately after initializing Client object.

我遇到了同样的问题,当我更改代码时,我的代码开始工作,即在初始化 Client 对象后立即将值分配给 Client 凭据。

here is the solution ,

这是解决方案,

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

回答by Blue Clouds

This will not happen if the service reference is added through -> Add service reference ->Advanced->Add Web Reference-> Url/wsdl (local disk file).

如果通过->添加服务引用->高级->添加Web引用-> Url/wsdl(本地磁盘文件)添加服务引用,则不会发生这种情况。

回答by Atul

I was facing this issue where I was trying to create a generic method to create a clients for different end points.

我正面临这个问题,我试图创建一个通用方法来为不同的端点创建客户端。

Here how I achieved this.

在这里,我是如何实现这一目标的。

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

回答by Fabienne Bonzon

The correct syntax is:

正确的语法是:

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

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

It worked for me.

它对我有用。

回答by Kwal

If using a duplex client, when you instantiate it the DuplexChannelFactory within the DuplexClientBase that your client is derived from is initialized with existing credentials so it can open the callback channel, which is why the credentials would be read only.

如果使用双工客户端,当您实例化它时,您的客户端所源自的 DuplexClientBase 中的 DuplexChannelFactory 将使用现有凭据进行初始化,以便它可以打开回调通道,这就是凭据将是只读的原因。

I second Mike's question and also ask why are you using NetTcpBinding if you are not going to use its inherent transport level security? Perhaps an HTTP based binding would be a better fit? That would allow you to use certificate based security which I believe can be modified after instantiation (http://msdn.microsoft.com/en-us/library/ms576164.aspx).

我第二个迈克的问题还问,如果您不打算使用其固有的传输级别安全性,为什么要使用 NetTcpBinding?也许基于 HTTP 的绑定会更合适?这将允许您使用基于证书的安全性,我相信可以在实例化后对其进行修改(http://msdn.microsoft.com/en-us/library/ms576164.aspx)。

回答by Shane

A shot in the dark but does netTcpBinding allow username and password validation? Try using application layer (SOAP) security using a http binding

摸不着头脑,但 netTcpBinding 允许用户名和密码验证吗?尝试使用 http 绑定使用应用程序层 (SOAP) 安全性