none
Reagrding WCF Service was created SharePoint RRS feed

  • Question

  • Hi there,

    I am a new one on the WCF ... My question is to create a WCF service and use a console to involve it to do something in the SharePoint.

    My web.config is :[Note] the web.config is belonged to SharePoint web.config NOT ASP.NET

    <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="MyServiceServiceBehavior">
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"></serviceMetadata>
              <serviceDebug includeExceptionDetailInFaults="true"></serviceDebug>
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="jsonBehaviour">
              <webHttp />
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <bindings>
          <wsHttpBinding>
            <binding name="wsHttpEndpointBinding" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647">
              <security mode="Transport">  
                <transport clientCredentialType="Ntlm"/>
    			<message clientCredentialType="UserName" algorithmSuite="Default"/>              
              </security>  
            </binding>
          </wsHttpBinding>
        </bindings>
        <services>
          <service name="TecturaWsListItems.v2.Service" behaviorConfiguration="MyServiceServiceBehavior">
            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" contract="TecturaWsListItems.v2.IService" />
            <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange">
            </endpoint>
          </service>
        </services>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        </serviceHostingEnvironment>
      </system.serviceModel>

    my Console Application (.net framework) :

    using System;
    using System.Net;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;
    using System.ServiceModel;
    
    namespace ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                var myBinding = new WSHttpBinding();
                myBinding.Security.Mode = SecurityMode.Transport;
                myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    
                var myEndPoint = new EndpointAddress("https://extlab.litwareinc.pri/_vti_bin/TecturaWsListItems.v2/service.svc");
    
                serviceClient.ServiceClient actionsClient = new serviceClient.ServiceClient(myBinding, myEndPoint);
    
                actionsClient.ClientCredentials.UserName.UserName = "litwareinc\\Administrator";
                actionsClient.ClientCredentials.UserName.Password = "pass@word1";
                actionsClient.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.Root, X509FindType.FindBySubjectName,
        "WIN-6CLKD4AEAOL.litwareinc.pri");
    
                ServicePointManager.ServerCertificateValidationCallback =
                delegate (
                    object s,
                    X509Certificate certificate,
                    X509Chain chain,
                    SslPolicyErrors sslPolicyErrors
                )
                {
                    return true;
                };
    
                actionsClient.Open();
                Console.WriteLine("actionsClient is Opened.");
    
                Console.WriteLine(actionsClient.DoWork(1));
            }
        }
    }
    

    Finally, I got the error message ::

    System.ServiceModel.Security.MessageSecurityException
      HResult=0x80131501
      Message=The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'NTLM'.
      Source=mscorlib
      StackTrace:
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at ConsoleApp.serviceClient.IService.DoWork(Int32 value)
       at ConsoleApp.serviceClient.ServiceClient.DoWork(Int32 value) in C:\Users\msClient\source\repos\ConsoleApp\ConsoleApp\Connected Services\serviceClient\Reference.cs:line 170
       at ConsoleApp.Program.Main(String[] args) in C:\Users\msClient\source\repos\ConsoleApp\ConsoleApp\Program.cs:line 40

    Inner Exception 1:
    WebException: The remote server returned an error: (401) Unauthorized.

    does anyone have any idea on it???

    Thanks

    WILL 


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.

    Tuesday, November 12, 2019 4:51 PM

All replies

  • Hi,

    I once saw your posts in the Sharepoint forum. there is a difference with the above configuration. Therefore, I have a misunderstanding of this issue. 
    There are two ways to use windows credentials. NTLM, Kerberos.
    Since we use NTLM authentication, which belongs to the Windows authentication, we should provide the credential by the below form.

    ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
                client.ClientCredentials.Windows.ClientCredential.UserName = "administrator";
                client.ClientCredentials.Windows.ClientCredential.Password = "abcd1234!";


    For more details about windows authentication, 
    https://docs.microsoft.com/en-us/windows-server/security/windows-authentication/windows-authentication-overview

             <security mode="Transport">  
                <transport clientCredentialType="Ntlm"/>
    			<message clientCredentialType="UserName" algorithmSuite="Default"/>              
              </security> 
    


    In the above configuration, the message section is invalid. So the server authenticates the client with NTLM credential. 
    In addition, the client proxy object will directly use the settings in the configuration file, such as the binding type, service endpoint address. there is no need for extra set up in the code segments.
    Feel free to let me know if there is anything I can help with.
    Best Regards
    Abraham

    Wednesday, November 13, 2019 9:17 AM
    Moderator
  • Hi Abraham,

    first of all, thank you very much for the help.

    correct. I had posted the same issue on the SharePoint forum and haven't got solution on it. To be honest, the workaround you provided I have tried it out. and unfortunately cannot work ...@@

    I have tried lots of solutions and cannot solve my problem.

    WILL


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.

    Wednesday, November 13, 2019 9:22 AM
  • Hi,
    How do you call the service on the client-side? Would you mind sharing more details about the steps you took? 
    If you do call the service by adding service reference, what is the configuration on the client-side?
    Finally, please ensure the credential is windows credential not username/password pattern.
    Feel free to let me know if the problem still exists.
    Best Regards
    Abraham
    Thursday, November 14, 2019 2:27 AM
    Moderator
  • Hi Abraham:

    I list out some information you want in my slide (https://1drv.ms/p/s!Aj2Mcyp8XWC1g8t9NoYpH6Ouk55hpQ)

    thanks

    The shown below is my outcome:

    My testing code: Pretty simple

    var myBinding = new WSHttpBinding();
                myBinding.Security.Mode = SecurityMode.Transport;
                myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    
                var myEndPoint = new EndpointAddress("https://extlab.litwareinc.pri/_vti_bin/TecturaWsListItems.v2/service.svc");
    
                serviceClient.ServiceClient actionsClient = new serviceClient.ServiceClient(myBinding, myEndPoint);
    
                actionsClient.ClientCredentials.Windows.ClientCredential.UserName = "litwareinc\\Administrator";
                actionsClient.ClientCredentials.Windows.ClientCredential.Password = "pass@word1!";
                //actionsClient.ClientCredentials.UserName.UserName = "litwareinc\\Administrator";
                //actionsClient.ClientCredentials.UserName.Password = "pass@word1";
    
                actionsClient.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName,
        "DESKTOP-F69D7GL.litwareinc.pri");
    
                ServicePointManager.ServerCertificateValidationCallback =
                delegate (
                    object s,
                    X509Certificate certificate,
                    X509Chain chain,
                    SslPolicyErrors sslPolicyErrors
                )
                {
                    return true;
                };
    
                actionsClient.Open();
                Console.WriteLine("actionsClient is Opened.");
    
                Console.WriteLine(actionsClient.DoWork(1));

    • Edited by Will .H Thursday, November 14, 2019 8:24 AM
    Thursday, November 14, 2019 8:20 AM
  • Hi,
    I admire your patience on this issue, I am glad to see your concise PPT. very good.
    Let’s talk the Console application first, we should use servicereference namespace instead of the service client.
    Try to directly instantiate the client proxy class by the below command and provide a pair of window credential without the domain name.
    ServiceReference.ServiceClient client = new ServiceReference.ServiceClient();
                client.ClientCredentials.Windows.ClientCredential.UserName = "Administrator";
                client.ClientCredentials.Windows.ClientCredential.Password = "pass@word1";

    The construct of the client proxy will automatically use the configuration in the Appconfig, binding type, authentication mode and the service endpoint address.
    We should ensure that the binding type between the server and the client-side is consistent, therefore it is unnecessary to provide an extra certificate according to the configuration on the server-side.
    Feel free to let me know if the problem still exists.
    Best Regards
    Abraham
    Friday, November 15, 2019 1:55 AM
    Moderator
  • Hi Abraham,

    I am very grateful for your help indeed. my another question is our client's production site is to use https and cert. if we only just use "account and password" OR "Cert" OR "Both" for authentication.? another thing is whether or not even though we use Class Library, we also need a App.config in the Class Library Project? I am a little bit confusing @@.

    Thanks.

    WILL


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.


    • Edited by Will .H Friday, November 15, 2019 2:37 AM
    Friday, November 15, 2019 2:37 AM
  • Hi Abraham,

    I got a new error:

    My config Client Side and Server Side

    Error:


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.

    Friday, November 15, 2019 2:58 AM
  • Hi,

    What client credential is provided depends on the WCF binding configuration on the server-side.

    Server-side configuration.

         <wsHttpBinding>
            <binding name="wsHttpEndpointBinding" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647">
              <security mode="Transport">  
                <transport clientCredentialType="Ntlm"/>
    			<message clientCredentialType="UserName" algorithmSuite="Default"/>              
              </security>  
            </binding>
          </wsHttpBinding>
    



    You could check the automatically configuration on the client-side after adding service reference on the client-side. it should be the same as the above and the message section will be ignored. The server uses a certificate to provide integrity, confidentially. But authenticate the client only with NTLM, namely we should provide windows account. 
    Besides, Your ActionCLient does not belong to your ServiceReference1 namespace, have you realized it? The newly generated client proxy located in the servicereference1 namespace.
    Best Regards
    Abraham

    Friday, November 15, 2019 7:50 AM
    Moderator
  • Hi Abraham,

    • Besides, Your ActionCLient does not belong to your ServiceReference1 namespace, have you realized it? The newly generated client proxy located in the servicereference1 namespace.

    Thanks for your remindation. I have already recomfirmed it.

    • We should ensure that the binding type between the server and the client-side is consistent, therefore it is unnecessary to provide an extra certificate according to the configuration on the server-side.

    I still past the screenshot for you as the shown below. the binding type is the same ... @@

    WILL


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.

    Sunday, November 17, 2019 3:44 AM
  • From the client details described in you PPT, the Service Refernece1 should contains the client proxy class, with which we could call the service.
    https://i.stack.imgur.com/k31ni.png
    But the automatically generated service endpoint on the client-side actually uses such service contract. The client service endpoint is supposed to use Servicereference1.IService contract.

    https://i.stack.imgur.com/JImFI.png
    Too many screenshots confuse me, I suggest you consume the service in another new console application. Do not add the other service reference.  After adding service reference, please share the System.servicemode section in the Appconfig with me.
    Feel free to let me know If there is anything I can help with.
    Best Regards
    Abraham

    Monday, November 18, 2019 1:54 AM
    Moderator
  • Hi Abraham,

    I have changed the name of namespace so it is correct. thanks.


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.

    Monday, November 18, 2019 8:19 AM
  • Hi,

    Anyway, congratulations to you, please mark the most helpful reply as an answer, so that helps whoever runs into a similar problem. Thanks for understanding,

    Best Regards

    Abraham

    Monday, November 18, 2019 11:12 AM
    Moderator
  • Hi Abraham,

    To be honest, the error is the same as previous. Event though I follow the above configuration.


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.


    • Edited by Will .H Monday, November 18, 2019 1:42 PM
    Monday, November 18, 2019 1:42 PM
  • Hi,

    What is the automatically generated configuration located in the Appconfig file in your new console application?

    Abraham

    Tuesday, November 19, 2019 2:11 AM
    Moderator
  • Hi Abraham,

    I recreate new project by using .NET core framework template. 

    1. no any client config (ex: app.config) was auto-generated. even though I create a app.config manually, the result is the same.
    2. and I also got the same error message as shown below.


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.


    • Edited by Will .H Tuesday, November 19, 2019 8:58 AM
    Tuesday, November 19, 2019 8:57 AM
  • Hi Will,

    Anyway, we indeed need to provide a client certificate if the server authenticates the client with a certificate, In WCF, we configure this by the below code.

    <wsHttpBinding>
              <binding name="mybinding">
                <security mode="Transport">
                  <transport clientCredentialType="Certificate"></transport>
                </security>
              </binding>
            </wsHttpBinding>

    Authenticating the client with a certificate requires that the trust relationship between the client-side and the server-side should be established in advanced. Thereby we should install the server certificate in the client LocalCA, and then the certificate we provided on the client-side should be installed on the server-side.

    Please refer to the below document.

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transport-security-with-certificate-authentication

    Feel free to let me know if there is anything I can help with.

    Best Regards

    Abraham

    Wednesday, November 20, 2019 1:49 AM
    Moderator
  • Hi Abraham,

    I got the error:

    when I amended my web.config of SharePoint Site as you mentioned on the previous post. on the other hand I also correct my source code like the following:

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    System.ServiceModel.Security.SecurityNegotiationException
      HResult=0x80131500
      Message=Could not establish trust relationship for the SSL/TLS secure channel with authority 'extlab.litwareinc.pri'.
      Source=System.Private.ServiceModel
      StackTrace:
       at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(HttpRequestException requestException, HttpRequestMessage request, HttpAbortReason abortReason)
       at System.ServiceModel.Channels.HttpChannelFactory`1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.<SendRequestAsync>d__13.MoveNext()
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
       at System.ServiceModel.Channels.RequestChannel.<RequestAsync>d__33.MoveNext()
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at System.ServiceModel.Channels.RequestChannel.<RequestAsyncInternal>d__32.MoveNext()
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at System.Runtime.TaskHelpers.WaitForCompletionNoSpin[TResult](Task`1 task)
       at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(MethodCall methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(MethodInfo targetMethod, Object[] args)
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Reflection.DispatchProxyGenerator.Invoke(Object[] args)
       at generatedProxy_1.DoWork(Int32 )
       at ServiceReference.ServiceClient.DoWork(Int32 value) in C:\Users\Administrator\source\repos\core.ConsoleApp\core.ConsoleApp\Connected Services\ServiceReference\Reference.cs:line 167
       at core.ConsoleApp.Program.Main(String[] args) in C:\Users\Administrator\source\repos\core.ConsoleApp\core.ConsoleApp\Program.cs:line 40
    Inner Exception 1:
    HttpRequestException: The SSL connection could not be established, see inner exception.
    Inner Exception 2:
    AuthenticationException: The remote certificate is invalid according to the validation procedure.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    WSHttpBinding myBinding = new WSHttpBinding();
                myBinding.Security.Mode = SecurityMode.Transport;
                myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    
                var myEndPoint = new EndpointAddress("https://extlab.litwareinc.pri/_vti_bin/TecturaWsListItems.v2/service.svc");
    
                ServiceReference.ServiceClient actionsClient = new ServiceReference.ServiceClient(myBinding, myEndPoint);
    
                //actionsClient.ClientCredentials.Windows.ClientCredential.UserName = "Administrator";
                //actionsClient.ClientCredentials.Windows.ClientCredential.Password = "pass@word1!";
                //actionsClient.ClientCredentials.UserName.UserName = "litwareinc\\Administrator";
                //actionsClient.ClientCredentials.UserName.Password = "pass@word1";
    
                actionsClient.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName,
        "WIN-6CLKD4AEAOL.litwareinc.pri");
    
                ServicePointManager.ServerCertificateValidationCallback =
                delegate (
                    object s,
                    X509Certificate certificate,
                    X509Chain chain,
                    SslPolicyErrors sslPolicyErrors
                )
                {
                    return true;
                };
    
                Console.WriteLine(actionsClient.DoWork(1));


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.

    Wednesday, November 20, 2019 3:14 AM
  • Hi Abraham,

    I add a little bit more,

    I doubt whether or not it might be the SharePoint Configuration issue? or source code and web.config 

    WILL


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.


    • Edited by Will .H Wednesday, November 20, 2019 6:14 AM
    Wednesday, November 20, 2019 6:11 AM
  • Hi,
    The error has clearly told us that the secure connection failed to establish. We have to establish the trust relationship between the client-side and the server-side.
    The SSL connection could not be established, see inner exception.
    Have you go through the official document?
    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transport-security-with-certificate-authentication
    The server’s certificate must be trusted by the client and the client’s certificate must be trusted by the server.
    Best Regards
    Abraham
    Monday, November 25, 2019 1:56 AM
    Moderator
  • Hi Abraham,

    Are you willing to provide some sample code with me?? because I follow the documentation from MS. and cannot get any expected result (I try a lots). and my WCF is built in the SharePoint instead of ASP .NET web site. I have no idea on it and what happened


    Hi there, if you found my comment very helpful then please | Propose as answer | . Thanks and Regards.

    Monday, November 25, 2019 2:52 AM
  • The complete code has been given in the Microsoft link, and the question is how to use certificates to build trust relationships.
    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/working-with-certificates
    Taking the issue of trusting the server certificate as an example.
    after that I copied the Cert(.cer) to client machine and imported the Cert into Perosnal Certificates folder of Local Computer
    We should install the certificate into Trusted Root Certification Authorities, this is the default validation mode.
    Best Regards
    Abraham
    Monday, November 25, 2019 8:09 AM
    Moderator