Wednesday, May 30, 2007

WCF: Security Architecture and Claims

At my WCF talk at NNUG last night, I didn't have the time to go into the security architecture of WCF in general or into identity model details such as STS, tokens, policies and claims.

To get an overview of these aspects, I recommend reading "The holy grail of Enterprise SOA security" by Matias Woloski.

To learn more about how to actually build an authorization system based on claims, you should read "Building a Claims-Based Security Model in WCF" part 1 and part 2 by Michele Leroux Bustamente.

[UPDATE] Read the Digital Identity for .NET Applications whitepaper by David Chappell to get a good overview of the involved technology.

Thursday, May 10, 2007

WCF+EntLib3: Getting started

In addition to the WCF+EntLib3 validation and exception handling posts at Guy Burstein's blog/CodeProject, this info from David Hayden's blog about logging should get you started:
  • A new EntLibLoggingProxyTraceListener class. This trace listener is designed to be used in WCF’s System.ServiceModel trace source, which is configured within the <system.diagnostics> section. This trace listener receives WCF messages logged to this trace source, wraps them in an XmlLogEntry class, and forward them to the Logging Application Block where it can be processed according to the application block configuration.
  • A new XmlLogEntry class, which derives from LogEntry but includes a new Xml property that preserves the original XML data provided by WCF.
  • A new XmlTraceListener class, which derives from the .NET XmlWriterTextWriter class. This class can extract XML data from an XmlLogEntry class
In short, attributes and the interceptor mechanisms of WCF are used to integrate EntLib3 features for validation and exception handling, while logging is just another trace listener. You'll need to understand how to configure all three application blocks to make the WCF integration work. I recommend using the EntLibConfig.exe tool to configure the EntLib3 stuff, and the SvcConfigEditor.exe tool to configure WCF tracing wrt logging. The WCF toolbox is included in the .NET3 SDK.

That is all I have managed to find regarding the WCF features of EntLib3. The online MSDN docs contains mostly "new WCF features added to the ____ Application Block" statements and no code samples.

Tuesday, May 08, 2007

MSCRM: viewing DHTML source of 'related entity' frames

Michael Höhne has an good post on how to change the default view of related entities in MSCRM v3, in which he shows how to gather the info necessary for creating the OnLoad javascript. One of the needed elements is the ID of a combobox inside the <iframe id="areaActivityHistoryFrame">. However, getting at the source of frames is not that easy in MSIE as Michael has discovered. The same goes for seeing the actual content of a modified dynamic HTML page.

Viewing the 'history' source is actually rather simple, follow these steps:
  • Open the view account form
  • Press CTRL-N on the keyboard to show the browser chrome including the address bar
  • Select the 'History' folder to view the related activities
  • Enter this javascript in the address bar and press enter to view the frame source:
javascript: '<xmp>' + document.frames("areaActivityHistoryFrame").document .body.outerHTML + '</xmp>';


Change the name of the <iframe> in the javascript to view the source of other related entity folders. Remember to select the folder first to make the frame source available for the script.

The above script is a slight modification of this script to view the dynamic source of the window.document:

javascript: '<xmp>' + window.document.documentElement.outerHTML + '</xmp>';

The MSIE Developer Toolbar is also useful, except for the issues with frames as described by Michael.

While you're in javascript mode, check out the impressive list of useful javascript snippets for MSCRM at Michael's Stunnware site.

Monday, May 07, 2007

WCF: Exception Handling with Logging

In my 'WCF Exception Shielding using Generics' post there was a "//TODO: add logging as applicable" comment, which I now have implemented using the EntLib3 Logging Application Block.

As part of the error information I wanted to write to the Windows Application Event Log was the actual request message causing the service operation exception. Thus, I googled for a solution for how to get the XML of the incoming message, so that I could log it along with the stack trace. There are a lot of options for getting at the message in WCF:

The problem of the first option is that I only want to get at the message XML when handling exceptions. The second option is not an option (duh!) as I want my operations to be strongly typed using my data contracts. The third option was more like what I wanted, but it seemed to be unneccessary complicated code.

The code to get at the message XML from within an operation is quite simple:

private static string GetMessageXml(DefaultMessage request)
{
return OperationContext.Current. RequestContext.RequestMessage.ToString();
}

This approach does not work for operations with no RequestContext, such as one-way operations.

The logging code is added after creating the fault details, this makes it possible to use fault details data in the log. This is how my WCF exception shielding with logging looks like:

public static FaultException<T> NewFaultException<T>(Exception ex)
where T : FaultContracts.DefaultFaultContract, new()
{
return NewFaultException<T>(ex, null);
}

public static FaultException<T> NewFaultException<T>(Exception ex, DefaultMessage request)
where T : FaultContracts.DefaultFaultContract, new()
{
return CreateNewFaultException<T>(ex, request);
}

private static FaultException<T> CreateNewFaultException<T>(Exception ex, DefaultMessage request)
where T : FaultContracts.DefaultFaultContract, new()
{
StackFrame stackFrame = new StackFrame(2);
string methodName = stackFrame.GetMethod().Name;

T fault = new T();
Type type = fault.GetType();
type.InvokeMember("SetFaultDetails", BindingFlags.Public BindingFlags.Instance BindingFlags.InvokeMethod, null, fault, new object[] { ex });

string msg = String.Format("An unexpected error occurred in {0}.", methodName);
Dictionary<string, object> props = new Dictionary<string, object>();
props.Add("stackTrace", ex.ToString());
if(request!=null)
{
string xml = GetMessageXml(request);
props.Add("requestMessage", xml);
}
Logger.Write(msg, Category.General, Priority.Highest, (int)EventLogId.Exception, TraceEventType.Error, ex.Message, props);

string reasonText = methodName + " failed, check detailed fault information.";

#if DEBUG
reasonText = methodName + " error: " + ex.ToString();
#endif

return new FaultException<T>(fault, new FaultReason(reasonText));
}

Note that I now use an inner private method to create the new fault to be thrown and thus must skip two stack frames to get the details of the original method called. The DEBUG section is there to make it simple to see full exception details in NUnit or with Fiddler when debugging the service. This DEBUG code must never make it into release builds, as this is not exactly exception shielding.
I have not looked into the WCF app-blocks integration mechanisms added in the april release of EntLib3, that is next on my task list for quieter days. There is not much info about this to be found, but Guy Burstein provides some samples. Btw, you should check out the Patterns and Practices Guidance site, it contains useful stuff and tutorials about EntLib3.

Sunday, May 06, 2007

EntLib3 should apply convention over configuration

After using the EntLib3 validation application block (VAB) for a while now, and also some of the new configuration mechanisms such as external configuration source and environmental overrides for different build types; it occurs to me that there is a bit to much XML noise in the config.

EntLib3 should do as in Castle Windsor and MonoRail and Ruby on Rails; apply "convention over configuration". In EntLib3 config files, you have to add mandatory attributes to identify the default configuration when there are multiple config options. Using "first is default" as in the Windsor 'constructor injection' mechanism would make configuration simpler and less error prone (see VAB issue below). I understand the reasons for having a default-identifier as a separate attribute, but with the new config override and merging mechanisms in EntLib3, there should be less need for compulsory config "switching" attributes.

The convention "first is default" would prevent silly omission errors such as not setting the default rule set in VAB less drastic. As it is now, if you forget to set the VAB default rule set, no validation will be applied, neither will there be any "no rules" exception - and your code will run as if all validations passed, even if there are plenty of broken rules in the input.

While I'm at it, the caching of connection strings and service URLs in the Settings class and the service proxies, is also really silly; you will not be able to detect that some configuration is missing until you move the solution to an isolated staging environment that has no access to the databases/service resources referenced in the development environment. Most test environments are not that isolated from the development environment, and such config errors can go undetected for a long time during testing. This is one area where it would be better if Microsoft could make configuration compulsory.

Wednesday, May 02, 2007

Puzzling TableAdapter problem

Today I was asked to look at a puzzling problem with TableAdapters at another project at my current customer. The problem they had was that they could not make the TableAdapter read back the generated SQL Server identity column values when saving a dataset (ta.Update) to insert new rows.

The first thing I checked was the 'Advanced options' of the TableAdapter to see if the 'Refresh the data table' setting was on. It wasn't. "But, we checked that option when we added the adapter". I checked the option and finished the wizard, then checked the setting again. It wasn't set...

I had noticed that details in the wizard summary page was rather short, so I did the wizard steps and inspected the summary again: "Generated SELECT statement" and "Generated INSERT statement", but no "Generated UPDATE statement" and no "Generated DELETE statement". I suspected that this was the cause of the problem, but what could cause the missing SQL commands ? The UpdateCommand and DeleteCommand of the TableAdapter's property window was empty. According to the online help, these statements "will be generated if there is enough information", but no hints to which information is needed. Really helpful.

Looking at the table definition in SQL Server, I then noticed that the table had no defined primary key. I selected the identity column and applied the "Set Primary Key" action and saved the table definition in SQL Server. After reconfiguring the TableAdapter in Visual Studio, the data table now has a defined primary key and - lo and behold - update/delete commands and refresh data on save.

Problem solved.