August 2008 - Posts
Get Rid of COM+ Application after Migrating to Framework 2.0
Scenario: Let's say that you went to work on an already-in-production system
which started on the old ages on Framework 1.1 (or lower). Back then,
transaction management could only be via COM+ application.
Beside it's advantage (back then...) in transaction management using COM Plus
is a burden for developers and has performance penalty because of inter process
communication between the main process and the DLLHost.exe that runs
the COM Plus.
Moreover, this architecture suffers from maintenance difficulties because you
have to keep at least two .config files, maybe share Dll files, and many other
error possibilities.
Therefore, altohugh COM+ has alot more to offer than only transaction management
(and because we have used nothing but transaction management) after migrating our
system to .Net Framework 2.0 we've decided to use the TransactionScope of
System.Transaction rather than the ContextUtil of System.EnterpriseServices and let
our COM+ application go
The Process:
The code, before the process should look this way:
Class decleration:
[Transaction(TransactionOption.Required)]
public class YourClass : ServicedComponent
Your methods may look like this:
public void UpdateSomething()
{
try
{
//Your code here
ContextUtil.SetComplete();
}
catch(Exception ex)
{
ContextUtil.SetAbort();
}
}
Or, with an AutoComplete attribute, like that:
[AutoComplete]
public void UpdateSomething()
{
//Your code here
}
1. Loose the reference to System.EnterpriseServices (unless you need it
not only for transaction management)
If you do need this reference besides transaction management matters,
you may temporarily loose it and correct only the transaction-related
compilation errors to come.
2. Add reference to System.Transactions
3. Loose the ServicedComponent inheritances and Transaction
attribute for your class.
4. On every method, Insert the using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
block to cover all transaction activities area.
After doing so, your method should be looking like that:
public void UpdateSomething()
{
try
{
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
{
//Your code here
ts.Complete();
}
}
catch(Exception ex)
{
//Do something with the exception
}
}
5. If your transaction managing methods uses ContextUtil.SetComplete() /
ContextUtil.SetAbort() methods you might replace the ContextUtil.SetComplete()
call by ts.Complete() call and erase the ContextUtil.SetAbort() call.
If your method is decorated by an AutoComplete attribute you might
place the ts.Complete call at the end of your TransactionScope block.
6. After your transaction managing assembly is compiled, all calling assemblies
project probably have compilation error, that is because your classes
won't implement IDisposable (implemented by ServicedComponent) anymore,
and therefore you cannot use them in a using(...) block.
Here you have two options:
A. Implement IDisposable yourself.
B. Remove the using(...) block and call them regularly.
Because from now on, these classes will be used on the same process,
you don't have to use the using(...) block and therefore I'd recommend
removing the using(...) block and call them regularly.
This process might take long but it can be done in steps. You can remove
the System.EnterpriseServices reference deal with several classes,
add it back on, deal with calling assemblies compilation errors and so on...
Summary:
If you've used COM+ for transaction management solly Loosing the dependency
on COM+ application is worthwhile, although it is a long process and must be
done with extreme caution. The transaction managing assembly is most of
the times the business layer assembly and needless to say how harmful reckless
changes can be there.
However, If there is one thing my colleges thank me for, loosing the COM+
application it is.

Sending complex typed data from web service to SilverLight client - Part III
On my previous post I discussed the JavaScript mediator part,
Here I'll sum this part which is Serialize the object for the SilverLight
component and operate method inside it to bind the data.
Step 5 - Serialize the data for the SilverLight component
And here is the code converting the objects
function onGettingAllEmployeesSuccess(result)
{
var slEmployees = new Array(result.length);
for (var index = 0; index <result.length; index++)
{
var newEmployee =
{
"FirstName" : result[index].FirstName,
"LastName" : result[index].LastName,
"EmployeeNumber" : result[index].EmployeeNumber
};
slEmployees[index] = newEmployee;
}
//Serialize the employees
var slSerEmployees = Object.toJSON(slEmployees);
//Bind the data on the silverlight component
$get("Xaml1").Content.silverlightManagedCode.BindListBox(slSerEmployees);
}
The method Object.toJSON is taken from the file Prototype.js written by
Sam Stephenson and distributed freely on http://www.prototypejs.org/
And Finally - Let's insert our SilverlLight control into our test page:
...
<asp:Silverlight ID="Xaml1" runat="server"
Source="~/ClientBin/<YourSilverLightProjectName>.xap"
Version="2.0" Width="100%" Height="100%" />
...
Summary: In order to have complex typed data sent from
your server to your Cleint's SilverLight control via JavaScript you
need to do the following:
1. On your SilverLight project code - write a class with data corresponds
to the data you get from your server.
2. Write JavasCript mediator between your page and your SilverLight control
3. Operate method from your page on your SilverLight control to bind
the serialized data received.
I've attached the SilverLight project's code so you can get started
with your server & mediator easily.
AJAX WEB Methods and Daylight Saving Settings
As most of you know, although our computer displayed time moves forward
by an hour on DST period, It's time isn't changing actually, it just moves to
it's neighboring time zone.
This is in order not to change the computer UTC so different DST setting on different
countries won't cause actual time difference between computers.
However, many system administrators doesn't know how to configure correctly
the time zone shift and instead they simply setting the clock forward / backwards by
one hour.
In an hours reporting system which I've developed I came across a side effect of the
phenomenon mentioned above. When reporting a working day hour one of my colleague
has discovered that his report was "shifted" one hour sooner. The cause of it was
combination of wrong DST settings on the customer's site along with right settings on
our company's site.
Well, In order to solve this problem we cannot change the customer's settings (It's a bank,
they cannot change something so fundamental so rapidly...) and we also can't (and won't)
change our company's settings to the wrong ones, what we can do is sending the client's
current date as a parameter so we can "fix" the dates being sent back to it, if needed.
What we basically need to do is send is the current date from our client.
For that meter we will simply call the new Date() function in our client side.
The server, from it's side, will receive it as a UTC date (you can check it by reading it's Kind
property on the server side or simply by checking the date itself while your client and server
are on the same computer.
Now, all you have to do is compare the date received with the server's UTC date and
correct the dates being sent back to the client if needed..
var hoursToAdd = clientDate.Subtract(DateTime.Now.ToUniversalTime()).Hours;
.
.
.
//Correct the hour "Gap"
MoveHour(result, hoursToAdd);
The MoveHour method implementation simply "shift" all the dates sending
back to the client by the "gap" needed. I did not post the implementation
because it differs from one structure to another and it is very simple.
I know I could use the TimeSpan object itself (without it Hours property)
to correct the gap but this was an example for work around the DST
miss-configuration and I used the Hour property to make it clearer.
Note: This solution contains security risk. If you sent sensitive
data and you relay on time stamp, you
cannot use this solution.
Moreover, if you're using your web service with another system
(not a browser to service like in
AJAX) and you're
implementing WS security this solution is not enough.
To sum up: This solution can go where you have no other choice.
We use it simply because we cannot force large organizations to correctly
configure their DST settings. The date being sent from the client is the
client's machine current UTC time and therefore it is easy to compare
with the server's current UTC time. The rest is too easy to write about...