Sunday, November 2, 2008

Microsoft Tech Days Toronto 2008

Microsoft Tech Days 2008 Toronto was held on Oct. 29 and 30 at Toronto Congress Center. Toronto is the first stop of this Microsoft Canada’s technical education conference series, which will go on to Montreal, Ottawa, etc across Canada in the next 3 months. As a developer working with Microsoft technologies, I had a chance to participate in this 2-days event and attended several training sessions for Windows developer and Web developer, even one for database.

The big difference for this event was that it was no longer for free. You need to pay $499.99 (early bird discount $249.99) for the admission. Microsoft said it was not free because this event targeted at education not marketing purpose. Moreover, attendees can get a Tech Days learning kit worth about $1000 (if it is really valuable for you), including a full version of Visual Studio 2008 Professional.

Although Microsoft stated that this event was not a marketing tour, most of the sessions were about new technologies, even some latest versions being launched 2 days ago. From my communication with other developers, I could see most of the developers and companies were just watching those new stuff. Companies are very carefully to take a stand on a new technology because that means a lot of investments and less support, and you cannot rely on a stable version in quite a while.

The good thing for Microsoft was although this was not a free event, it still allured so many people, over one thousand by estimate, to flock together to enjoy the new technologies and collect new information.

Let’s talk about the sessions. Among the 8 sessions I attended, including 4 for Windows development, 3 for Web development and 1 for data management, some of them were pretty impressive. For instance, “Mastering Your Samurai Skills of Silverlight” not only showed the great features of the latest version of Silverlight and what beautiful stuff the tools could build, but demonstrated the simple start-up process a beginner can take. Some sessions about WPF, such as one from MVP Barry Gervin, were attractive as well. The presentations were well prepared and most of the speakers had rich experience and good presentation skills.

As it was told, most of the speakers were not from Microsoft, but from other companies. That is good in that it could bring the audience real experience. However, this cannot guarantee good quality. To be honest, not all presentations were worth the money and time you spent.

Later on we will plan our next software version. I hope what we got from the conference could help us make a good choice.

Wednesday, October 8, 2008

WCF Service: support transaction and IIS in an intranet environment

Currently I am working on a web project whose data access layer is separated as a standalone WCF service. Both the web server and WCF service are in the same intranet environment and we use Windows integrated authentication to verify users in a domain, so the security issue is not that critical. An additional requirement is that WCF service needs to know the client credential which logs in the web application and store that information into database for later audit. So the web server should pass over the client credential to the WCF service.

I use IIS to host my WCF service and web application. The WCF service and web application could be on different computers. In IIS I set my web application to use Windows integrated authentication, so users have to provide their domain user name and password to access the web application.

basicHttpBinding with “TransportOnly” security setting

In this situation, I simply use basicHttpBinding with the security setting “TransportOnly” and it works well. Here is the relative server configuration code:
<basicHttpBinding>
<binding name="basicBinding">
<security mode = "TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>

I use the following code to get the user name in the WCF service:
string user = System.ServiceModel.OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;

The client configuration code is the following:
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService" >
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" realm="" />
</security>
</binding>
</basicHttpBinding>

The code works well getting the user name in a Windows domain from a client.

Drawbacks of basicHttpBinding

Despite the obvious disadvantage in security, we still can make do with basicHttpBinding since all our applications are in an internal Windows domain. Another fatal weakness, however, forced me to transfer from basicHttpBinding to wsHttpBinding. basicHttpBinding doesn’t support Transaction! I have a business mode that I need to call different WCF functions several times and all the calls should be within one transaction.

In .NET framework, we usually use TranscationScope to automatically manage transactions, especially in a distributed environment. WCF supports transaction, and provides many relative classes and attributes. However, all of them are not working with basicHttpBinding.

wsHttpBinding with transaction support

wsHttpBinding can have different security setting. There are many good blogs we can find in the internet. If we use Transport security with wsHttpBinding, we actually use SSL/TLS over HTTP, that is, HTTPS. We cannot use HTTP prefix in this situation. Transport is good for point-to-point scenarios, but in end-to-end scenarios where we have intermediaries existing, we should go for Message security.

The following is what I changed to my basicHttpBinding source code.

1. Install a certificate in WCF for transport security to support HTTPS. Transport security needs SSL, so we have to install a server certificate first.

2. In server side, the configuration is like this:
<wsHttpBinding>
<binding name="wsBinding" transactionFlow="true" >
<security mode = "Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>

<serviceBehaviors>
<behavior name="DBService.Service1Behavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
<serviceCredentials>
<serviceCertificate storeName="My" findValue="CN=localhost"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>

3. In WCF service source code, add attributes in several places:

In the service interface:
[ServiceContract()]
public interface IMyService
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
bool UpdateData(AInfo info);
}

In the implementation class:
[ServiceBehavior(TransactionAutoCompleteOnSessionClose = true,
ReleaseServiceInstanceOnTransactionComplete = true,
TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable,
TransactionTimeout = "01:00:00",
InstanceContextMode = InstanceContextMode.PerSession)]
public class MyService : IMyService
{
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public int UpdateData(AInfo info)
{
return 1;
}
}

4. The client configuration code is like this:
<wsHttpBinding>
<binding name="WSHttpBinding_IAssayService" closeTimeout="00:01:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
bypassProxyOnLocal="false" transactionFlow="true" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="1000000"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<security mode="Transport">
<transport clientCredentialType="Windows" realm="" />
<message clientCredentialType="UserName" negotiateServiceCredential="false"
algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>

5. The client source code looks like this:
TransactionOptions options = new TransactionOptions();
options.Timeout = new TimeSpan(1, 0, 0);
MyServiceClient client = new MyServiceClient();
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options))
{
client. UpdateData (source1);
client. UpdateData (source2);
client. UpdateData (source3);
}

Now I can call my service function any times. All the operations will be rolled back if any of them fails.