locked
Message Routing doesn't work RRS feed

  • Question

  • Hi, all. I defined a very simple ASP.NET Web service as follows (namespace omitted):

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Service : WebService
    {
        [WebMethod]
        public void Log(string log)
        {
            using (StreamWriter writer = File.CreateText(@"C:\log.txt"))
            {
                write.WriteLine(log);
            }
        }
    }

    The session manifest is as follows:

    <Session timestamp="0001-01-01T00:00:00.0000000-08:00" timeout="30" serialize="None" routeAnyAction="true" ackOnRouteMsgToParticipants="false" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XmlSchema-instance" xmlns="http://Microsoft/ConectedServices/2006/06/Session/">
        <SessionName>HelloWorld</SessionName>
            <Participants>
                <Participant timeout="30" role="Service" inChannelResponse="false" type="WebService">
                    <ParticipantName>TestService</ParticipantName>
                    <ParticipantID>TestService</ParticipantID>
                    <ParticipantUrl>http://localhost/TestService/Service.asmx</ParticipantUrl>
                </Participant>
            </Participants>
            <RoutingTable version="0" timestamp="0001-01-01T00:00:00.0000000-08:00">
                <Routes>
                    <Route>
                        <Criteria>(ACTION EQ 'http://tempuri.org/Log')</Criteria>
                        <Destination>TestService[http://tempuri.org/Log]</Destination>
                    </Route>
                </Routes>
            </RoutingTable>
    </Session>

    Then I created an ASP.NET Web site to talk to the service defined above through CSF Session. On the ASP.NET page, there's a button named OK. Here's the code:

    propected void OKButton_Click(object sender, EventArgs e)
    {
        if (InputTextBox.Text.Length != 0)
        {
            Header header = new Header();
            header.Addressing = new AddressingHeader();
            header.Addressing.To = new Uri(SessionUrls.SessionUrl);
            header.Addressing.Action = @"http://tempuri.org/Log;"
            header.CsfProperties.SessionId = new Uri(SessionIDTextBox.Text);
            header.Security.Add(SecurityHelper.GetUsernameToken());
            Message msg = Message.CreateMessage(header, InputTextBox.Text);
            MessageSender msgSender = new MessageSender();
            msgSender.SendAsync(msg);
        }
    }

    Several things to be noted:

    • The ASP.NET Web service works fine when I talk to it directly either by using IE or proxy class in a test project. The log.txt will sit in C:\ when we finish the talk.
    • Both ASP.NET Web service and ASP.NET Web site have permission to have access to local resources.
    • Session can be created successfully and the ID can be displayed on the web page.
    • HelloWorld sample code correspond to CSF 3.0 can be run properly.
    • Session trace has been enabled. Session_InputTrace.webinfo shows that message that should to be sent to my service has been received by Session. But Session_OutputTrace.webinfo doesn't contain any response message from my service.

    What's the problem? How can the message be routed to my service? What else should I take into account?

    Monday, October 9, 2006 7:01 AM

Answers

  • Hello - I would like to clarify a concept in session here.

    The anology I could draw is a telephone conference bridge. In order to talk to somebody in the conference you need join the conference and become a participant. To join the a teleconference you need some kind of credentials. Also when you join the conference, your name gets announced to everybody in the conference. When you leave the conference, that also gets announced to everybody in the conference.

    Similarly to route a message in Session that service needs to be a participant in the Session. You cannot route a message to a session if you are not a participant. When a participant is added / removed in a session, AddRemoveParticipantNotification is sent to all the participants who have subscribed to it. Please refer the Session documentation on how to subscribe to these notifications.

    To address your question of how do I route a message from a webpage, we have shipped a Sync Session sample which shall provide you more clarity on this. So please take a look at that.

    Thanks

    Thursday, October 12, 2006 4:42 AM
  • Hello Yoglun,

    See the manifest submitted to the Session by the service trying to invoke TestService (this is the same manifest you had posted):

    <Session timestamp="0001-01-01T00:00:00.0000000-08:00" timeout="30" serialize="None" routeAnyAction="true" ackOnRouteMsgToParticipants="false" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XmlSchema-instance" xmlns="http://Microsoft/ConectedServices/2006/06/Session/">
        <SessionName>HelloWorld</SessionName>
            <Participants>
                <Participant timeout="30" role="Service" inChannelResponse="false" type="WebService">
                    <ParticipantName>TestService</ParticipantName>
                    <ParticipantID>TestService</ParticipantID>
                    <ParticipantUrl>http://localhost/TestService/Service.asmx</ParticipantUrl>
                </Participant>
            </Participants>
            <RoutingTable version="0" timestamp="0001-01-01T00:00:00.0000000-08:00">
                <Routes>
                    <Route>
                        <Criteria>(ACTION EQ 'http://tempuri.org/Log')</Criteria>
                        <Destination>TestService[http://tempuri.org/Log]</Destination>
                    </Route>
                </Routes>
            </RoutingTable>
    </Session>

    Here you have added TestService as participant. But you have not added the Service trying to call TestService as a participant. For example: Service XYZ is trying to call TestService then you need to add XYZ as a participant in the session manifest.

    Also if you look at the routing table, you have specified route for routing message to the TestService. But there should also be a route to accept the response and route the response to XYZ service.

    You need to do all these in order to get the response from TestService.

    See the following, I have modified your manifest to include XYZ service:

    <Session timestamp="0001-01-01T00:00:00.0000000-08:00" timeout="30" serialize="None" routeAnyAction="true" ackOnRouteMsgToParticipants="false" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XmlSchema-instance" xmlns="http://Microsoft/ConectedServices/2006/06/Session/">
        <SessionName>HelloWorld</SessionName>
            <Participants>
                <Participant timeout="30" role="Service" inChannelResponse="false" type="WebService">
                    <ParticipantName>TestService</ParticipantName>
                    <ParticipantID>TestService</ParticipantID>
                    <ParticipantUrl>http://localhost/TestService/Service.asmx</ParticipantUrl>
                </Participant>
                <Participant timeout="30" role="Service" inChannelResponse="false" type="WebService">
                    <ParticipantName>XYZService</ParticipantName>
                    <ParticipantID>XYZService</ParticipantID>
                    <ParticipantUrl>XYZ Service URL</ParticipantUrl>
                </Participant>
            </Participants>
            <RoutingTable version="0" timestamp="0001-01-01T00:00:00.0000000-08:00">
                <Routes>
                    <Route>
                        <Criteria>(ACTION EQ 'http://tempuri.org/Log')</Criteria>
                        <Destination>TestService[http://tempuri.org/Log]</Destination>
                    </Route>
                    <Route>
                        <Criteria>(ACTION EQ 'http://tempuri.org/LogResponse')</Criteria>
                        <Destination>XYZService[Specify Action to accept the response similar to http://tempuri.org/Log]</Destination>
                    </Route>
                </Routes>
            </RoutingTable>
    </Session>

    I hope that should solve the issue.

    Regards

    Vikram

    Friday, October 13, 2006 4:48 AM

All replies

  • Hi,

    In the manifest you have routed the request message to teh required web service, but the response returned by the web service will have the action as http://tempuri.org/LogResponse (if you havent specified any other action name for the method explicitly in the web service)

    This response needs to be routed to the originator, hence another route needs to be created in the manifest to route the response message. Also a service should be running at your web site to receive and process this response.

    Hope this helps.

    Ashish

    Tuesday, October 10, 2006 4:20 AM
  • Hi, Ashish. For simplicity, I have made the Log method of my service a one-way method, just as the code above shown. When the client message is sent to my service through session, the Log method should create a file under C: drive and inside the file contains the message body text. When dive into the trace file of session, it seemed that message had been sent to session but didn't reach the destination service, i.e. my service didn't receive the message! Is there anything else I should take into account to make the routing work?
    Tuesday, October 10, 2006 5:33 AM
  • Hello Yoglun,

    See the event log where CSF has been installed. I suppose you will find some error logged by the Session service.

    In your code I found that the action specified by you ends with a semicolon

    header.Addressing.Action = @"http://tempuri.org/Log;"

    Remove the semicolon and try running the implementation again.

    I hope that solves your problem.

    Regards,

    Vikram

    Tuesday, October 10, 2006 5:48 AM
  • Hi, Vikram. I'm sorry, but the code in my computer doesn't contain such a mistake. Well, I didn't copy the code and posted it here. I just re-typed the code again. In addition, if the semicolon sits inside quotation mark, then the compiler will complain! The session input trace file indicates that message has been sent to session, but output trace file indicates that session doesn't route the message to the destination service. Any suggestions?
    Tuesday, October 10, 2006 6:37 AM
  • Hello Yoglun,

    Are you using CSF 3.0 Developer Edition or CSF 3.0 Full Version?

    Did you see the event log. What is the error inside event log?

    Regards,

    Vikram

    Tuesday, October 10, 2006 6:42 AM
  • Hi Vikram. I am using the 3.0 version downloaded from MSDN subscription. What's wrong with it?
    Tuesday, October 10, 2006 12:07 PM
  • Hello Yoglun,

    Please send the error log in the event viewer after you send the request. So that I can get some idea as to what is happening.

    Regards,

    Vikram

    Wednesday, October 11, 2006 7:29 AM
  • Hi Vikram. After I sent the request, there were four logs in the event viewer. Three of them are of type information: one for Session service has started successfully; one for clustering is not enabled in Session; and one for CustomUsernameTokenManager is enabled. The last of them is of error type, detailed as follows:

    Event Type: Error
    Event Source: Session
    Event Category: None
    Event ID: 20137
    Date:  10/11/2006
    Time:  3:54:24 PM
    User:  N/A
    Computer: RESEARCH-OSDT
    Description:
    Timestamp: 10/11/2006 10:54:24 PM
    Message: Microsoft.ConnectedServices.Sdk.Messaging.SoapFaultException: The message 'urn:uuid:c2e93c0e-08d0-4a67-971f-8fcfcdfa6949' from non-participant is ignored for routing.
       at Microsoft.ConnectedServices.Connector.Session.Session.RouteMsgToParticipant(SessionRequestEnvelope request)
       at Microsoft.ConnectedServices.Connector.Session.SessionManager.RouteMsgToParticipants(SoapEnvelope envelope, Boolean sendRouteAck)
       at Microsoft.ConnectedServices.Connector.Session.SessionWS.DeadLetter()
    Category: Session OperationalEvent
    Priority: 1
    EventId: 20137
    Severity: Error
    Title:Session
    Machine: RESEARCH-OSDT
    Application Domain: /LM/W3SVC/1/Root/Session30-1-128050808487187500
    Process Id: 3496
    Process Name: c:\windows\system32\inetsrv\w3wp.exe
    Win32 Thread Id: 3448
    Thread Name:
    Extended Properties:

    For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

    What happens under the hook in your opinion? Thanks.

    Wednesday, October 11, 2006 8:06 AM
  • Hi

    Can you please check the trace and see whats the url present in the "From" section in header of the message.

    The session service accepts the messages only from the services which are a participant in the session.

    If the "From" information in header is different from the participants list used to create the session, the message is ignored.

    Ashish

    Wednesday, October 11, 2006 8:20 AM
  • Hello Yoglun,

    Check the session output trace and see the "From" address. I suppose you are constructing a message with a "From" address. Ensure that you are including "From" address in the message you are responding back.

    Check whether the "From" address matches the participant URL in Session manifest. If not, then change the URL in the "From" address and test the implementation.

    See if it work after making the above changes.

    Regards,

    Vikram

    Wednesday, October 11, 2006 3:22 PM
  • Hi Vikram. The following segment is from Session_InputTrace.webinfo:

      <inputMessage utc="10/11/2006 10:54:24 PM" messageId="urn:uuid:c2e93c0e-08d0-4a67-971f-8fcfcdfa6949">
        <processingStep description="Unprocessed message">
          <env:Envelope xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:env="http://www.w3.org/2003/05/soap-envelope">
            <env:Header>
              <wsa:Action>http://tempuri.org/Log</wsa:Action>
              <wsa:MessageID>urn:uuid:c2e93c0e-08d0-4a67-971f-8fcfcdfa6949</wsa:MessageID>
              <wsa:To>http://research-osdt.contoso.com/session30/session.ashx</wsa:To>
              <csfse:SessionID xmlns:csfse="http://Microsoft/ConnectedServices/2006/06/Session/">urn:0eacbcc3-b878-4bca-8286-3617cf550076</csfse:SessionID>
              <wsse:Security env:mustUnderstand="true">
                <wsu:Timestamp wsu:Id="Timestamp-87bb2f2d-01e1-4f59-8648-1933f55f40d9">
                  <wsu:Created>2006-10-11T22:54:24Z</wsu:Created>
                  <wsu:Expires>2006-10-11T22:59:24Z</wsu:Expires>
                </wsu:Timestamp>
                <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-513d48d4-da02-4fa0-ab6c-115c0cc68c72">
                  <wsse:Username>Session-Service@contoso.com</wsse:Username>
                  <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">research=0sdt</wsse:Password>
                  <wsse:Nonce>Lur9WqvGaSkN7xpiZDW1YA==</wsse:Nonce>
                  <wsu:Created>2006-10-11T22:54:24Z</wsu:Created>
                </wsse:UsernameToken>
              </wsse:Security>
            </env:Header>
            <env:Body>
              <string xmlns="http://tempuri.org/">Allen Lee</string>
            </env:Body>
          </env:Envelope>
        </processingStep>
        <processingStep description="Entering SOAP filter Microsoft.Web.Services3.Design.RequireSoapHeaderAssertion+RequireSoapHeaderFilter" />
        <processingStep description="Exited SOAP filter Microsoft.Web.Services3.Design.RequireSoapHeaderAssertion+RequireSoapHeaderFilter" />
        <processingStep description="Entering SOAP filter Microsoft.ConnectedServices.Sdk.Security.DynamicAssertionServiceInputFilter" />
        <processingStep description="Exited SOAP filter Microsoft.ConnectedServices.Sdk.Security.DynamicAssertionServiceInputFilter" />
        <processingStep description="Entering SOAP filter Microsoft.ConnectedServices.InternalUtils.TraceFilters.InputTraceFilter" />
        <processingStep description="Exited SOAP filter Microsoft.ConnectedServices.InternalUtils.TraceFilters.InputTraceFilter" />
        <processingStep description="Entering SOAP filter Microsoft.Web.Services3.Design.AuthorizationAssertion+AuthorizationFilter" />
        <processingStep description="Exited SOAP filter Microsoft.Web.Services3.Design.AuthorizationAssertion+AuthorizationFilter" />
        <processingStep description="Processed message">
          <env:Envelope xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:env="http://www.w3.org/2003/05/soap-envelope">
            <env:Header>
              <csfse:SessionID xmlns:csfse="http://Microsoft/ConnectedServices/2006/06/Session/">urn:0eacbcc3-b878-4bca-8286-3617cf550076</csfse:SessionID>
            </env:Header>
            <env:Body>
              <string xmlns="http://tempuri.org/">Allen Lee</string>
            </env:Body>
          </env:Envelope>
        </processingStep>
      </inputMessage>

    There's no "From" inside. But why should there be a "From" while I sent a message in one-way fashion asychronously? The message was sent from an ASP.NET web page by using MessageSender. There was just one participant service who would receive the message and persist it. Can't session route the kind of message?

    Thursday, October 12, 2006 12:14 AM
  • Hello - I would like to clarify a concept in session here.

    The anology I could draw is a telephone conference bridge. In order to talk to somebody in the conference you need join the conference and become a participant. To join the a teleconference you need some kind of credentials. Also when you join the conference, your name gets announced to everybody in the conference. When you leave the conference, that also gets announced to everybody in the conference.

    Similarly to route a message in Session that service needs to be a participant in the Session. You cannot route a message to a session if you are not a participant. When a participant is added / removed in a session, AddRemoveParticipantNotification is sent to all the participants who have subscribed to it. Please refer the Session documentation on how to subscribe to these notifications.

    To address your question of how do I route a message from a webpage, we have shipped a Sync Session sample which shall provide you more clarity on this. So please take a look at that.

    Thanks

    Thursday, October 12, 2006 4:42 AM
  • Hello Yoglun,

    See the manifest submitted to the Session by the service trying to invoke TestService (this is the same manifest you had posted):

    <Session timestamp="0001-01-01T00:00:00.0000000-08:00" timeout="30" serialize="None" routeAnyAction="true" ackOnRouteMsgToParticipants="false" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XmlSchema-instance" xmlns="http://Microsoft/ConectedServices/2006/06/Session/">
        <SessionName>HelloWorld</SessionName>
            <Participants>
                <Participant timeout="30" role="Service" inChannelResponse="false" type="WebService">
                    <ParticipantName>TestService</ParticipantName>
                    <ParticipantID>TestService</ParticipantID>
                    <ParticipantUrl>http://localhost/TestService/Service.asmx</ParticipantUrl>
                </Participant>
            </Participants>
            <RoutingTable version="0" timestamp="0001-01-01T00:00:00.0000000-08:00">
                <Routes>
                    <Route>
                        <Criteria>(ACTION EQ 'http://tempuri.org/Log')</Criteria>
                        <Destination>TestService[http://tempuri.org/Log]</Destination>
                    </Route>
                </Routes>
            </RoutingTable>
    </Session>

    Here you have added TestService as participant. But you have not added the Service trying to call TestService as a participant. For example: Service XYZ is trying to call TestService then you need to add XYZ as a participant in the session manifest.

    Also if you look at the routing table, you have specified route for routing message to the TestService. But there should also be a route to accept the response and route the response to XYZ service.

    You need to do all these in order to get the response from TestService.

    See the following, I have modified your manifest to include XYZ service:

    <Session timestamp="0001-01-01T00:00:00.0000000-08:00" timeout="30" serialize="None" routeAnyAction="true" ackOnRouteMsgToParticipants="false" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XmlSchema-instance" xmlns="http://Microsoft/ConectedServices/2006/06/Session/">
        <SessionName>HelloWorld</SessionName>
            <Participants>
                <Participant timeout="30" role="Service" inChannelResponse="false" type="WebService">
                    <ParticipantName>TestService</ParticipantName>
                    <ParticipantID>TestService</ParticipantID>
                    <ParticipantUrl>http://localhost/TestService/Service.asmx</ParticipantUrl>
                </Participant>
                <Participant timeout="30" role="Service" inChannelResponse="false" type="WebService">
                    <ParticipantName>XYZService</ParticipantName>
                    <ParticipantID>XYZService</ParticipantID>
                    <ParticipantUrl>XYZ Service URL</ParticipantUrl>
                </Participant>
            </Participants>
            <RoutingTable version="0" timestamp="0001-01-01T00:00:00.0000000-08:00">
                <Routes>
                    <Route>
                        <Criteria>(ACTION EQ 'http://tempuri.org/Log')</Criteria>
                        <Destination>TestService[http://tempuri.org/Log]</Destination>
                    </Route>
                    <Route>
                        <Criteria>(ACTION EQ 'http://tempuri.org/LogResponse')</Criteria>
                        <Destination>XYZService[Specify Action to accept the response similar to http://tempuri.org/Log]</Destination>
                    </Route>
                </Routes>
            </RoutingTable>
    </Session>

    I hope that should solve the issue.

    Regards

    Vikram

    Friday, October 13, 2006 4:48 AM
  • Hi Vikram. As SenthilN-msft said, I need to add one more service as a participant in order to send message to the destination service. But the method of the service a defined above has no return value. How can I expect there is a response routing in the routing table? Is it a must to add this kind of response routing no matter whether the target method has a return value?
    Friday, October 13, 2006 5:14 AM
  • Hello Yoglun,

    You need to add the service (XYZ) as participant in order to send the message to TestService and also to get the response.

    If you want the response from TestService (if you are sending any) to be routed to the XYZ service then you need to add a routing for the same in the session manifest.

    Note:Session cannot do anything by itself. Session needs to be guided by some one. Hence SessionManifest drives the session to do the activities. The SessionManifest is a guide to the session.

    It does not matter whether the function in the service is returning a value (which is Synchronous behaviour) or responding by sending a message in a different channel (which is Asynchronous behaviour), you need to have a routing entry for the response.

    This routing entry will tell the session where to route the response. In your case it would be XYZ service.

    Regards,

    Vikram

    Friday, October 13, 2006 9:56 AM