none
Per-Session Services based on WSHttpBinding

    Question

  • Hi Folks. I am writing a WCF services based on http, which can be consumed by web browsers. Because my web method might return a huge number of objects, so that a single Request-Reply method call doesn't meet my need. 

    Firstly, I chose to use WSDualHTTPBinding to leverage its "call back", but it seems not work if browser raises a Ajax invocation. So I switched to WSHttpBinding to make it as a Per-Session Service. Then my Browser and my client (yup, my service supports both web browsers and windows clients) can raise a "poll" to get those objects, 100 for each time.

    I do read some docs, which said WSHttpBinding supports Per-Session services. But I cannot get it work. Here is just my client code sample, and the InvalidOperationException is thrown when creating a channel and says "Contract requires Session, but Binding 'WSHttpBinding' doesn't support it or isn't configured properly to support it."

    So my question is that:

        a.) what's the right way to get a huge number of objects thru web services?
        b.) Is the WSHttpBinding right one for my scenario? Basically, I need any web browsers can consume my service, besides my current client;
        c.) How to make WSHttpBinding support Per-Session call?

    Thx!!!

     

     

    [

    ServiceContract(SessionMode = SessionMode.Required)]

     

    public interface IDDIService

    {

      [

    OperationContract()]

      

    void BeginGetList(string schemaName);

      [

    OperationContract()]

     

      object[] GetList();

    }

     


    public

     

    static void Main(string[] args)

    {

     

    EndpointAddress endPoint = new EndpointAddress(new Uri("https://myMachine/Service.svc"));

     

    WSHttpBinding binding = new WSHttpBinding(SecurityMode.Transport, false);

    binding.Security.Transport.ClientCredentialType =

    HttpClientCredentialType.Certificate;

    binding.SendTimeout =

    new TimeSpan(0, 10, 0);

     

    ChannelFactory<IDDIService> factory = new ChannelFactory<IDDIService>(binding, endPoint);

    factory.Credentials.Windows.ClientCredential =

    new NetworkCredential("administrator", "password");

     

    IDDIService moacService = factory.CreateChannel();

     



     

    Tuesday, January 26, 2010 9:17 AM

Answers

  • oh - if you are using transport security then it is not using WS-SecureConversation and WS-ReliableMessaging is turned off by default. Therefore the two protocols that WSHttpBinding uses for session are not available. You either need to use message security or turn on reliable session
    Richard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
    Twitter: richardblewett
    • Marked as answer by Mog Liang Wednesday, February 03, 2010 1:40 AM
    Tuesday, January 26, 2010 9:52 AM
    Moderator

All replies

  • WSHttpBinding supports session but only if either security (SecureConversation) or reliable messaging are enabled. So with the standard defaults, if you then change the security mode to none for the binding then it can;t support session
    Richard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
    Twitter: richardblewett
    Tuesday, January 26, 2010 9:24 AM
    Moderator
  • "if you then change the security mode to none for the binding then it can;t support session"

    But I didn't change security mode to none, the whole code is above. :-(

    Tuesday, January 26, 2010 9:32 AM
  • Are you using a different proxy instance for the requests?
    Richard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
    Twitter: richardblewett
    Tuesday, January 26, 2010 9:38 AM
    Moderator
  • Absolutely not. The whole client code is listed below, I believe it's very simple and direct. But don't know what's wrong.


     

    using System;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Permissions;
    using System.Security.Principal;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.Text;
    using System.Threading;
    using System.Xml;
    using System.Globalization;
    using System.IO;
    using System.Security;
    using System.Net;
    
    namespace TestMoac
    {
    
        /// <summary>
        /// Public interface for extensions web services
        /// </summary>
        [ServiceContract(SessionMode = SessionMode.Required)]
        public interface IDDIService
        {
            [OperationContract()]
            void BeginGetList(string schemaName);
    
            [OperationContract()]
            object[] GetList();
        }
    
        class Program
        {
            public static void Main(string[] args)
            {
                // Turn off the server SSL cert check
                System.Net.ServicePointManager.ServerCertificateValidationCallback += CertificateValidationCallBack;
                try
                {
                    EndpointAddress endPoint = new EndpointAddress(new Uri("https://bjexvm117/ecp/DDIService/DDIService.svc"));
                    WSHttpBinding binding = new WSHttpBinding(SecurityMode.Transport, false);
                    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
                    binding.SendTimeout = new TimeSpan(0, 10, 0);
                    ChannelFactory<IDDIService> factory = new ChannelFactory<IDDIService>(binding, endPoint);
                    factory.Credentials.Windows.ClientCredential = new NetworkCredential("administrator", "J$p1ter");
                    IDDIService moacService = factory.CreateChannel();
    
                    moacService.BeginGetList("Test");
                    var list = moacService.GetList();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
    
            private static bool CertificateValidationCallBack(
                  object sender,
                  System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                  System.Security.Cryptography.X509Certificates.X509Chain chain,
                  System.Net.Security.SslPolicyErrors sslPolicyErrors)
            {
                return true;
    
            }
        }
    }
    Tuesday, January 26, 2010 9:47 AM
  • oh - if you are using transport security then it is not using WS-SecureConversation and WS-ReliableMessaging is turned off by default. Therefore the two protocols that WSHttpBinding uses for session are not available. You either need to use message security or turn on reliable session
    Richard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
    Twitter: richardblewett
    • Marked as answer by Mog Liang Wednesday, February 03, 2010 1:40 AM
    Tuesday, January 26, 2010 9:52 AM
    Moderator
  • Thank for the reply. So I added the following code to enable reliable session, but get another error message, "Binding validation failed because the WSHttpBinding does not support reliable sessions over transport security (HTTPS). The channel factory or service host could not be opened. Use message security for secure reliable messaging over HTTP."

    Does that mean if I want to use per session call, I have to use Message mode? in which I have to pass my credential as a text?

    binding.ReliableSession.Enabled =

    true;

    Tuesday, January 26, 2010 11:27 AM
  • You can use certificate based authentication over message security


    Richard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
    Twitter: richardblewett
    Tuesday, January 26, 2010 12:29 PM
    Moderator