Khare, Atul

A .NET Blog

<November 2008>
SuMoTuWeThFrSa
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456


Navigation

Subscriptions

Post Categories



RTM on top of Whidbey Beta2 (and an ode to Code Generation)!!!
Our application was just deployed in production on top of Whidbey Beta2!!! In addition to being a Whidbey success story, our application is a showcase for code generation techniques (and the great CodeSmith 2.6). In our DataAccess layer (about 4000 lines of code), a total of 10 lines were written by hand and that too to retrieve DB connection strings from configuration files. If we had been building on top of 1.1, we would have even bigger numbers for autogenerated lines of code) -- Whidbey generics eliminate the need to write code to create specialized collections of objects. In addition, we used xsd schemas to generate partial classes that were later extended using hand written code. If you ask me, creating a XSD file is much easier than defining a class and defining a whole bunch of get / set props (well, arguably the Whidbey IDE makes it trivial, but you get the point). The XSDs were processed using xsd.exe and XsdObjectGen (from MS). Both of these tools generate code from XSD definitions, but they work slightly differently. In addition, we used a couple of small homegrown tools to slightly tweak the output using regex (to change the generated class to "partial" for instance). Also, it's pretty worthwhile to have a tool that generates code intelligently based on some of timestamp mechanism so that build doesn't take a long time.

posted Monday, June 27, 2005 6:22 PM by dotnetruminator with 0 Comments

ASP.NET / COM Interop. puzzle...
This might be rather obvious to quite a few people out there, but it's been a while since I have blogged and there's nothing like getting a kick start. There’s a legacy COM object called Foo with a method called Enum(). Basically, Enum() enumerates certain things based on a user’s Windows identity and returns the result. For example say Enum() returns x,y,z for UserA and d,e, f for UserB. You write a small standalone program to test Enum() under different user identitities and everything works just fine, i.e., it returns values that that pertain to UserA and UserB. You create a web site and that web site uses integrated Windows authentication and impersonates the client (impersonate=true in web.config if you insist on details). You verify that impersonation is working correctly this by printing the user’s Windows identity from the web page. However, when you execute the same code on the server side in the context of UserA or UserB, the COM component doesn’t work as expected, i.e., it doesn’t return the right result either user. What’s happening here?

posted Tuesday, February 22, 2005 2:02 PM by dotnetruminator with 6 Comments

Whidbey System.Data.SqlClient.SqlConnection bug...
The Whidbey System.Data.SqlClient.SqlConnection doesn't handle connections on non default ports correctly. Basically, if you create a DB on a SQL 2000 server, but host it on a non default port, say 3180, the GetConnection() method throws a SqlException with the following message : "Unknown Provider Connection String is not valid". Check bug FDBK17272 on the Whidbey feedback site for more details. The workaround for the problem is to prefix the server name in the connection string w/ tcp:. Atul

posted Wednesday, November 10, 2004 9:57 PM by dotnetruminator with 6 Comments

UnhandledExceptionEventHandler quirk...
Managed code programs can use AppDomain.UnhandledExceptionEventHandler to trap unhandled exceptions and it works great. However, there's an interesting quirk that might be of interest in situations where your managed code assembly (DLL) might be used inside an unmanaged process. It appears that for some reason, this event is NOT fired if an managed code exception is thrown inside an unmanaged process. Come to think of it, it kind of makes sense because the CLR needs to walk the entire call stack to find if an exception handler is in place and fire the event only if no exception handler is found. My guess is that the stack walk terminates if an unmanaged code frame is detected and the exception is swallowed. Just out of curiosity, is this behaviour by design?

posted Wednesday, November 10, 2004 9:19 PM by dotnetruminator with 4 Comments

Win32 threads vs. Thread gotcha (and a little GC surprise)....

During a recent code review, the following piece of C# code set off a red flag:

void CreateAThread()
{
Thread NewThread = new Thread(...);
...//Assign ThreadStart etc...
NewThread.Start(); //Long live the thread...
}

The intention here is to create a new thread that will live till the process terminates. Come to think of it, such code would make perfect sense to someone who comes from a C++ background.

For example, consider the following C++ code:
void CreateAThread()
{
HANDLE ThreadHandle = CreateThreadEx(.....); //Call Win32 API to create a thread....
CloseHandle(ThreadHandle);
}

In the C++ case, the thread continues to run after return from the function.

However, in the managed world, Thread is just another object and therefore NewThread is a reference that a prime candidate for GC. So, what happens when the GC collects a Thread() object? My guess was that the actual OS thread would be terminated by the Finalizer().

To confirm my suspicion, I stepped into the code with a debugger and called GC.Collect() after exiting from CreateAThread(). Interestingly enough, the thread continued to run even after GC.Collect()!!! Is this because the GC has some buit in checks for such special type of objects? In any case, I think that it's bad practice to rely upon GC behaviour and it's imperative to assign the Thread reference alive for the lifetime of the thread. What do you folks think? Atul

posted Saturday, October 09, 2004 11:21 PM by dotnetruminator with 6 Comments

PInvoke ULONG gotcha...

While doing PInvoke stuff, it's customary to cut and paste stuff from the C++ header file and translate the native types into the corresponding C# types.

However, as I discovered after many hours of debuggging a few weeks ago, looks can be deceptive ;). In Windows programming, it's common to use ULONG (defined in windows.h) instead of unsigned long. Therefore, it must be right to translate ULONG into the ulong managed type, right? The answer is a resounding “no“ -- ulong in the managed world is a full 64 bits, and therefore the correct data type to use is uint.

This is a subtle bug because you can get away w/ using ulong for a long time until it bites you. This is because at runtime, 64 bits will be pushed on the stack instead of 32 and if you have any pointer values (reference types) that follow the ulong parameter, it can result in some strange behaviour that will leave you scratching your head.

In this particular case, the API in question was:

[DllImport("secur32.Dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern int AcceptSecurityContext(ref SECURITY_HANDLE phCredential,
IntPtr phContext,
ref SecBufferDesc pInput,
uint fContextReq,  //managed ulong == 64 bits!!!
uint TargetDataRep, //managed ulong == 64 bits!!!
out SECURITY_HANDLE phNewContext,
out SecBufferDesc pOutput,
out uint pfContextAttr, //managed ulong == 64 bits!!!
out SECURITY_INTEGER ptsTimeStamp);

Since the pointer values were skewed, it resulted in an “address access violation“ type exception in the unmanaged world, which was faithfully translated by the CLR into a runtime “Null Pointer“ (or similar exception) :)....

posted Tuesday, September 07, 2004 11:45 AM by dotnetruminator with 6 Comments

Oh MarshalAs(), where art thou? (new Interop book review)...

Whether or not it has something to do w/ my COM/C++ karma :), I frequently seem to get assigned code that deals with Interop. In any case, I am not complaining because I enjoy that kind of stuff anyway (thanks to Adam Nathan's Bible for saving me a few gray hairs :).

Anyway, while browsing around a few days ago, I was pleasantly surprised to find a new Interop book on the block titled: ".NET Framework Solutions: In Search of the Lost Win32 API" (by John Mueller). I reckoned that at $8 (used on Amazon) it wouldn't be too bad of an investment.

After reading the book, all that I can say is that if you are doing .NET -> Native Interop (PInvoke), this book should pretty have almost all that you need. Note that it does not cover COM (RCW) Interop in that much detail and does not talk about CCW (COM -> .NET). However, the coverage of MarshalAs() and the clever examples that show how to deal with the complex DirectX structures (unions and so forth) are alone worth the price of admission.

What I liked best was the author didn't take the cop out solution (managed C++) unless it was absolutely necessary. Most of the code examples in the book are in C# and this might be of some concern to the VB.NET programmers. The chapters are well organized and there's an appendix with 50+ good tips on PInvoke. If you are still struggling with your PInvoke Interop problem after reading this book, it's time to bring out the heavy weight  -- good luck!!!

 

posted Thursday, September 02, 2004 9:44 AM by dotnetruminator with 6 Comments

Interop fun: SSPI in 100% managed C# code...

Readers might want to reference the SSPI chapter from Keith Brown's excellent online book if they want to obtain more information. Anyway, MS published an excellent article a while ago about how to use SSPI in Remoting.

My only reservation about the article was that some of the code was written in managed C++ and I am a strong advocate of doing everyting in C# as much as possible. Anyway, since it appeared that other people have had trouble with the API, I decided that it would be an interesting exercise to port the C++ portions to C# and use PInvoke :).

The actual code is a little too long to be included here, but if someone's interested, drop me a note a and I will mail the code - it does have a few interesting Interop tricks...

 

posted Wednesday, September 01, 2004 1:38 PM by dotnetruminator with 5 Comments

CodeGen and compile time AOP...

Being a fan of the declarative programming, I have always been fascinated by the idea of AOP (Aspect Oriented Programming), but from the (failed) promise of COM+ interceptors (remember PDC 1999?) to the now deprecated CBOs (Context Bound Objects), it somehow hasn't fulfilled it's promise.  For the uninitiated, the idea is it should be possible to provide certain functionality say for logging or tracing, just by means of an declarative attribute.

For example, instead of writing a typical call to a log or trace function like:

MyMethod()

{

       Trace(“I am in MyMethod();“);

 //Rest of method...

}

we could use something like:

[Trace]

MyMethod()

{

 

 //Rest of method...

}


Granted, it's a trivial example, but aspects can be used to provide more interesting behaviours like Transactions, Post Conditions and Preconditions as well (a la Design by Contract). Indeed, EnterpriseServices used the AutoComplete attribute to automagically provide a transaction context and automatic completion and rollback.

So, if this is such a promising technology, where's the fly in ointment? For one thing, behaviour that's added at runtime can result in a severe performance penalty. Also, there may be “quirks” that may result from the interaction of such runtime behaviours (which may not be compatible w/ each other). In other words, if your software didn't behave as expected, would you blame your code or the “aspects”? And how would one go about debugging it?

If only there were a way to not incur the performance hit and also make it easy to debug the code so that you could actually see what was going on.

I think that's where static or compile time AOP comes into the picture. Watch this space for details...

 

posted Wednesday, September 01, 2004 10:33 AM by dotnetruminator with 6 Comments

Code generation anyone (a pitch for the excellent CodeSmith)?

With all the excellent code generation tools out there, it's really amazing that people still spend a whole bunch of time writing boiler plate code. What am I talking about here?

Let's take a look at a typical three tier web application:

  • Web UI Layer
  • BizFacade Layer
  • Biz Layer
  • DB Access Layer
  • SP


In addition, since some people prefer dealing with objects rather DataSets, there's a Relational -> Object mapping layer that needs to be built. Naturally, where there are objects, there are collections and now we end up writing strong typed (of course) collections for each of those objects.

So, to retrieve and display some data, we had to go through the process of writing the SPs, coding the DB access layer to call the SPs, writing the objects, writing the collections, writing the code that mapped DataSets -> Objects....whew!!!

Is there something wrong with the picture here? Of course there is -- most or all of the things referenced the the above paragraph simply weren't meant to be written by hand. Or, if they were before, now is the time to STOP!!!

Stop making excuses for letting brain dead code hold you hostage and download the excellent (and free!!!)
CodeSmith NOW!!!

posted Wednesday, September 01, 2004 10:14 AM by dotnetruminator with 6 Comments

Whidbey SqlDataSource bug...

The problem is that SqlDataSource does not translate empty parameter string into DbNull.Value DateTime value. This behaviour is different from integers and strings, where an empty string is translated into DbNull.Value. You can check out the details and vote on the bug here .

 

posted Wednesday, September 01, 2004 10:02 AM by dotnetruminator with 5 Comments

Whidbey ASP.NET Literal control bug

For some reason, the ASP.NET Literal control doesn't like calls to server side scripts or Eval statements. Any call to a server side script fails with the following parse time message: 'System.Web.UI.WebControls.Literal' does not allow child controls.

 <%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">
public string CallMe()
{
return ("hi there");
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<% CallMe();%>
<asp:Literal Runat=Server>
<% CallMe();%>
</asp:Literal>
</form>
</body>
</html>

Please vote on this bug:

http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackId=fe629cb4-9345-47fe-8073-817eb9351cc8 

posted Wednesday, September 01, 2004 9:48 AM by dotnetruminator with 6 Comments

Whidbey System.Security.Cryptography enhancements...
 Hi folks,

This is my very first blog entry. Pardon the number of exclamation marks in this post, but I downloaded Beta 1 of VS.NET a few weeks ago and but the improvements in System.Security.Cryptography are simply amazing!!!

Here's a partial list of enhancements (this part is not everyone's cup of Framework :):

  1. X509CertificateEx extends the X509Certificate class and lots of new properties like PrivateKey, Thumbprint, Extended Key Usage etc.
  2. X509Store allows you to browse cert stores and even add and remove certs!!! Well, arguably WSE 1.0/2.0 gave you the browse features, but this is much more!!!
  3. There's complete support for CMS, meaning there's not need to muck around with CAPI for signed / enveloped messages etc.!!! Granted, CAPICOM was easier, but I would rather do things w/o having to resort to a RCW and have to deal with some of the nasty bugs (like Decrypt problems when dealing w/ string data)
  4. Support for ASN1 encoded data!!!
  5. Ability to generate PKCS12/PFX files from certificates!!!

Here's a piece of trivia about X509CertificateEx.Export (from MS)  for people trying to export the entire certificate chain:

Thanks you for the feedback. X509CertificateEx.Export only exports the certificate itself and does not build the certificate chain. It is however possible to export the whole certificate chain with the set of APIs available today: what you could do is build a chain using X509Chain.Build; then get the certificates in the chain by accessing X509Chain.ChainElements. Once you get the collection you want exports, you can call X509CertificateExCollection.Export(). This method is the way to go if you need to export more than one certificate.

Atul

posted Wednesday, September 01, 2004 9:40 AM by dotnetruminator with 6 Comments




Powered by Dot Net Junkies, by Telligent Systems