3

I'm pretty new to WCF and trying to create a WCF service with custom username and password. I know that I should set the userName and Password to the proxy's ClientCredentials, but out of some reason, I have no such a property...

I assume it has something to do with my Contract, so here it is:

My contract code:

namespace Contracts
{    
    [ServiceContract]
    public interface ICalc
    {
        [OperationContract]
        CalcResponse Add(double x, double y);

        [OperationContract]
        CalcResponse Substract(double x, double y);

        [OperationContract]
        CalcResponse Multiply(double x, double y);

        [OperationContract]
        CalcResponse Divide(double x, double y);
    }
}

In my client all I try to do is:

ChannelFactory<ICalc> channel = new ChannelFactory<ICalc>("calcEndpoint");
ICalc proxy = channel.CreateChannel();

proxy.ClientCredentials.UserName.UserName = "USER";
proxy.ClientCredentials.UserName.Password = "PASSWORD";

But my proxy doen't have a ClientCredentials property

Update: I had some issues that causes some other errors. As I solved them, I got a new error:

The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue.

My timeout is 5 set to 5 minutes in both client and server. I get this error after less than a minute...

Here's my updated code:

ChannelFactory<ICalc> channel = new ChannelFactory<ICalc>("calcEndpoint");

var defaultCredentials = channel.Endpoint.Behaviors.Find<ClientCredentials>();
channel.Endpoint.Behaviors.Remove(defaultCredentials);

ClientCredentials loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = "Comply";
loginCredentials.UserName.Password = "123456";

channel.Endpoint.Behaviors.Add(loginCredentials); 
ICalc proxy = channel.CreateChannel();

I have a custom validator, I put a breakpoint there, but it just didn't make it there... My validator code:

class CustomUserNameValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        if (userName == "comply" && password == "123456")
        {
        }
    }
}

The config (on both client and server):

<service name ="WcfServiceLibrary.Service1" behaviorConfiguration ="CustomValidator">
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost/CalcIISHost/mex"/>
        <add baseAddress ="net.tcp://localhost:808/CalcIISHost/CalcService"/>
      </baseAddresses>
    </host>
    <endpoint address ="" binding ="netTcpBinding" bindingConfiguration="tcpWithMessageSecurity" contract ="Contracts.ICalc"></endpoint>
    <endpoint address ="net.tcp://localhost:5001/CalcIISHost/mex" binding ="mexTcpBinding" contract ="IMetadataExchange"></endpoint>
  </service>
...
<behavior name="CustomValidator">
      <serviceCredentials>
        <userNameAuthentication
          userNamePasswordValidationMode="Custom"
          customUserNamePasswordValidatorType="WCFClasses.CustomUserNameValidator, WCFClasses"/>
        <serviceCertificate
          findValue="localhost"
          x509FindType="FindBySubjectName"
          storeLocation="CurrentUser"
          storeName="My" />
      </serviceCredentials>
      <serviceMetadata httpGetEnabled ="true"/>
    </behavior>
...
<netTcpBinding>
    <binding name="tcpWithMessageSecurity"  sendTimeout="00:05:00" receiveTimeout="00:05:00">
      <security mode="Message" >
        <message clientCredentialType="UserName"/>
      </security>
    </binding>
  </netTcpBinding>

Any ideas what have i done wrong?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
DA_Prog
  • 263
  • 3
  • 7
  • 14

1 Answers1

5

You can set the credentials like this...

Remove default endpoint behavior

ChannelFactory<ICalc> channel = new ChannelFactory<ICalc>("calcEndpoint");
var defaultCredentials = channel.Endpoint.Behaviors.Find<ClientCredentials>();
channel.Endpoint.Behaviors.Remove(defaultCredentials); 

Create credentials

ClientCredentials loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = "USER";
loginCredentials.UserName.Password = "PASSWORD";

Set the credentials as new endpoint behavior on factory

channel.Endpoint.Behaviors.Add(loginCredentials); 
ICalc proxy = channel.CreateChannel();

EDIT 27 Feb

I suggest adding logging to you service and post the exception you are getting in your Error.svclog file, add below under Configuration tag in your Service app.config.

<system.diagnostics>
        <sources>
            <source name="System.ServiceModel"
                    switchValue="Information, ActivityTracing"
                    propagateActivity="true" >
                <listeners>
                    <add name="xml"/>
                </listeners>
            </source>
            <source name="System.ServiceModel.MessageLogging">
                <listeners>
                    <add name="xml"/>
                </listeners>
            </source>
            <source name="myUserTraceSource"
                    switchValue="Information, ActivityTracing">
                <listeners>
                    <add name="xml"/>
                </listeners>
            </source>
        </sources>
        <sharedListeners>
            <add name="xml"
                 type="System.Diagnostics.XmlWriterTraceListener"
                 initializeData="Error.svclog" />
        </sharedListeners>
    </system.diagnostics>
Milan Raval
  • 1,880
  • 1
  • 16
  • 33
  • Oh, I'm afraid it didn't actually work... I now get an error as updated in the question... – DA_Prog Feb 24 '14 at 12:29
  • I believe that error message is not related with passing credentials, I suggest you trace the error message. – Milan Raval Feb 24 '14 at 13:22
  • I have... No errors... Only Transfer and Information. and some Activity Boundary (Start and Stop), if I got it right - it doesn't mean anything's wrong really... – DA_Prog Feb 24 '14 at 13:58
  • I have edited my answer, add the Diagnostic configuration to your Service config and let me know the exception – Milan Raval Feb 27 '14 at 06:21
  • Still nothing... In those 2 days, I changes my code a bit... After many many tries I got it to work, but my Validator was skipped... when I change the config so the validator will be called - I once again got an error ("The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue"). Even though my timeout is set to 5 minutes, I got this exception after 1 second... – DA_Prog Feb 27 '14 at 12:50
  • Do you mean that you have the diagnostic configuration in your service and stil you can see any exception in the .svclog file ? – Milan Raval Feb 28 '14 at 00:45
  • Yes. Its only Information and Transfer, and the Activity Boundary that I've mentioned before.... – DA_Prog Mar 02 '14 at 07:39