I’ll be presenting a series of talks for Calgary .NET User Group on acquiring your MCAD/MCSD. The series will include test taking strategies, helpful hints, and other useful information you should know about attaining your credentials.


The first in the series will be Tips & Tricks for 70-306/70-316: Developing Windows®-Based Applications.


Date & Time: Wednesday, September 14, 2005, 5:00 PM to 6:30 PM (Registration starts at 4:30pm)
Location: Alberta EUB Building, Training Room-2nd Floor, 640 5th Avenue SW, Calgary, AB


Pre-registration at the user group website is required.


Thanks to everyone who attended. You can find the slidedeck here and the VB.NET polymorphism demo here.

I’ve had this kicking around in my bookmarks for ages, but I thought I’d share…


Have you ever had to diagram in UML using Visio? It’s a painful process. The UML add-in for Visio has a number of deficiencies:



  • Doesn’t support the latest spec (UML 2.0)
  • Even with the spec it supports, it gets some things wrong (e.g. Completely valid UML will show up with red errors around it.)
  • Using it to really design a software system downright hurts*

* Try the following: Create a sequence diagram. Add some objects and method calls between those objects. Realize that you forgot a step. Marquee and move all the method calls down a notch so that you can insert the forgotten method. Guess what? Visio just forgot all the method names previously entered. You have to manually wire-up the method names again. When actually designing a software system, you are constantly re-ordering methods, removing methods, inserting methods, etc. The team that maintains the Visio UML Add-in should really use their own tool for designing version N+1.


You can’t fault Visio completely. It’s a diagraming tool, not a software engineering tool. So how do you stop Visio from pretending to be a software engineering tool and force it to do what it’s good at (being a diagraming tool)? You grab Pavel Hruby‘s UML 2.0 Stencil for Visio. Thank you, Pavel! You’ve made my time with Visio that much more tolerable.


P.S. Some of you might ask, “Why don’t you use a real UML tool like [insert favourite UML tool here]?” I’m a consultant. As a consultant, it’s often hard to convince a client to buy tools and Visio comes free with many versions of Visual Studio. Typically I’ll need to give my client soft copies of any design artifacts in a file format that they can read. Typically that also means Visio. So like it or hate it, Visio is often the lowest common denominator that all developers on a team can use or have access to.


P.P.S. Some of you might be wondering, given my choice, what my favourite UML tool is? Rational Rose, Borland Together, Sparx Systems’ Enterprise Architect, … I’ve tried a lot of different UML tools over the years and while Borland Together is my favourite UML software package, the best UML designer I’ve ever worked with is definitely a large whiteboard and a digital camera. Honestly, if you can’t design good UML on a whiteboard, the software packages aren’t going to help you much.

If you haven’t checked them out yet, take a look at the MSDN Forums. I’ve been assisting with the Forums since they launched earlier this year and was asked to be a MSDN Forums Moderator recently. They were originally launched to answer questions about VS 2005, .NET Framework 2.0, and SQL Server 2005, but have expanded greatly to include questions about most Microsoft development products. My favourite conversation so far was this one. I answered a question about the GC for someone and Chris Lyon, one of the guys on the CLR Team at Microsoft, chimed in with additional information, which started a great back and forth about GC internals. Be sure to check out Chris’ “A Few Good GC Links” to learn more about the GC in the CLR.


Note to Chris Lyon regarding his blog. Subscribed. 🙂

Fantastic! I’ve been selected as a member of the INETA Community Launch Team for Visual Studio 2005 and SQL Server 2005! You want me to talk about cool new features in the upcoming releases? No problemo. The only question is how to cover all the new goodness that we’ll be receiving November 7? I’m sure I’ll find a way. This should be a fun next few months.

Microsoft just completed a DCR (Design Change Request) that rippled through the entirety of .NET 2.0 and will be available in the August CTP. They made Nullables truly null! Why is this a big deal? Consider the following C# code snippet running under Beta 2:


static bool IsNull<T>(T val) {
   return val == null;
}

static void Main() {
   object obj = null;
   Console.WriteLine(“obj is null: {0}”, IsNull(obj)); // Writes “obj is null: True”
   int? i = null;
   Console.WriteLine(“i is null: {0}”, i == null); // Writes “i is null: True”
   Console.WriteLine(“i is null: {0}”, IsNull(i)); // Writes “i is null: False”!
}


What the heck??? I just assigned i the value of null, a direct check confirms that it is null, but my generic method says otherwise. How can this happen? Let’s look at what is actually happening. An int? (which is just syntactic sugar for Nullable<int>) is a value-type. So when we call the generic method, our int? gets boxed. The box around the null definitely exists, which is what val == null is looking at in the generic method. Hence it returns false because the box exists, even though the value in the box is null. When you look at the code though, you don’t expect that. You expect to be examining the value.


The change in the August CTP makes the generic method work as expected for Nullable types, but it required making some fundamental changes to the CLR. Nullables are now intrinsic types and have special rules around how the runtime handles them. For instance, when boxing an int? which is null, a null is put on the heap, not a box containing null. Hence the above code works. You can also unbox any value-type into its Nullable equivalent. From Soma’s blog:


int x = 10;
object y = x;
int? z = (int?)y;   // In Beta 2, this throws an invalid cast exception at runtime  – not pretty


I wanted to say a big thanks to everyone at Microsoft who was involved in this change. It’s always gutwrenching to make such a sweeping change so close to shipping. I can only imagine the person-hours worth of testing that has been required to ensure that this change does not break existing code. Personally I think it’s definitely worth it. Frameworks and languages are easier to use the less baggage you have to carry around in your head. It’s great when things just work. This is an example of having your framework/language match the mental map you have in your head of how the world should work.


You can find some great information about this change on Somasegar’s and Joe Duffy’s blogs.

Microsoft just released a boatload of SharePoint templates for everything from a HelpDesk Dashboard to RFP Management to Change Management and more. 30 new templates in total with both standard SPS and custom versions. All free downloads and customizable to your needs. So if you need to set up a SPS site quickly, it’s worth taking a look.

 


I was asked recently by a colleague whether you could programmatically emit the name/value pairs of parameters in a Reporting Services report without hard-coding them. Seems like a logical thing to do. So I started digging deep into the guts of the Reporting Services object model and was sorely disappointed. I really like Reporting Services, but the object model accessible from within a report just bites. Let me explain.


When you access Parameters in a report from the Report Properties… Code… (or a custom assembly), you are actually dealing with a Microsoft.ReportingServices.ReportProcessing.ReportObjectModel.Parameters object. (The class is located in an assembly Microsoft.ReportingServices.Processing.dll, which is installed by default in C:\Program Files\Microsoft SQL Server\MSSQL\Reporting Services\ReportServer\bin\.) This object exposes a string-based indexer and that’s it!


public class Parameters {
   public Parameter this[string key] {
      get {
         // code
      }
   }
}


You have to know the key (a.k.a. name of the parameter) to retrieve the parameter to get its value. There is no collection support. (i.e. No Count property and integer-based indexer or IEnumerable implementation.) Parameters is derived from System.Object rather than System.Collections.CollectionBase or something equally useful. You cannot use “foreach” or “for” to enumerate through the parameters.


So from within a report, you cannot obtain a parameter list programmatically as far as I can tell. The same applies to ReportItems and Fields. You’re really limited to creating little helper functions rather than being able to programmatically query the state of a report. How disappointing!

While simultaneously mucking around with the Indigo RC1 bits, I decided to upgrade to DasBlog 1.8 RC1 and kick the tires. (If my OS can multitask, why can’t I?) Very easy upgrade with some nifty goodies. Great job on the new release to Scott, Omar, and the rest of the DasBlog team!


I also decided to change my blog layout to the new “Portal”, which mimics the look and feel of Windows SharePoint Portal. Thanks to Johnny Hughes for the new theme.

You have an ASP.NET application running on your Windows Server 2003 and you’re merrily logging events to the Application Event Log (or any event log for that matter). Then you upgrade to Windows Server 2003 SP1 and see something like this:



Security Exception


Description: The application attempted to perform an operation not allowed by the security policy. To grant this application the required permission please contact your system administrator or change the application’s trust level in the configuration file.


Exception Details: System.Security.SecurityException: Requested registry access is not allowed.


Source Error:


An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. 


Stack Trace:


[SecurityException: Requested registry access is not allowed.]
   Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable) +473
   System.Diagnostics.EventLog.CreateEventSource(String source, String logName, String machineName, Boolean useMutex) +443
   System.Diagnostics.EventLog.WriteEntry(String message, EventLogEntryType type, Int32 eventID, Int16 category, Byte[] rawData) +348
   System.Diagnostics.EventLog.WriteEntry(String message, EventLogEntryType type, Int32 eventID, Int16 category) +21
   AspNetTest.WebForm1.Page_Load(Object sender, EventArgs e) in c:\dev\aspnettest\webform1.aspx.cs:23
   System.Web.UI.Control.OnLoad(EventArgs e) +67
   System.Web.UI.Control.LoadRecursive() +35
   System.Web.UI.Page.ProcessRequestMain() +2112
   System.Web.UI.Page.ProcessRequest() +218
   System.Web.UI.Page.ProcessRequest(HttpContext context) +18
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication+IExecutionStep.Execute() +179
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +87


What happened? The problem is caused by Microsoft tightening up security around the event logs in Windows Server 2003 SP1. (See the section entitled “Tighter ACLs on Event Logs”.)Tightening security is a good idea, but logging events to the event log from an ASP.NET application is a rather common thing to do. So how do we re-enable the ability of ASP.NET to write to the event log?


I have seen information on the web, the sources of which shall remain nameless to protect the seriously misled, that basically tells you to modify your ASP.NET process identity in machine.config from machine to system so that your application can write to the event log. What a collosally bad idea! What’s so bad about this? Imagine that you’re going away for holidays and you ask a friend to water your plants. You realize that your friend cannot open the locked front door. So what do you do? You leave the door unlocked for two weeks while you’re away. That way your friend can get in and water the plants. Does this sound reasonable to you? Of course not. You give your friend a key to get into the house.


So how do you give ASP.NET a key to the event log? I’m glad you asked. There is a custom security descriptor on each event log that determines which users can access that particular event log. Where is this custom security descriptor stored? In the registry of course. So fire up regedt32 and browse to the following registry key:


HKLM\SYSTEM\CurrentControlSet\Services\EventLog\{logName}\CustomSD


where {logName} is Application in our case. You should see a string value that looks like:


O:BAG:SYD:(D;;0xf0007;;;AN)(D;;0xf0007;;;BG)(A;;0xf0007;;;SY)(A;;0x7;;;BA)(A;;0x7;;;SO)(A;;0x3;;;IU)(A;;0x3;;;SU)(A;;0x3;;;S-1-5-3)


What the heck is this? It’s Security Descriptor Description Language (SDDL), my dear Watson. SDDL is a text-based (and human authorable, believe it or not) representation of a security descriptor.


What does it mean in simple terms? The first part is some general information about the security descriptor:












O:BA Object owner is built-in administrators
G:SY Primary Group is SYSTEM
D: This is a discretionary access control list (DACL) as opposed to a SACL or audit entry

Next come the access control entries (ACE). I’ll only talk about the fields needed for the custom security descriptor on the event logs. You can find full information about the ACE format here. First is allow (A) or deny (D). Hex number in the middle is a permissions bitmask:















0x1 READ
0x2 WRITE
0x4 CLEAR
0xf000 DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER

Last comes the SID, which has abbreviated forms for most common built-in accounts.


So here are the ACEs:
























(D;;0xf0007;;;AN) Deny everything to Anonymous
(D;;0xf0007;;;BG) Deny everything to Builtin Guests
(A;;0xf0007;;;BA) Allow everything to Builtin Administrators
(A;;0x7;;;SO) Allow read, write, and clear to Server Operators
(A;;0x3;;;IU) Allow read and write to Interactive Users
(A;;0x3;;;SU) Allow read and write to Service Accounts*
(A;;0x3;;;S-1-5-3) Allow read and write to Batch Accounts*

* These two are not an actual groups, but are flags in the security token, which can be configued by local or group security policy.


You’ll notice that Network Service isn’t mentioned anywhere on that list. Simply add (A;;0x3;;;NS) to the end of the list and Network Service will be permitted read and write access to the event log. Note that if you are using impersonation (<identity impersonate=”true” /> in your web.config), the event log access will be done under the credentials of the impersonated user. In this case, you’ll want to permit authenticated users read and write access, which can be done using (A;;0x3;;;AU). You should now be merrily writing to the event logs from your ASP.NET applications with your security intact.


Afterword: After writing this blog post, I discovered that Dominick Baier has a blog entry about the same problem. Dominick is extremely knowledgeable about all things security on the Windows platform. If you haven’t subscribed to his RSS feed, do so now!


Edit: I originally attributed the information on http://www.leastprivilege.com to Keith Brown. I feel so embarassed. Keith’s blog is http://www.pluralsight.com/blogs/Keith. Both Keith and Dominick are definitely Windows security gurus. I highly recommend subscribing to both of their blogs! Sorry, guys!


How to Reproduce this Error


To reproduce the problem, create a new event source called “AspNetTest” that can write to the local Application log by running the following code in a console app as a local administrator:

string sourceName = “AspNetTest”;
string logName = “Application”;
string machineName = “.”;
if(!EventLog.SourceExists(sourceName, machineName)) {
EventLog.CreateEventSource(sourceName, logName, machineName);
}
Create an ASP.NET web application using the wizard and add the following two lines to Page_Load of WebForm1:
private void Page_Load(object sender, System.EventArgs e) {
EventLog log = new EventLog(“Application”, “.”, “AspNetTest”);
log.WriteEntry(“Writing from AspNetTest application”, EventLogEntryType.Information, 42, 42);
}

When run on Windows Server 2003 SP1, you will see a security exception like the one above. Modify the CustomSD on the Application event log and browse to WebForm1.aspx again. The web application will successfully write into the event log, which you can verify using the Event Viewer.

I get this question relatively frequently:

“I need to send binary data in my SOAP message. What is the recommended way of doing this?”

(I’ll admit that I’m a bit late to the party on this one. Most of the information below is summarized from the referenced sources near the end of this post.)

You can always Base-64 encode the binary data, but this has a number of undesirable consequences including the encoding/decoding costs at the endpoints and a 33% size bloat on the wire. It does have the advantage that all the WS-* specs work with it.

So the next obvious question is how can I send the binary data as binary? This leads us to SOAP attachments. Unfortunately the SOAP attachments space is somewhat fragmented at the moment. The current options are:

  • SwA (SOAP with Attachments)
  • DIME (Direct Internet Message Encapsulation) (AKA WS-Attachments)
  • PASwA (Proposed Infoset Addendum to SOAP Messages with Attachments)
  • MTOM (Message Transmission Optimisation Mechanism)

All of these techniques send the attachments using MIME or a MIME-like mechanism. DIME adds record lengths to MIME for quick lookup of binary data. Unfortunately with SwA and DIME, the attachments are not part of the XML InfoSet, which means that you cannot apply the WS-* specs to them. (Probably most notable and serious is WS-Security. Using SwA or DIME, you can sign and/or encrypt parts of the SOAP message, but you cannot sign or encrypt the attachments. You can make guarentees that the message has not been tampered with, but you cannot make those same guarentees about the attachments.)

PASwA and MTOM solve this problem using an include element to incorporate the attachment into the XML Infoset. There seems to be general agreement that the way forward is MTOM. MTOM will be available with WSE 3.0 and Indigo. (WSE 3.0 is currently available as a CTP and Indigo is a Beta1 RC.)

So what should I do in the meantime? If you’re dealing with relatively few small binary attachments, Base-64 encoding seems to be the way to go. The extra 33% size and encoding/decoding costs probably won’t matter much to you.* On the plus side, you get to use all those snazzy WS-* specs. If you’re processing large numbers of messages and/or your attachments are large, the extra 33% size and encoding/decoding costs probably matter to you.* So you’ll have to use WSE 2.0 and DIME or roll your own SwA implementation (as Microsoft does not have an implemenation of SwA). Be aware that any WS-* goo that you apply will not work on the attachments. So don’t go sending images of bank statements via SwA or DIME!

* As with all things perf-related, measure, measure, measure. Don’t assume that Base-64 encoding is too slow for your situation and write a pile of extra encryption code for DIME attachments. Establish some performance criteria and measure against it. Then make an educated decision as to the solution architecture.

Here are some background articles that were good reads on the topic:

And don’t forget to catch John Bristowe‘s GrokTalk on MTOM in WSE 3.0:

Edit: Corrected wonky links and strange HTML formatting.