Wednesday, June 16, 2010

C# Puzzle No.20 (intermediate)

Suppose you are writing a class for a generic vector and you want to naively implement a method to add two vectors:

public class Vec<T>
{
    public T x { get; set; }
    public T y { get; set; }
 
    public Vec() { }
    public Vec( T x, T y ) { this.x = x; this.y = y; }
 
    public static Vec<T> Add( Vec<T> v1, Vec<T> v2 )
    {
        return new Vec<T>( v1.x + v2.x, v1.y + v2.y );
    }
}

This won’t work. The compiler is unable to interpret the “+” for type T so v1.x + v2.x cannot be compiled.

One of possible approaches could be to restrict possible Ts with a type constraint so that “+” can be replaced with a method of an interface implemented by T. Such approach, however, does not take you anywhere since you cannot impose an interface on an existing type and thus, Vec<int> or Vec<double> would still fail to compile.

Another common approach is to define an auxiliary interface:

public interface IAdder<T>
{
    T Add( T t1, T t2 );
}

so that Vec::Add can be now implemented as:

public static Vec<T> Add( Vec<T> v1, Vec<T> v2, IAdder<T> Adder )
{
    return new Vec<T>( Adder.Add( v1.x, v2.x ), Adder.Add( v1.y, v2.y ) );
}

and used:

public class IntAdder : IAdder<int>
{
    public int Add( int t1, int t2 )
    {
        return t1 + t2;
    }
}
 
class Program
{
    static void Main( string[] args )
    {
        Vec<int> v1 = new Vec<int>( 4, 5 );
        Vec<int> v2 = new Vec<int>( 6, 7 );
 
        Vec<int> v3 = Vec<int>.Add( v1, v2, new IntAdder() );
 
        Console.ReadLine();
    }
}

While this works, there are obvious drawbacks – an extra implementation of the auxiliary interface has to be provided for any T you want to use your Vec class with. Also, the signature of the Add method is now rather clumsy.

Let’s then just start again:

public class Vec<T>
{
    public T x { get; set; }
    public T y { get; set; }
 
    public Vec() { }
    public Vec( T x, T y ) { this.x = x; this.y = y; }
 
    public static Vec<T> Add( Vec<T> v1, Vec<T> v2 )
    {
       // ???
    }
}

Your goal is to provide valid implementation of the Add method so that the returning vector is a sum of two provided vectors and the generic class works for built-in numeric types. You are not allowed to use reflection (or any BCL API) but rather depend solely on the features of the C# language.

Thursday, June 10, 2010

DevExpress XPO – a support for LINQ’s Skip is finally there

A lack of support for LINQ’s Skip has been a huge drawback of the XPO implementation. I am glad to confirm that Skip is finally there. I test it with Microsoft SQL Server 2008 where Skip is evaluated using row_number. For example, a simple query:

new XPQuery<D_Grupa_Roli>( Global.Model )
    .Where( o => o.Oid > 0 )
    .OrderBy( o => o.Nazwa )
    .Skip( 2 )
    .Take( 3 )
    .ToList()
    .ForEach( rola => Console.WriteLine( rola.Nazwa ) );

is evaluated as

exec sp_executesql 
   N'select resultSet.F0, resultSet.F1, resultSet.F2, resultSet.F3, resultSet.F4, resultSet.F5, resultSet.F6 
     from(select N0."OID" as F0, N0."ModifyDate" as F1, N0."ModifyUser" as F2, N0."ID_GLOBAL_DICT" as F3, 
                 N0."Nazwa" as F4, N0."OptimisticLockField" as F5, N0."GCRecord" as F6, 
                 row_number() over(order by N0."Nazwa" asc) as ''rowNumber'' 
         from "dbo"."D_Grupa_Roli" N0
         where (N0."GCRecord" is null and (N0."OID" > @p0))) resultSet 
     where resultSet.rowNumber > 2 and resultSet.rowNumber <= 2 + 3',N'@p0 int',@p0=0

What’s interesting is that skipping throws an exception for an unordered query:

new XPQuery<D_Grupa_Roli>( Global.Model )
    .Where( o => o.Oid > 0 )
     //.OrderBy( o => o.Nazwa ) ordering is missing
    .Skip( 2 )
    .Take( 3 )
    .ToList()
    .ForEach( rola => Console.WriteLine( rola.Nazwa ) );
and the exception says “Can not skip records without ORDER BY clause.”

If you think about it, that sounds reasonable as the row_number requires an explicit order.

How’s that possible then that Linq2Sql will not throw an exception for such query? Well, it seems that if the ordering is missing from the query tree, Linq2Sql will …………… .

I am sure the curious reader will find the answer on his/her own.

Wednesday, June 9, 2010

DevExpress XPO – Deferred Deletion

One of the interesting features of XPO is the Deferred Deletion. Basically, instead of physically removing rows from your database, XPO marks them as deleted. Not only this can speed up the deletion but also helps to avoid some subtle concurrency issues.

One of our critical applications uses XPO as the ORM engine. As rows are deleted from the database, I never run a Purge mechanism which is designed to physically remove rows marked as deleted. My intention is simple – because all rows are kept in my database, I can always track any changes made by an end user. Even when a row is deleted, I can always peek into the database and conclude “you see, it’s not that our application deletes your data, in fact it’s been Mr.X/Mrs.Y who deleted it” (I mark every single row with the name of the last user who modifies the record).

There’s unfortunately an inconvenient issue with Deferred Deletion. Suppose you have a class (the class code has been simplified):

public class Person {
public int Oid { get; set; } // primary key
public string Name { get; set; }
public int ID_CITY { get; set; } // foreign key
}
and you delete an instance from the database.
Instead of just marking the GCRecord (a marking column in the database) as deleted, XPO also clears all foreign keys for such row! This is explained in the Remarks section of the documentation:

When a child object of a one-to-many association is deleted, XPO clears its reference to a parent object. This object remains orphan when restored. This behavior is by design, because the Deferred Deletion feature is not intended for the object restoration, but for overcoming complex foreign index constraints at the database level.


What does it mean?

Well, suppose you have a row in your database (NULL, 1, ‘The name’, 1) : (GCRecord, Oid, Name, ID_CITY). When XPO “deletes” it, the row becomes (11442123, 1, ‘The name’, NULL). The GCRecord column marks the row as deleted (with a random not null value) but in the same time the reference to the parent row is cleared.

How that’s possible – you ask – if the ID_CITY has the int type? Well, it does not matter whether you have int or int? in your model, XPO will always create a reference column as INT NULL (sic!).

Ok. So far, so good. Since Deferred Deletion is not designed to restore rows, it may not matter that the record has been altered in a way that it becomes an orphan (parent reference is gone!).

But now, you have a problem if you ever try to access such deleted record (and XPO allows that!) – your model insists that the ID_CITY has an int type, while the database holds a NULL value. XPO is then unable to create an instance of your business class.

Possible solutions?

First solution could be to alter your business classes so that all reference fields would always be of type int?. This does not seem acceptable, since it’s you to decide wheter a reference is required (int) or can be empty (int?) and XPO should not force you to stick with the only possibility.

Second, which works for me is to change the way you handle such reference properties in your business classes. It seems that before a query is sent to the database to update the GCRecord, XPO automatically invokes the setters of all reference properties (and sets them to null). Let’s then change the setter to handle this:

public class Child {
public Parent TheParent
{
get { ... }
set
{
// add this to prevent setting NULL value for your reference property
if ( this.IsDeleted ) return;
...
}
}
}

A remark - XPO claims that the Skip operator is implemented now. I’ll confirm that and write a note.

Monday, May 24, 2010

How to programmatically configure SSL for WCF Services

One of the issues with WCF is that is heavily depends on declarative configuration. In case of the SSL protocol, a basic ASP.NET WebService supports it “out-of-the-box” if the web server supports it. But a WCF service configured for noSSL calls will not accept SSL calls without an extra configuration. This article describes the issue and the ability to configure the service programmatically to lower the risk of misconfiguration.

Static configuration of WCF endpoints

Let’s start from a basic configuration of a service configured for noSSL calls:

<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding1">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SilverlightApplication13.Web.Service2Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="SilverlightApplication13.Web.Service2Behavior"
name="SilverlightApplication13.Web.Service2">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpBinding1" contract="SilverlightApplication13.Web.Service2">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>

As you can see I have a single endpoint with security mode set to None which corresponds to noSSL mode. With such static configuration the SSL is not a problem. You just define an extra endpoint with proper settings (mode set to Transport):
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding1">
<security mode="None" />
</binding>
<binding name="basicHttpBinding2">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SilverlightApplication13.Web.Service2Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="SilverlightApplication13.Web.Service2Behavior"
name="SilverlightApplication13.Web.Service2">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="basicHttpBinding1"
contract="SilverlightApplication13.Web.Service2">
</endpoint>
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="basicHttpBinding2"
contract="SilverlightApplication13.Web.Service2">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>

However, there are two issues here.

First, note that both endpoints has empty value of address attribute. This won’t work. The second endpoint’s address has to be manually configured. For example:

<services>
<service behaviorConfiguration="SilverlightApplication13.Web.Service2Behavior"
name="SilverlightApplication13.Web.Service2">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="basicHttpBinding1"
contract="SilverlightApplication13.Web.Service2">
</endpoint>
<endpoint address="https://myhost.com/service1.svc" binding="basicHttpBinding"
bindingConfiguration="basicHttpBinding2"
contract="SilverlightApplication13.Web.Service2">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>

It means that everytime you expose your service under different address, you have to reconfigure it in web.config.

But having two endpoints with different bindings stops your service from working with the Visual Studio Integrated Web Server since it does not support the SSL protocol (you’ll get the exception from the integrated webserver saying that SSL is not supported).

The simplest solution for both issues is to have a two sets of configuration files. One used with the development environment would have a single endpoint for noSSL calls. The other one used in a production environment. However, having few or few dozens of services means that there’s a risk of the misconfiguration, revealed only in the runtime.

Creating endpoints dynamically

The other option however would be to create endpoints dynamically depending on the environment. This way no static configuration is required and the service would expose a single noSSL endpoint when working with the Integrated WebServer and two endpoints (SSL/noSSL) when deployed onto the IIS.

I have found few articles on the dynamic configuration of self-hosted WCF services, however it has been much harder to find a way to do it with the IIS.

To have your service configured dynamically, you start with the *.svc file to change the way the IIS initializes your service:

<%@ ServiceHost Language="C#" Debug="true" 
Service="SilverlightApplication13.Web.Service2" CodeBehind="Service2.svc.cs" %>

and you change this to point to a factory class responsible for creating instances of your service:

<%@ ServiceHost Language="C#" Debug="true" 
Factory="SilverlightApplication13.Web.Service1Factory" CodeBehind="Service1.svc.cs" %>

and you provide the implementation of the factory:

public class Service1Factory : ServiceHostFactory
{
public override ServiceHostBase CreateServiceHost( string constructorString, Uri[] baseAddresses )
{
ServiceHost serviceHost = new ServiceHost( typeof( Service1 ), baseAddresses );

// create the noSSL endpoint
serviceHost.AddServiceEndpoint( typeof( Service1 ), new BasicHttpBinding(), "" );

// create SSL endpoint
if ( ExposeAsSSL )
serviceHost.AddServiceEndpoint(
typeof( Service1 ),
new BasicHttpBinding( BasicHttpSecurityMode.Transport ) ,
baseAddresses[0].ToString().Replace( "http", "https" ) );

// Enable HttpGet for the service
ServiceMetadataBehavior metadata = new ServiceMetadataBehavior();
metadata.HttpGetEnabled = true;
serviceHost.Description.Behaviors.Add( metadata );

return serviceHost;
}
}

[ServiceContract( Namespace="http://www.test.com/test" )]
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple )] //please refer to the docs for more info on these values
public class Service1
{
[OperationContract]
public string DoWork( string Param )
{
return Param;
}
}
Note that there’s just a single ExposeAsSSL variable which has to be configured somehow but the risk of misconfiguration is much lower.

Wednesday, May 12, 2010

System.Windows.Forms.Timer vs System.Timers.Timer/System.Threading.Timer

There is an obvious difference between System.Windows.Forms.Timer and System.Timers[System.Threading].Timer – the former is handled with Win32’s WM_TIMER message and thus it needs a message loop which usually means you need a Windows application.

But there’s also a much less obvious difference – and this difference is the reason to write this entry.

Suppose you set your Windows.Forms timer to 50 miliseconds and then a single Tick lasts a little bit longer:

// execute the Tick every 50 miliseconds
private void timer1_Tick( object sender, EventArgs e )
{
     this.richTextBox1.Text += DateTime.Now.ToString() + Environment.NewLine;
     
     // but a single Tick lasts longer
     Thread.Sleep( 1000 );
}

What happens then? You see, a WM_TIMER message is constrained by the system so that is never occurs too often. It means that the message queue will not be flooded with extra messages and you are safe. In the above scenario, the RichTextBox would be updated once for a second, even if the timer is set to launch every 50 miliseconds.

But the case is completely different with the two latter timers! The operating system launches a new thread with every tick so that you are not safe from having multiple ticks running in the same time.


static void Main( string[] args )
{
    System.Threading.Timer t = new Timer( timer_callback, null, 0, 50 );           
 
    while ( true ) { }
}
 
static void timer_callback( object state )
{
    Console.WriteLine( DateTime.Now.ToString() );
    Thread.Sleep( 1000 );
}

Run the above code snippet to see that the console is actually flooded with messages arriving independently much ofter than you’d expect. This time it’s important then to manually handle the flooding:

static void Main( string[] args )

{
    System.Threading.Timer t = new Timer( timer_callback, null, 0, 50 );           
 
    while ( true ) { }
}
 
static bool worksNow;
 
static void timer_callback( object state )
{
    // exit if in the middle of action 
    if ( worksNow ) return;
 
    try
    {
        // disable temporarily
        worksNow = true;
 
        Console.WriteLine( DateTime.Now.ToString() );
        Thread.Sleep( 1000 );
    }
    finally
    {
        // make sure that the handler is always reenables
        worksNow = false;
    }
}

There’s still a small issue with such approach. This time, when the timer interval is only a fraction smaller than the time of the action, every second tick of the timer will exit because of the value true of the guarding worksNow variable but then there will be a long period of inactivity before next timer’s tick. You’d rather like the timer to resume the work immediately after the handler completes.


static void Main( string[] args )
{
    System.Timers.Timer t = new System.Timers.Timer( 50 );
 
    t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
    t.Start();
 
    while ( true ) { }
}
 
static void t_Elapsed( object sender, System.Timers.ElapsedEventArgs e )
{
    System.Timers.Timer Timer = 
        (System.Timers.Timer)sender;
 
    try
    {
        // disable temporarily
        Timer.Stop();
 
        Console.WriteLine( DateTime.Now.ToString() );
        Thread.Sleep( 1000 );
    }
    finally
    {
        // make sure that the handler is always reenables
        Timer.Start();
    }
}

The only subtle issue here is that, as you’ve probably noticed, there does not seem to be an easy way to stop/start System.Threading.Timer, so I had to switch to System.Timers.Timer.

Complete list of different timers with their profiles is available on the MSDN Magazine.

Tuesday, April 13, 2010

ASP.NET Forms Authentication Sharing for Silverlight/WCF applications

Over two years ago I’ve blogged on how to share the forms authentication between ASP.NET and ClickOnce applications. We use this technique often for it’s just convenient to have just one, centralized authentication mechanism (ASP.NET Membership Provider in this case) in large modular systems.

In just few words – that sharing is possible by passing a Forms authentication cookie to the ClickOnce application as an Uri parameter and append the cookie to the CookieContainer of a webservice proxy class. This way all requests from the ClickOnce application back to the server (which pass through the FormsAuthenticationModule) are correctly recognized as authenticated and in the same time an exception is thrown in case of a missing or invalid authentication cookie. On the server side – web service methods are guarded with the PrincipalPermission attribute. Please, refer to the article for more details.

As we finally add Silverlight to our daily toolbox, I strongly needed a corresponding mechanism for WCF Services and Silverlight proxies. I need to share the Forms authentication between my ASP.NET hosting application and the Silverlight application users run after they login to the ASP.NET application.

What seemed to be a piece of cake, has turned out to be tricky, mostly because of the way in which exceptions are passed between the server and the Silverlight at the client side.

Guarding WCF calls with PrincipalPermission – an easy step

The first step is easy. Since Silverlight is hosted in web browser, there’s no need to copy cookies as cookies are appended automatically to WCF service calls (assuming that both hosting application and hosted Silverlight come from the same domain but this is usually the case). Assuming then that users need to login first using Forms authentication and then they get access to the Silverlight application, whenever the Silverlight calls back the WCF on the server, Forms authentication cookies are there.

So I just happily put PrincipalPermission over my WCF methods but unfortunately no matter whether I logged first or not, I got an exception all the time. It seems that WCF needs an few additional spells to be casted for this to work (and these spells was not needed for ASP.NET WebServices):

  • an additional AspNetCompatibilityRequirements attribute over the WCF class
  • setting Thread.CurrentPrincipal in the WCF constructor
[ServiceContract( Namespace = "http://my.namespace.com/service1" )]
[AspNetCompatibilityRequirements( RequirementsMode = AspNetCompatibilityRequirementsMode.Required )]
public class Service1
{
public Service1()
{
/* this line is crucial for PrincipalPermission to work */
Thread.CurrentPrincipal = HttpContext.Current.User;
}
... WCF methods follow ...





  • forcing the runtime to use ASP.NET compatibility mode for WCF (web.config)




...
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
...
</system.serviceModel>





Having all these prepared, I can safely guard my WCF business methods with PrincipalPermission attribute and exceptions are thrown back to the client in case of unauthenticated users.




...
public class Service1
{
[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
public int DoWork( int i )
{
return i;
}


Detecting the Forms Cookie timeout – a slightly more difficult step





Unfortunately, I cannot stop at this point. This is because Forms Authentication cookies do timeout. For ASP.NET application this is not a problem – the FormsAuthenticationModule just redirects the call to the LoginPage so users just relogin. For ClickOnce/WebService – I can catch SOAPExceptions, take a look at the Message and check whether it says something about PrincipalPermission. If this is so, I can relogin my users with an additional unguarded Web Service method which just reappends valid Forms Authentication cookies to the proxy’s cookie container.



In my WCF/Silverlight scenario, the timeout of the Forms cookie is a disaster. All consecutive WCF requests still contain the Forms cookie but the cookie is not valid anymore and the PrincipalPermission attribute causes these calls to fail. An exception from the inside of server’s runtime environment is returned to the client as just “The remote server returned an error: Not found”. My chance to detects the actual cause of the exception is zero. “Not found” does not mean “Your cookie has just timed out!”.



What I need is to use two independent mechanisms:




  • I have to catch principal permission issues explicitely on the server so that …


  • … I can explicitely pass it to Silverlight and catch on the client side



Let’s start from the latter, since it’s more obvious – there’s an explicit way of passing exceptions from the server to Silverlight using FaultContract.



FaultContract is an attribute on my service class with tells WCF how to pass exceptions to the client.



The former can be achieved by using an imperative way of permission demanding – rather than using PrincipalPermissionAttribute, we will use the PrincipalPermission and call it’s Demand method so that we can catch the exception of the server side, wrap it into the FaultContract and send it to the client.



Let’s start from the FaultContract at the server side:




/* note that this does not inherit from the Exception class ... */
[DataContract]
public class MyException
{
[DataMember]
public int Code { get; set; }
[DataMember]
public string ActualException { get; set; }
}

[ServiceContract( Namespace = "" )]
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Required )]
public class Service1
{
public Service1()
{
Thread.CurrentPrincipal = HttpContext.Current.User;
}

[OperationContract]
/* ... because this is the FaultContract which inherits from Exception */
[FaultContract( typeof( MyException ) )]
public int DoWork( int i )
{





Inside our business method we have to check if the call is authenticated and if not – we wrap it in a FaultException instance.



There’s still one caveat however – MSDN claims that in Silverlight, FaultContracts have to be handled using a WCF Behavior Extension due to some limitations of the web browser’s stack. Fortunately, someone has pointed that much simpler way – I just need to cast a single-line spell inside the business method so that exceptions are passed with 200 OK instead of 500 Internal Server error and the FaultContract can be consumed at the Silverlight’s client side:




[OperationContract]
[FaultContract( typeof( MyException ) )]
public int DoWork( int i )
{
/* a powerfull spell so that I do not need a WCF
Behavior Extension as MSDN says
*/
System.ServiceModel.Web.WebOperationContext
.Current.OutgoingResponse.StatusCode =
System.Net.HttpStatusCode.OK;

/* Check for principal permissions explicitely rather than
using the attribute */

/* I do not need any special username/role but I need
calls to be authenticated */
PrincipalPermission p = new PrincipalPermission( null, null, true );
try
{
p.Demand();
}
catch ( Exception ex )
{
/* wrap the exception so that Silverlight can consume it */
MyException fault =
new MyException()
{
/* Code = 1 will mean "unauthenticated!" */
Code = 1, ActualException = ex.Message
};

throw new FaultException<MyException>( fault );
}

return i;
}







This is all at the server’s side, let’s go back to the Silverlight client and call the service:




private void Button1_Click( object sender, RoutedEventArgs e )
{
ServiceReference1.Service1Client c = new Service1Client();

c.DoWorkCompleted +=
new EventHandler<DoWorkCompletedEventArgs>( c_DoWorkCompleted );

/* cannot try-catch here as this is an asynchronous call */
c.DoWorkAsync( 5 );
}

void c_DoWorkCompleted( object sender, DoWorkCompletedEventArgs e )
{
/*
Note that e.Error is set whenever an exception is raised from somewhere.
However, this time instead of "Not found." we have the FaultContract passed
to the client.
*/

HandleFaultException( e.Error );

MessageBox.Show( e.Result.ToString() );
}

/* A generic method to handle WCF exceptions */
void HandleFaultException( Exception ex )
{
/* Is it my custom Fault sent to the Client? */
if ( ex is FaultException<MyException> )
{
FaultException<MyException> exception = (FaultException<MyException>)ex;

/* Is the Code == 1? Remember the convention - 1 means "unauthenticated" */
if ( exception.Detail.Code == 1 )
{
/* Do whatever you like but now you know
what's the reason of the exception */
/* You can for example redirect the Silverlight
application to ASP.NET Login page
so that the user relogins and will likely run
the Sliverlight application again */
HtmlPage.Window.Navigate( new Uri( "loginPage.aspx", UriKind.Relative ) );
}
}
}





Happy coding.