Thursday, August 21, 2008

Sql Server Paging

We can return only a page from a large query's resultset with the following construct :

SELECT * FROM
(
SELECT Client.*,
ROW_NUMBER() OVER (ORDER BY ClientID) AS RowNumber
FROM Client
) AS NumberedRows
WHERE RowNumber
BETWEEN @StartRowIndex AND (@StartRowIndex + @MaximumRows - 1);

Wednesday, August 20, 2008

Service Request Workload

In order to improve our service's availability, we should put an upper limit on the workload that can be allocated to deserve a single request.

Take for example the real world 411 telephone directory service. The operator is instructed to accept looking up only one phone number for every received call. This is done to keep calls short, and to ensure that everyone gets a chance to be served. You would certainly not like your call to be queued behind Mr Smith's one, who would like to get the phone number of every student from his 1952 high school promotion.

In much the same way, we should design our service interfaces with the implied workload in mind. Maybe we should not return all of the catalog's items at once after all. We could rather require an item category to be chosen, and only return this subset among the original results. Or if such a natural division is not available, maybe our service's interface should include a pagination scheme.

This does not prevent any of our clients to get all the results they need: they stay free to issue as many service requests as they want. But it sure improves the service's availability for the other clients. After all, nothing prevents Mr Smith from getting all the phone numbers he wants by calling 411 all day long, but he won't prevent us from getting the line by hogging the service's resources.

Tuesday, August 19, 2008

Server Message Box

ASP.NET server code can provoke the display of a message box in the client's browser by registering a client script within the page's output. The following example displays a message box when the page is rendered :

string escapedMessage = message.Replace("'", @"\'");
string script = String.Format("alert('{0}');", escapedMessage);
this.ClientScript.RegisterStartupScript(typeof(Page), "MessageBox", script, true);

Sunday, August 17, 2008

Asynchronicity Theory

Asynchronicity implies multithreading. While working in our restaurant's kitchen, we notice that we are running short on milk. Not having the time go and get more from the corner grocery store, we ask our boss boy to do it for us, and instruct him to store the milk in the refrigerator when he gets back. We are now two persons doing work for the kitchen, in the same way as if we had spun off a worker thread to call a lengthy method asynchronously.

Multithreading requires synchronization. We are now preparing sophisticated deserts for tonight's dinner. As soon as one is completed, we cautiously store the precious creation in the refrigerator. As we place one on the bottom shelf, our boss boy gets back from the grocery store, and drops the milk we asked him on the same shelf. Ouch, one desert less... maybe we should avoid using the refrigerator simultaneously next time.

The moral of this story: Asynchronous callbacks are serious stuff, as they imply the utilization of multiple threads, and the synchronization of the resources accessed by these threads.

WFC Automatic Synchronization

If automatic synchronization is activated with ConcurrencyMode.Single, a service instance is locked by WCF when it is asked to perform an operation. This prohibits other worker threads to enter this service instance, and thus provides thread-safety to the service's code by serializing the client requests.

Automatic synchronization works for service instances because the only threads to access them are WCF's worker threads, and these are disciplined to set the lock as required. Unluckily, this might not work for the client callback objects, because they can also be accessed by non-WCF threads being unaware of this locking scheme.

As a rule, callback objects cannot solely rely on WCF automatic synchronization for their thread-safety, and need to provide their own manual synchronization.

Saturday, August 16, 2008

UI Synchronization Context

The controls provided by Windows are not designed to be thread-safe; they are intended to be accessed only the by thread which created them, namely the UI thread. But that UI thread is engaged in an endless loop, waiting for and dispatching the messages sent to its windows, and will therefore never be available to do anything else. How then can a worker thread interact with the user interface if it cannot safely access the controls by itself, and if the only thread allowed to do so will never get available ?

In Windows Forms, this problem is addressed by WindowsFormsSynchronizationContext. Any method call sent to this context is automatically translated into a Windows message, which is then posted to the UI thread's message pump. Eventually, the UI thread processes this message, and executes the requested method. That is how a worker thread can get the attention of the UI thread, and have it safely access the user interface controls on it's behalf.

Synchronization Contexts

An object may require to be accessed only by a predefined set of threads. Maybe these threads have some required information attached to their local storage (TLS), or maybe synchronized access to the object is ensured by limiting access to a single thread.

A synchronization context may be used to act as a proxy between the outside world's threads and the synchronized object. The synchronization context intercepts incoming calls, and redispatches them to one of the allowed threads.

This design pattern requires the synchronized object to publish it's synchronization context, and it's users to access the object through this context. Alternatively, the synchronized object could redirect all incoming calls to it's synchronization context by itself, thus encapsulating this requirement.

SyncObject syncObject = CreateSyncObject();
SynchronizationContext syncContext = syncObject.GetSynchronizationContext();
SendOrPostCallback methodCall = new SendOrPostCallback(syncObject.DoWork);
syncContext.Send(methodCall, someObjectParameter);


Synchronized objects then need to know which context they belong to. This context could be defined by the synchronized object itself when it is created, or if the object is known to be created from one of the synchronization context's threads, the object can get this information by calling SynchronizationContext.Current from it's constructor.

Sunday, August 10, 2008

Transactional Instance Management

As a best practice, use per-call instancing for transactional services. Every instance is disposed after method calls, no matter whether the transactional resources are committed or aborted much later depending on the outcome of the distributed transaction. This ensures that no instance is left with an invalid memory state because of a potential rollback.

This behaviour is even enforced by WFC for per-session instancing. Whenever an instance completes a transaction, either explicitly or declaratively, the instance is disposed of. Note that the distributed transaction may commit or rollback later on. This behavior is ensured by the ReleaseServiceInstanceOnTransactionComplete service behavior, which defaults to true for SessionMode.Required services.

When set to false, ReleaseServiceInstanceOnTransactionComplete will ensure that the per-session instances survive their client's transaction boundaries. This is perilous, since a client rollbacking it's transaction would leave the instance in an invalid state.

Another possible solution is to limit the session to a single client transaction by setting the TransactionAutoCompleteOnSessionClose behavior to true, while avoiding completing the transaction between operations by setting the TransactionAutoComplete behavior to false. By avoiding letting the instance live past the transaction's scope, we are sure not to keep an inconsistent memory state should the transaction abort.

Fault Management

Except for FaultException derived exceptions, any exception thrown by a service faults the client proxy, which can the only be closed. All service exceptions are rethrown on the client side as a FaultException.

Detailed FaultException<T> can be defined in a service contract, specifying the type through which the fault details will be provided. These exceptions are rethrown with their details on the client side

For debugging purposes, the IncludeExceptionDetailsInFaults service behavior can be applied to a service, in which case the FaultException<Exception> attribute is automatically provided for the service's operations.

Wednesday, August 6, 2008

Problems with Event Validation

Since ASP.NET 2.0, a check is performed when a page is post back to ensure that all the submitted values are part of the original choices. This would for example prevent someone from spoofing the selection of the item Winter from a list of days. All in all, this is good stuff.

The implementation of this new functionality relies on an hidden field named __EVENTVALIDATION, which is automatically added to the end of our web forms. There are some flaws to this approach, though. In fact, it is possible for a browser to submit a partially received page, for which the validation field has not yet been received. When ASP.NET receives such a post back, it has not basis for comparing the submitted values with the original choices, so it refuses the post back with the "Invalid postback or callback argument" exception.

While waiting for a fix on this functionality :

<script type="text/javascript">
function IsLoaded()
{
return (document.getElementById("__ISLOADED")!=null);
}
</script>

<form onsubmit="javascript: return IsLoaded();">
</form>

<input type="hidden" id="__ISLOADED" value="true" />

Monday, August 4, 2008

Service Requests Managing Associations

The fact that associations are maintained by many-to-many tables in a database is an implementation detail, and this must not affect our service interfaces. Take for example an application which associates clients to different possible types. The following database schema could fulfill these requirements :

Client (1)-(*) ClientType (*)-(1) Type

The services needed to retrieve and update associations between a client and its types should make total abstraction of the ClientType table. Indeed, the GetClientTypes service should accept a ClientID and return a list of types, while the AddClientType and RemoveClientType services should accept both a ClientID and a TypeID.

These are the values which are meaningful to the service users.

Authorized Service Requests

By including the identity of the current user within a service request, we can check for the required authorizations before executing the service. We can even filter out the returned information based on this authorization. For example, the following GetAccountBalance service could return InvalidAccount if the requested account exists but does not belong to the authenticated client.

public class GetAccountBalance
{
/// <summary>
/// The client requesting the account balance.
/// </summary>
public ClientRequestElement Client;
public class ClientRequestElement
{
public int ClientID;
}

/// <summary>
/// The account for which the balance is requested.
/// </summary>
public AccountRequestElement Account;
public class AccountRequestElement
{
public string AccountNumber;
}
}