Category Archives: Services

lPeriodically calling a function in your web app

A recurring theme in web programming is calling a function periodically and/or at a specific date and time. This has two aspects:

  • Calling a function on a scheduled basis
  • Making sure time-outs don’t interfere

Calling a function on a scheduled basis

To be able to call a function on your web app, you first need an endpoint (a URL) that you can call to kick the function off. In ASP.NET you can do this in several ways:

  1. Create a page that calls the function.
  2. Create a handler (ASHX) that calls the function (more efficient than a page).
  3. Create a WCF service that allows calls with HTTP GET, as discussed in this blog post by Sasi Suryadevara.

With your endpoint in place, you can use the Windows Task Scheduler to invoke the function at any given time and at intervals as low as one minute. With the Windows Task Scheduler you have several options again:

  1. Create a VB Script that calls the URL, as discussed in this blog post by Steve Schofield.
  2. Create a PowerShell script that calls the URL (same as option 1, but more modern).
  3. Have the Windows Task Scheduler open Internet Explorer and open the specified URL (e.g. C:\PROGRA~1\INTERN~1\iexplore.exe -extoff http://www.google.com, which starts IE without extensions). If you do this, you also need to specify that the Task Scheduler closes IE after 1 minute, which you can do in the Settings tab of the task (Windows 2003), or in the Trigger configuration (Windows 2008), as shown below. NOTE: I’ve found that IE sometimes doesn’t close, even if you tell Windows to close it. Eventually this will cripple your scheduled task.


Task Settings in Windows 2003


Trigger configuration in Windows 2008

Note: In Windows 2008 the dropdowns governing duration and interval show 30 minutes as lowest value. You can in fact change this to 1 minute by editing the text.

Making sure time-outs don’t interfere

A web based call is bound to time-out after a few minutes. If you task takes longer than that, this may abort the call depending on how you programmed it, and what webserver settings are used with regards to disconnected clients. To ensure a time-out does not interfere, you can spawn a new thread and have it call the function. That way the thread handling the request can return a response to the client, and the function is carried out regardless. One issue that may arise there is that the function itself hangs or takes too long. You may want to add logic to ensure that it’s aborted after a certain time, and add logging to notify you of this, and possibly also ensure that the function can only be run by one caller at a time.

WSDL and WCF: WCF requires <sp:OnlySignEntireHeadersAndBody>

If you’ve ever tried svcutil.exe to import WSDL which has doesn’t have <sp:OnlySignEntireHeadersAndBody> specified in the security policy, you’ll know that this doens’t fly. SvcUtil will tell you the the security policy is not supported. So why is this? I assume this has something to do with the a statement in paragraph 6.6 in the WS-SecurityPolicy specification, which states:

Setting the value of this property to ‘true’ mitigates against some possible re-writing attacks.

So apparently Microsoft decided that setting it to false is not a good idea, and decided not to support setting it to false (omitting the element).

Removing the ReplyTo element if it is anonymous

Talking to a non-WCF webservice is like a box of chocolates… you never know what you’re going to get. After solving the issue mentioned in my previous blog post, I had another problem. For some reason the service didn’t expect a <wsa:ReplyTo> element if the value was anonymous. Later on the other party adjusted the service so it actually worked as expected from WCF, but in the mean time I did write a message inspector to solve the problem. Besides solving the problem it also is a nice little example of a message inspector.

public class RemoveAnonymousReplyToMessageInspector : IClientMessageInspector
{
    private const string ReplyToNode = "ReplyTo";
    private const string WSAddressingNamespace = "http://www.w3.org/2005/08/addressing";

    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {} // Not used for this scenario.

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
    {
        // This method is called before the request is sent. You can read/manipulate the message here.
        // If you’re using signing or encryption, that is done after this, this is the
        // unencrypted/unsigned mesage.
        request = RemoveAnonymousReplyTo(request);
        return null;
    }

    private Message RemoveAnonymousReplyTo(Message message)
    {
        if (message.Headers.ReplyTo.IsAnonymous == true)
        {
            int index = message.Headers.FindHeader(ReplyToNode, WSAddressingNamespace);
            message.Headers.RemoveAt(index);
        }
        return message;
    }
}

To use this, you’ll need to create a class implementing the IEndpoint behavior and add the MessageInspector in ApplyClientBehavior, as follows:

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
    RemoveAnonymousReplyToMessageInspector inspector = new RemoveAnonymousReplyToMessageInspector();
    clientRuntime.MessageInspectors.Add(inspector);
}

DataContractSerializer and interfaces

I was working on this little app I wrote a while ago and wanted to add some features requiring (de)serialization. So, I took the original class and made it a DataContract so I could use it with the DataContractSerializer. The class then looked more or less like this:

[DataContract]
public class MyClass
{
List<Trip> m_Items = new List<Item>();

[DataMember]
public IList<Item> Items
{
get { return m_Items; }
}
}


Serialization went fine, but when I tried to deserialize the same object, I got a null reference exception. Of course you say, you should have added a method tied to de OnDeserializing event, because the constructor of the object doesn’t work and hence the m_Items field is never initialized. The code I added to solve this looked like this:

[OnDeserializing]
protected void Init(StreamingContext context)
{
m_Items = new List<Item>();
}

To my surprise I still got the same exception. I finally figured out that the problem was the type of Items. It is was an IList<> instead of a List<>. To avoid tying a class to a specific implementation of a list, I usually use an interface, which is good practice in most cases… however, not when you want to do deserialization :).

Code Camp 2008

Op zaterdag 6 september organiseren dotNED, SDN en VBCentral samen Code Camp 2008. Vorig jaar kon ik er helaas niet bij zijn, maar dit jaar zal ik er niet alleen bij zijn, maar ook een sessie doen. Omdat ik heel erg hou van interactie doe ik een zogenaamde Chalk & Talk. Dat is een sessie waarbij interactie met de groep voorop staat en er niet een vooraf vastgestelde agenda is. Het onderwerp van de sessie in Omgaan met data in een Service Oriented Architecture. In een SOA is een service namelijk verantwoordelijk voor een bepaald domein en de data die daarbij hoort. Een join doen met in de database met data van een andere service bijvoorbeeld is uit den boze… of toch niet? Dat zijn het soort vragen die aan bod komen in deze sessie. Hopelijk tot ziens op Code Camp 2008!