ASP.NET: asynchronous calls to session-enabled web service methods

Howdy,

This time a small hint for those of you that are using jQuery and/or AJAX methods to connect with an ASP.Net web service, and the web service is using Session variables (web methods with [EnableSession=true] attribute).

I have been using this approach for some time, since I needed to persist some data for users.

However, when it came to performance tests, it occurred that the AJAX calls weren’t really asynchronous. The tests revealed that each next call waits for the previous one to finish.

The reason is quite simple and is one of ASP.net’s limitations: the first request gains exclusive access to the session and its variables, and thus prevents execution of next request until the current one completes. My approach was wrong and it took a while to discover the cause. Maybe if I had read the last paragraph of this article  first, it would have been easier 😉

So, for having better performance of concurrent request in a similar architecture, one would have to either use other ASP.net methods for persisting state (like Cache object), or write a custom solution.

Hope this helps,

Łukasz

Posted from WordPress for Android

Grouping nodes by date in XSL

Hello,

a while ago I stumbled upon a task to display a list of entries (let’s call them events) grouped by date. The requirement was to transform the data which I got from a web service via XSL. The source data was not grouped in any way, each node had its own sub-element with the date information (let’s call the field EventDate). So the desired output had ought to look like this:

  • 15.03.2009
    • Event A
    • Event B
  • 21.03.2009
    • Event C
    • Event D

…and so forth. There is a technique in XSL which allowed me to achieve the goal. First of all, we have to define a key for the style sheet, which will include the dates, by which we want to group our data:

<xsl:key name="dateGroup" match="Event"
                          use="substring-before(EventDate,'T')"/>

So, we name the key dateGroup, it has to match nodes of type Event, and its value should be set to a part of the EventDate value (the substring-before function). Since our date format looks like that:

2009-03-15T15:30:00

, and we don’t want to take exact time into consideration (only the date), we shall use the sub-string of the value. So far, so good. Note that the key declaration is a top-level element in XSL.

In the next step, we shall select only the nodes with unique dates:

<xsl:template match="/ArrayOfEvent">
  <xsl:for-each select="Event[generate-id(.)=generate-id(
    key('dateGroup',substring-before(EventDate,'T')))]">
    <ul>
      <li>
        <xsl:value-of select="substring-before(EventDate,'T')" />
      </li>
    </ul>
  </xsl:for-each>
</xsl:template>

A couple of words of explanation: two additional XSL functions have been used here. The key() function uses the key defined before in order to find a node (an event in this case) with a given date. The generate-id() function creates and returns an unique identifier for a node. The dot (.) represents a current item in the for-each loop. Hence, the loop goes only over those Event-nodes, for which the equation is true, therefore for those which have an unique date.

OK, but that’s the first part. We already got first level of our desired list – the dates. Still we have to get a list of events for each of those unique dates. And again, the key() function comes to rescue. Within the previous loop, for example after displaying the date as in the previous snippet, we use another for-each loop and go over the nodes/events which have in fact the date:

<ul>
  <xsl:for-each select="key('dateGroup',substring-before(EventDate,'T'))">
    <li>
      <xsl:value-of select="Title" />
    </li>
  </xsl:for-each>
</ul>

Assuming that our event nodes have an element called Title, we display here its value. The function used here selects only the events which have the date equal to the date in the first level’s loop current iteration. The final code could look like this:

<xsl:template match="/ArrayOfEvent">
  <xsl:for-each select="Event[generate-id(.)=generate-id(
    key('dateGroup',substring-before(EventDate,'T')))]">
    <ul>
      <li>
        <xsl:value-of select="substring-before(EventDate,'T')" />
        <ul>
          <xsl:for-each select="key('dateGroup',
             substring-before(EventDate,'T'))">
            <li>
              <xsl:value-of select="Title" />
            </li>
          </xsl:for-each>
        </ul>
      </li>
    </ul>
  </xsl:for-each>
</xsl:template>

Hope this helps. Happy XSLTransforming!

“Could not find default endpoint element that references contract”

Hello,

recently, while developing a web application which uses quite a lot of ASP.Net web services, I ran across a following problem.

The application uses also a few C# class libraries, and I wanted one of those libraries to retrieve some data from a web service (let’s call it service A). So, within the class library, I added web reference to the desired web service, downloaded all needed definitions and wrote a method in order to check whether the connection to the web service was working. I also checked whether the app.config file of the class library has been modified. Positive – the Service Model section has been added, the binding has been configured. So far, so good. I compiled the assembly, and wanted to use it in another web service (service B), which serves some specific information to the presentation layer of my web application.

However, the instantiation of the SOAP client method threw the following exception:

Could not find default endpoint element that references contract ‘Client.ClientSoap’ in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.

The reason for the exception was quite simple: the web service B (which invoked the class library method that retrieved the data from service A), hasn’t been configured for usage of web service A. In other words, the Service Model section in the web.config file was missing.

Solution? Put the Service Model section generated in the app.config of the class library (as mentioned earlier) into the web.config file of the web service project.

Happy programming!