Saturday, April 12, 2008

Someone on the CSLA .NET discussion forum recently asked what new .NET 3.5 features I used in CSLA .NET 3.5. The poster noted that there are a lot of new features in .NET 3.5, which is true. They also included some .NET 3.0 features as "new", though really those features have now been around for 15 months or so and were addressed in CSLA .NET 3.0. CSLA .NET 3.0 already added support for WCF, WPF and WF, so those technologies had very little impact on CSLA .NET 3.5.

My philosophy is to use new technologies only if they provide value to me and my work. In the case of CSLA .NET this is extended slightly, such that I try to make sure CSLA .NET also supports new technologies that might be of value to people who use CSLA .NET.

While .NET 3.5 has a number of new technologies at various levels (UI, data, languages), many of them required no changes to CSLA to support. I like to think this is because I'm always trying to look into the future as I work on CSLA, anticipating at least some of what is coming so I can make the transition smoother. For example, this is why CSLA .NET 2.0 introduced a provider model for the data portal - because I knew WCF was coming in a couple years and I wanted to be ready.

Since CSLA .NET already supported data binding to WPF, Windows Forms and Web Forms, there was no real work to do at the UI level for .NET 3.5. I actually removed Csla.Wpf.Validator because WPF now directly supplies that behavior, but I really didn't add anything for UI support because it is already there.

Looking forward beyond 3.5, it is possible I'll need to add support for ASP.NET MVC because that technology eschews data binding in favor of other techniques to create the view - but it is too early to know for sure what I'll do in that regard.

Since CSLA .NET has always abstracted the business object concept from the data access technique you choose, it automatically supported LINQ to SQL (and will automatically support ADO.NET EF too). No changes required to do that were required, though I did add Csla.Data.ContextManager to simplify the use of L2S data context objects (as a companion to the new Csla.Data.ConnectionManager for raw ADO.NET connections). And I enhanced Csla.Data.DataMapper to have some more powerful mapping options that may be useful in some L2S or EF scenarios.

LINQ to Objects did require some work. Technically this too was optional, but I felt it was critical, and so there is now "LINQ to CSLA" functionality provided in 3.5 (thanks to my colleague Aaron Erickson). The primary feature of this is creating a synchronized view of a BusinessListBase list when you do a non-projection query, which means you can data bind the results of a non-projection query and allow the user to add/remove items from the query result and those changes are also reflected in the original list. As a cool option, LINQ to CSLA also implements indexed queries against lists, so if you are doing many queries against the same list object you should look into this as a performance booster!

So all that's left are some of the language enhancements that exist to support LINQ. And I do use some of them - mostly type inference (which I love). But I didn't go through the entire body of existing code to use the new language features. The risk of breaking functionality that has worked for 6-7 years is way too high! I can't see where anyone would choose to take such a risk with a body of code, but especially one like CSLA that is used by thousands of people world-wide.

That means I used some of the new language features in new code, and in code I had to rework anyway. And to be honest, I use those features sparingly and where I thought they helped.

I think trying to force new technologies/concepts/patterns into code is a bad idea. If a given pattern or technology obviously saves code/time/money or has other clear benefits then I use it, but I try never to get attached to some idea such that I force it into places where it doesn't fit with my overall goals.

Saturday, April 12, 2008 3:11:52 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [2]  | 

 Sunday, March 16, 2008

I have a question (helping a colleague do some research) for all .NET VB developers.

Do you use late binding in VB? If so, how/why do you use it? What are the scenarios where you find it of value?

I'll start this off with my own observations:

I use late binding when getting data of a given shape from unknown types.

For example, you can write a nice bit of reusable data access code that accepts data from a web service, LINQ object, etc. by using late binding. You can’t easily do this without late binding in fact, because the types of the objects are different even though their shapes are the same.

That dynamic interface concept that got dropped from VB9 would address this issue in a better way, but late binding makes it work too.

I also use late binding when creating some generic types. There are cases where generics and casting are problematic, but converting a value to type Object first allows you to do a cast or operation that wouldn’t otherwise be allowed. I don’t know if this is “late binding” as such, but it is a useful technique!

I have used late binding when dynamically loading an assembly for interaction. Ideally you’d require the assembly author to implement one of your interfaces, but that’s not always possible, and late binding is a particularly nice way to get “polymorphic” access to multiple assemblies that you don’t control.

What about you?

Sunday, March 16, 2008 2:56:16 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [6]  | 

 Sunday, March 09, 2008

I'm just back from the MIX 08 conference. This was the first conference I've attended in many years (around 10 I think) where I wasn't speaking or somehow working. I'd forgotten just how fun and inspiring it can be to simply attend sessions and network with people in the open areas. No wonder people come to conference!! :)

Not that it was all fun and games. I did have meetings with some key Microsoft people and Scott Hanselman interviewed me for an upcoming episode of Hanselminutes (discussing the various data access and ORM technologies and how they relate to CSLA .NET 3.5).

The Day 1 keynote was everything I'd hoped for.

Well, nearly. The first part of the keynote was Ray Ozzie trying to convey how Microsoft and the web got to where it is now. The goal was to show the vision they are pursuing now and into the future, but I thought the whole segment was rather flat.

But then Scott Guthrie came on stage and that was everything you could hope for. Scott is a great guy, and his dedication and openness seem unparalleled within Microsoft. I remember first meeting him when ASP.NET was being unveiled. At that time he seemed so young and enthusiastic, and he was basically just this kick-ass dev who'd created the core of something that ultimately changed the Microsoft world. Today he seems nearly as young and easily as enthusiastic, and he's overseeing most of the cool technologies that continue to change the Microsoft world. Awesome!

So ScottGu gets on stage and orchestrates a keynote that really illustrates the future of the web. Silverlight (which makes me SOOoooo happy!), IE8, new data access technologies (like we needed more, but they are still cool!) and things like ASP.NET MVC and more.

As I expected, they released a whole lot of beta code. You can get a full list with links from Tim Sneath's blog. He also has links to some getting started materials.

The real reason for keynotes though, is to inspire. And this keynote didn't disappoint. The demos of Silverlight and related technologies were awesome! There was some funny and cute banter with the casting director from Circ del Sole as she demonstrated using a cool disconnected WPF app. There was a fellow RD, Scott Stanfield, showing integration of SeaDragon into Silveright so we can look (in exquisite detail) at the memorabilia owned by the Hard Rock Cafe company, some thought-provoking demos of Silverlight on mobile devices and more.

Now to be honest, I've never been a fan of the web development model. Having done terminal-based programming for many years before coming to Windows, I find it hard to get excited about returning to that ancient programming model. Well, a worse one actually, because at least the mainframe/minicomputer world had decent state management...

AJAX helps, but the browser makes for a pretty lame programming platform. It is more comparable perhaps to an Apple II or a Commodore 64 than to a modern environment, and that's before you get into the inconsistencies across browsers and that whole mess. Yuck!

Which is why Silverlight is so darn cool! Silverlight 2.0 is really a way to do smart client development with a true web deployment model. Much of the power of .NET and WPF/XAML, with the transparent deployment and cross-platform capabilities of the browser world. THIS is impressive stuff. To me Silverlight represents the real future of the web.

It should come as no surprise then, that I spent my time in Silverlight 2.0 sessions after the keynote. Sure, I've been working (on and off) with Silverlight 1.1/2.0 for the past several months, but it was a lot of fun to see presentations by great speakers like Joe Stegman (a Microsoft PM) and various other people.

One of the best sessions was on game development with Silverlight. I dabble in game development whenever I have spare time (not nearly as much as I'd like), and so the talk was interesting from that perspective. But many of the concepts and techniques they used in their games are things designers and developers will likely use in many other types of application. Background loading of assemblies and content while the app is running, and some clever animation techniques using pure XAML-based concepts (as opposed to some other animation techniques I saw that use custom controls written in C#/VB - which isn't bad, but it was fun to see the pure-XAML approaches).

Many people have asked about "CSLA Light", my planned version of CSLA .NET for Silverlight. Now that we have a Beta 1 of Silverlight I'll be working on a public release of CSLA Light, based on CSLA .NET 3.5. Microsoft has put a lot more functionality into Silverlight 2.0 than they'd originally planned - things like data binding, reflection and other key concepts are directly supported. This means that the majority of CSLA can be ported (with some work) into Silverlight. The data portal is the one big sticking point, and I'm sure that'll be the topic of future blog posts.

My goal is to support the CSLA .NET 3.5 syntax for property declaration and other coding constructs such that with little or no change you can take a business class from full CSLA and have it work in CSLA Light. This goal excludes the DataPortal_XZY implementations - those will almost always be different, though if you plan ahead and use a DTO-based data access model even that code may be the same. Of course time will tell how closely I'll meet this goal - but given my work with pre-beta Silverlight 2.0 code I think it is pretty realistic.

Scott Guthrie indicated that Silverlight 2.0 Beta 1 has a non-commercial go-live license - right now. And that Beta 2 would be in Q2 (I'm guessing June) and would have a commercial go-live license, meaning it can be used for real work in any context.

The future of the web is Silverlight, and Beta 1 is the start of that future. 2008 is going to be a great year!

Sunday, March 09, 2008 5:18:27 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

 Wednesday, December 19, 2007

I've been working all day on this WPF/WCF application, mostly trying to figure out how to configure WCF to actually do what I want in terms of security and authentication. All those angle brackets from the config files have given me a splitting headache... WCF may be cool, but configuring even relatively simple security scenarios is ridiculously difficult.

And then distaster struck. As though fighting with WCF and SSL wasn't enough, VS 2008 decided to quit publishing my app for ClickOnce. In order to test this app, I need to publish for ClickOnce on my dev box, copy the results to a test server and then run the code on a test client (thankfully we live in an age of virtual machines!!).

So the failure to publish to ClickOnce brought me up short. The issue is that the WPF project wouldn't build. It would build and run fine in all other ways, but not when I tried to publish for ClickOnce. It had been publishing just fine, and then BOOM!

(The only thing I can think of is that I was publishing for online only, then I published for online/offline, and then I switched back to online only - maybe VS doesn't like that sort of waffling and wants me to be more decisive?)

The specific problem is that the .g.i.cs files for each XAML source file that should have been in the obj\Debug directory didn't get there. Google was no help - searching for "clickonce publish .g.i.cs obj\Debug could not be found" resulted in one hit - to an MSDN forums post that was unreachable (I kept getting an MSDN forums error page).

Build|Clean Solution had no effect. Shutting down and reopening VS had no effect. Rebooting the dev box had no effect.

Finally I thought to manually delete the obj and bin folders in the project directory. And for good measure I deleted the .user file and .suo file for the project and solution. Then I reopened the project and it how publishes just fine.

Wednesday, December 19, 2007 5:10:22 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [1]  | 

 Friday, December 07, 2007

I rather expected this - a bit of confusion around .NET versions and related CSLA .NET versions.

Microsoft started the whole thing by calling .NET 2.5 version 3.0. Oops, did I say that out loud? :)

But it is true. From a .NET programming perspective, 3.0 is purely additive over 2.0. Thus it is really hard to see why it is a major version.

Especially when .NET 3.5 has a much bigger impact on day-to-day use of .NET, but is just a point release... If anything, this should have been .NET 4.0, but it isn't and so now we're all royally stuck in the land of confusion.

Nothing to do but make the best of it.

I know several people and organizations who ignored .NET 3.0, but are now looking to move to .NET 3.5. Effectively "skipping" 3.0, though the reality is that their move to 3.5 is also a move to 3.0. Personally I think that's smart - they saved themselves a year of pain by not trying to use .NET 3.0 with the limited tools available, and can now move to 3.0/3.5 with Visual Studio 2008 - so they have decent tool support for the technology.

When it comes to CSLA .NET, here's my take on it:

  • CSLA .NET 1.5.3 - latest version for .NET 1.x
  • CSLA .NET 2.1.4 - effectively obsolete
  • CSLA .NET 3.0.3 - latest version for .NET 2.0 and .NET 3.0
  • CSLA .NET 3.5.0 - in-progress version supporting .NET 3.5

At this time I do not anticipate being able to make CSLA 3.5 work without .NET 3.5, primarily due to use of new compiler features as well as LINQ and features in .NET 2.0a and 3.0a (aka .NET 2.0 SP1 and 3.0 SP1).

Friday, December 07, 2007 2:29:51 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [6]  | 

 Thursday, July 26, 2007

Visual Studio 2008 Beta 2, along with Microsoft .NET 3.5 Beta 2, is available for download. Here's Soma's official announcement.

I find that downloading such huge sets of files requires a bit of help. My recommendation: Free Download Manager. This tool is awesome - indispensable in fact - if you do any downloads beyond small text files :) It does queued downloads, resumed downloads and throttling. Perhaps best of all, it does multi-threaded downloads, so it maximizes the use of your bandwidth when running at full throttle.

Update: Apparently there are some things you must do/fix before using VS 2008!! Read ScottGu's blog post about it!

Update 2: According to Juval Lowy, the svcutil.exe program in Beta 2 is broken. A workaround is to copy an older (Beta 1?) version of svcutil.exe over the top of the Beta 2 version.  Instead, Justin Smith says that you need to run "sn.exe -Vr svcutil.exe" - apparently then you don't need to copy an older verison over the new one.

Thursday, July 26, 2007 3:21:37 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [2]  | 

 Monday, June 11, 2007

I posted previously about an issue where the WCF NetDataContractSerializer was unable to serialize a SecurityException object. Microsoft provided some insight.

It turns out that the constructor of the SerializationException object doesn't set the Action property to anything valid. Before you can serialize a SerializationException with NDCS you must explicitly set the Action property to a valid SecurityAction.

This does mean that NDCS is not compatible with the BinaryFormatter in this case, but at least there's a workaround/solution.

I've now updated CSLA .NET 3.0 to explicitly set the Action property any time a SecurityException is thrown, thus allowing the WCF data portal channel to return valid details about the nature of any exception.

Monday, June 11, 2007 9:07:53 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

 Friday, June 01, 2007

The WCF NetDataContractSerializer is an almost, but not quite perfect, replacement for the BinaryFormatter.

The NDCS is very important, because without it WCF could never be viewed as a logical upgrade path for either Remoting or Enterprise Services users. Both Remoting and Enterprise Services use the BinaryFormatter to serialize objects and data for movement across AppDomain, process or network boundaries.

Very clearly, since WCF is the upgrade path for these core technologies, it had to include a serialization technology that was functionally equivalent to the BinaryFormatter, and that is the NDCS. The NDCS is very cool, because it honors both the Serializable model and the DataContract model, and even allows you to mix them within a single object graph.

Unfortunately I have run into a serious issue, where the NDCS is not able to serialize the System.Security.SecurityException type, while the BinaryFormatter has no issue with it.

The issue shows up in CSLA in the data portal, because it is quite possible for the server to throw a SecurityException. You'd like to get that detail back on the client so you can tell the user why the server call failed, but instead you get a "connection unexpectedly closed" exception instead. The reason is that WCF itself blew up when trying to serialize the SecurityException to return it to the client. So rather than getting any meaningful result, the client gets this vague and nearly useless exception instead.

By the way, if you want to see the failure, just run this code:

    Dim buffer As New System.IO.MemoryStream
    Dim formatter As New System.Runtime.Serialization.NetDataContractSerializer
    Dim ex As New System.Security.SecurityException("a test")
    formatter.Serialize(buffer, ex)

And if you want to see it not fail run this code:

    Dim buffer As New System.IO.MemoryStream
    Dim formatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
    Dim ex As New System.Security.SecurityException("a test")
    formatter.Serialize(buffer, ex)

I've been doing a lot of work with the NDCS over the past several months. And this is the first time I've encountered a single case where NDCS didn't mirror the behavior of the BinaryFormatter - which is why I do think this is a WCF bug. Now just to get it acknowledged by someone at Microsoft so it can hopefully get fixed in the future...

The immediate issue I face is that I'm not entirely sure how to resolve this issue in the data portal. One (somewhat ugly) solution is to catch all exceptions (which I actually do anyway), and then scan the object graph that is about to be returned to the client to see if there's a SecurityException in the graph. If so perhaps I could manually invoke the BinaryFormatter and just return a byte array. The problem with that is in the case where the object graph is a mix of Serializable and DataContract objects - in which case the BinaryFormatter won't work because it doesn't understand DataContract...

In the end I may just have to leave it be, and people will need to be aware that they can never throw a SecurityException from the server...

Friday, June 01, 2007 11:34:14 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

 Friday, May 11, 2007

Earlier I blogged about the fact that the Orcas Beta 1 VPC image doesn't have ASP.NET set up with IIS, so you have to do that. Unfortunately there are a couple other issues I've discovered. Here's the full list:

  1. IIS isn't configured for ASP.NET
  2. Windows authentication isn't enabled for the default web site in IIS - blocking the use of VS debugging until you enable it
  3. The default for a VS Orcas web site is to build for .NET 3.5. If you attempt to debug such a project (when it is set to run in IIS) you'll get an error dialog with a vague message about an authentication error. The reason for this is that ASP.NET only supports .NET 2.0. To resolve this, you must go into the web site's properties dialog and set its target .NET version to 2.0. You can still reference the 3.0 and 3.5 assemblies and use the new features, but VS must build to .NET 2.0 or you can't debug in IIS.

    But it isn't just the debugger - other features may not work properly either, possibly resulting in a "hang" when you try to access a page.

For those of you at my workshop at VS Live this past Sunday, this was why my web site wouldn't run properly in the VPC. Fortunately there is this workaround, but I hope Microsoft provides a more comprehensive solution in the release version, because it is quite confusing to have to set your build version back to 2.0 even though you are really building against 3.5...

Friday, May 11, 2007 9:01:33 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [3]  | 

 Thursday, April 26, 2007
Aaron Erickson, a Magenic consultant, has been working on an interesting project: providing an indexing service for LINQ. You can get full information about i4o from this blog post, and from the official codeplex site.

You might wonder why this matters, given that LINQ uses database indexes to get its data. But that's actually Dlinq, which runs against SQL Server.

LINQ itself runs against objects, arrays, collections, lists and so forth. All of which are just in-memory objects, and obviously aren't indexed at all. LINQ does "table scans" against arrays and lists at all times. Basically LINQ just runs a lot of for-each loops for you. And in the vast majority of cases that is the right answer, because most lists are only a few score or maybe a few hundred items in length, and using for-each is faster than building an index.

However, you might have lists that are big enough, or where you are doing many repeated queries against the same set of properties, where the cost of building an index is lower than the cost of using simple for-each loops. And this is where the ability to index properties of the objects in a list such that LINQ uses the index becomes very useful.

In any case, check out i4o, because it is interesting and very cool stuff!

Thursday, April 26, 2007 8:33:32 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

 Tuesday, April 24, 2007

I am building a WPF UI for my ProjectTracker CSLA .NET sample app. On the whole this is going pretty well, and I anticipate being done within the next couple days. I’ve found and fixed a couple bugs in CSLA – one in BusinessListBase that’s been there forever, and one in ValidationPanel that caused a null reference exception. While I fixed that last one, I optimized the code a bit, which does seem to make the control a bit faster.

But one thing I spent a ridiculous amount of time on was the simple process of getting a ComboBox control to bind to one data source to get its list of items, and to the business object property for the key value. Google turned up a number of search results, none of which really addressed this particular scenario – which seems odd to me given how common a scenario it is…

In ProjectTracker, a person (resource) can be assigned to a project. If they are, they are given a role on that project. The Role property is numeric – a key into a name/value list, and a foreign key into the Roles table in the database. In Windows Forms and Web Forms the UI handles translating this numeric value to a human-readable value through ComboBox controls, and obviously WPF can do the same thing. The trick is in figuring out the XAML to make it happen.

Here’s the ComboBox XAML:

            <ComboBox

              ItemsSource="{Binding Source={StaticResource RoleList}}"

              DisplayMemberPath="Value"

              SelectedValuePath="Key"

              SelectedValue="{Binding Path=Role}"

              Width="150" />

 

Let’s break this down.

The ItemsSource property specifies the data source for the data that will populate the display of the control. In my case it is referencing a data provider control defined like this:

  <Page.Resources>

    <csla:CslaDataProvider x:Key="RoleList"

                           ObjectType="{x:Type PTracker:RoleList}"

                           FactoryMethod="GetList"

                           IsAsynchronous="False" />

  </Page.Resources>

 

This data provider control loads a name/value list object called RoleList (that inherits from Csla.NameValueListBase). The child objects in this collection expose properties Key and Value.

You can see how the ComboBox uses the DisplayMemberPath to specify that the Value property from the name/value list should be displayed to the user, and the SelectedValuePath specifies that the Key value from the list should be used to select the current item (the Key value is not displayed to the user).

Then notice that the SelectedValue property is used to bind to the main business object. This binding statement sets a path to a property on the overall DataContext for the ComboBox, which in my case is actually set through code at the Page object level:

      this.DataContext = project;

So all controls on the entire page, by default, bind to a Project object, and this includes the ComboBox.

Remember though, that the Role property on the Project is a numeric index value. And so is the Key value from the name/value list. The ComboBox control connects these two automatically. So when the business object’s Role property changes, the ComboBox automatically changes the displayed/selected item. Conversely, when the user changes the ComboBox selected item, that automatically causes the business object’s Role property to change.

Tuesday, April 24, 2007 7:55:13 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [5]  | 

 Monday, April 23, 2007

I just spent more time than I care to think about chasing down a silly config error in the Visual Studio codename "Orcas" Beta 1 VPC image.

I wanted to run a pre-existing web site, so I copied it to the VPC, aimed a virtual directory at it in IIS and BOOM! 404 errors.

I figured it was directory permissions, incorrect paths, all sorts of things.

Eventually, in frustration I opened VS and created a new ASP.NET web project at localhost/test. Guess what? VS kindly informed me that ASP.NET wasn't enabled for IIS on this machine, and asked if I'd like to enable it. Of course I said yes - and instantly my pre-existing web site started working.

So if you decided to use the Beta 1 VPC (which is a nice way to go), be aware that ASP.NET is not enabled for IIS, and you'll need to enable it before doing any work with ASP.NET or WCF.

Monday, April 23, 2007 1:43:31 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [1]  | 

 Wednesday, April 11, 2007

We're really not that far away from some major new technology. Visual Studio "Orcas" is slated to ship this fall, and will include .NET 3.5; which includes new compilers. And new compilers always means fun! :)

The VB team is running a series of webcasts to bring everyone up to speed on the language changes and the resulting capabilities.

Wednesday, April 11, 2007 3:09:12 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [5]  | 

 Thursday, March 15, 2007

I’ve been spending a lot of time in WPF-land over the past few weeks, and thought I’d share some of what I’ve learned. I haven’t been learning styles or UI layout stuff – Microsoft says that’s the job of the turtleneck-wearing, metrosexual GQ crowd, so I’ll just roll with that. Instead, I’ve been learning how to write data source provider controls, and implement Windows Forms-like behaviors similar to the ErrorProvider and my Csla.Windows.ReadWriteAuthorization control.

You know, manly programming J

The data source provider control is, perhaps, the easiest thing I’ve done. Like ASP.NET, WPF likes to use a data control concept. And like ASP.NET, the WPF data provider controls are easy to create, because they don’t actually do all that much at runtime.  (I do want to say thank you to Abed Mohammed for helping to debug some issues with the CslaDataProvider control!)

I’m sure, as designer support for data provider controls matures in tools like Visual Studio and Expression Blend, that life will get far more complex. Certainly the Visual Studio designer support for Csla.Web.CslaDataProvider has been the single most time consuming part of CSLA .NET, though I was able to create the runtime support in an afternoon…

What I have today, is a Csla.Wpf.CslaDataProvider control that works similar to the ObjectDataProvider. The primary difference is that CslaDataProvider understands how to call Shared/static factory methods to get your objects, rather than calling a constructor method. The result is that you can create/fetch CSLA .NET business objects directly from your XAML.

The really cool part of this, is that CslaDataProvider supports asynchronous loading of the data. To be fair, the hard work is done by the WPF base class, DataSourceProvider. Even so, supporting async is optional, and requires a bit of extra work in the control – work that is worth it though. If you construct a form that has multiple DataContext objects for different parts of the form, loading all of them async should give some nice performance benefits overall.

On the other hand, if your form is bound to a single business object the value isn’t clear at all. Though the data load is async, the form won’t actually display until all the async loads are complete, so for a single data source on a form my guess is that async is actually counter-productive.

The validation/ErrorProvider support is based on some work Paul Stovell published on the web. I conceptually based my work on similar concepts, and have created a ValidationPanel control that uses IDataErrorInfo to determine if any bindings of any controls contained in the panel are invalid.

The panel control loops through all the controls contained inside the panel. On each control it loops through the DependencyProperty elements defined for that control (in WPF controls, normal properties aren’t bindable, only dependency properties). And it then loops through any Binding objects attached to each DependencyProperty. I discovered that those Binding objects are complex little buggers, and that there are different kinds of binding that I need to filter out. Specifically relative bindings and control-to-control bindings must be ignored, because they don’t represent a binding to the actual business object.

To optimize performance the panel does a bunch of caching of binding information, and is relatively sparing in how often it refreshes the validation data – but it is comparable to ErrorProvider, in that changing one business object property does trigger rechecking of all other properties bound within the same ValidationPanel. I think this is necessary, because so many data source objects are constructed around the Windows Forms model. Not following that model would cause a lot of headache when moving to WPF.

The authorization support is implemented in a manner similar to the validation. Csla.Wpf.AuthorizationPanel uses the CSLA .NET IAuthorizeReadWrite interface and scans all bindings for all controls contained in the panel to see if the business object will allow the current user to read or write to the bound property. If the user isn’t allowed to read the property, the panel either hides or collapses the data bound control (your choice). If the user isn’t allowed to write to the property, the panel sets the control’s IsReadOnly property to true, or if the control doesn’t have IsReadOnly, it sets IsEnabled to false.

AuthorizationPanel doesn’t include the same level of caching as ValidationPanel, but I don’t think it is necessary. Where ValidationPanel refreshes on every property change, AuthorizationPanel only refreshes if the data source object is changed (replaced) or if you explicitly force a refresh – probably because the current user’s principal object has changed.

I want to pause here and point out that I’ve had a lot of help in these efforts from Paul Czywczynski. He’s spent a lot of time trying these controls and finding various holes in my logic. And the next control addresses one of those holes...

The IsValid, IsDirty, IsSavable, IsNew and IsDeleted properties on a CSLA .NET business object are marked as Browsable(false), meaning they aren’t available for data binding. In Windows Forms you can work around this easily by handling a simple event on the BindingSource object. But in WPF the goal is to write no code – to do everything through XAML (or at least to make that possible), so such a solution isn’t sufficient.

Enter the ObjectStatusPanel, which takes the business object’s properties and exposes them in a way that WPF can consume. Using this panel, your object’s status properties (single object or collection) become available for binding to WPF controls, and if the object’s properties change those changes are automatically reflected in the UI. The most common scenario here is to bind a button’s enabled status to the IsSavable property of your editable root business object.

Most recently I’ve started refactoring the code in these controls. For the most part, I’ve now consolidated the common code from all three into a base class: Csla.Wpf.DataPanelBase. This base class encapsulates the code to walk through and find relevant Binding objects on all child controls, and also encapsulates all the related event handling to detect when the data context, data object, object property, list or collection have changed. It turns out that a lot of things can happen during data binding, and detecting all of them means hooking, unhooking and responding to a lot of events.

I wrote all these controls originally using the Dec 2006 CTP, and just started using them in the Mar 2007 CTP. As a pleasant surprise there was no upgrade pain – they just kept working.

In fact, they work better in the MarCTP, because the Cider designer (WPF forms designer) is now capable of actually rendering my custom controls. What I find very interesting, is that the designer actually runs the factory method of the CslaDataProvider control, so the form shows real data from the real objects right there in Visual Studio. I’m not sure this is a good thing, but that’s what happens.

There’s no doubt that I’ll find more issues with these controls, and they’ll change over the next few weeks and months.

But the exciting thing is that I’m now able to create WPF forms that have functional parity with Windows Forms, including validation, authorization and object status binding. And it can all be done in either XAML or code, running against standard CSLA .NET business objects.

People attending VS Live at the end of this month will be the first to see these controls in action – both in my workshop on Sunday the 25th and in my sessions during the week. And I plan to put a test version of CSLA .NET 3.0 online that week as well, so anyone who wants to play with it can give it a go.

Right now, if you aren’t faint of heart, you can grab the live code from my svn repository. Keeping in mind, of course, that this is an active repository and so the code in trunk/ may or may not actually work at any given point in time.

Thursday, March 15, 2007 9:37:24 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [4]  | 

 Tuesday, March 13, 2007

String formatting in .NET is a pain. Not that it has ever been easy - even COBOL formatting masks can get out of hand, but there's no doubt that the .NET system is harder to grasp and remember than the VB 1-6 scheme...

I just had a need to format an arbitrary value using a user-supplied format string. You'd think that

obj.ToString(format)

would do the trick. Except that System.Object doesn't have that override of ToString(), so that's not a universal solution. So String.Format() is the obvious next choice, except that I need to somehow take a format string like 'N' or 'd' and make it into something valid for String.Format()...

Brad Abrams has some good info. But his problem/solution isn't quite what I needed. Close enough to extrapolate though:

outValue = string.Format(string.Format("{{0:{0}}}", format), value);

Given a format string of 'N', the inner Format() returns "{0:N}", which is then used by the outer Format() to format the actual value.

Tuesday, March 13, 2007 9:30:21 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [7]  | 

I've been working with the Visual Studio Orcas CTP from March 2007 for a few days now. My focus had been around WCF and WPF and ensuring my CSLA .NET 3.0 development worked in the new CTP.

Then earlier today I tried building a workflow. And the workflow designer wouldn't open. Instead I got a concise little error dialog saying "Microsoft.VisualStudio.Shell.WindowPane.GetService(System.Type)". This was the case with both C# and VB projects.

Worse, attempting to close VS after that point caused a complete VS crash. It turns out that other designers (like project properties) fail as well, with similar errors.

In talking to some people at Microsoft, I discovered that the problem wasn't universal. But in talking to more people, the root of the issue appeared.

I downloaded the huge 9 part VSTS/TFS edition of the Orcas VPC. Other people downloaded the smaller 7 part VSTS-only edition. The problem only occurs in the big 9 parter, and is due to a side-by-side issue. Some VS 2005 components are in the bigger VPC to support SQL Server, and they are causing the issue. The 7 part VPC doesn't have that functionality, or those components, and so the SxS problem doesn't occur.

So I'm about 80% done downloading the 7 parter, then I can get back to work.

Tuesday, March 13, 2007 9:15:14 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [1]  | 

 Wednesday, February 07, 2007

I get a lot of questions about the new ADO.NET Entity Framework and LINQ and how these technologies interact with CSLA .NET. I've discussed this in a few other blog posts, but the question recently came up on the CSLA .NET forum and I thought I'd share my answer:

They are totally compatible, but it is important to remember what they are for.

Both ADO.NET EF and LINQ work with entity objects - objects designed primarily as data containers. These technologies are all about making it an easy and intuitive process to get data into and out of databases (or other data stores) into entity objects, and then to reshape those entity objects in memory.

CSLA .NET is all about creating business objects - objects designed primarily around the responsibilities and behaviors defined by a business use case. It is all about making it easy to build use case-derived objects that have business logic, validaiton rules and authorization rules. Additionally, CSLA .NET helps create objects that support a rich range of UI supporting behaviors, such as data binding and n-level undo.

It is equally important to remember what these technologies are not.

ADO.NET EF and LINQ are not well-suited to creating a rich business layer. While it is technically possible to use them in this manner, it is already clear that the process will be very painful for anything but the most trivial of applications. This is because the resulting entity objects are data-centric, and don't easily match up to business use cases - at least not in any way that makes any embedded business logic maintainable or easily reusable.

CSLA .NET is not an object-relational mapping technology. I have very specifically avoided ORM concepts in the framework, in the hopes that someone (like Microsoft) would eventually provide an elegant and productive solution to the problem. Obviously solutions do exist today: raw ADO.NET, , the DAAB, nHibernate, Paul Wilson's ORM mapper, LLBLgen and more. Many people use these various technologies behind CSLA .NET, and that's awesome.

So looking forward, I see a bright future. One where the DataPortal_XYZ methods either directly make use of ADO.NET EF and LINQ, or call a data access layer (DAL) that makes use of those technologies to build and return entity objects.

Either way, you can envision this future where the DP_XYZ methods primarily interact with entity objects, deferring all the actual persistence work off to EF/LINQ code. If Microsoft lives up to the promise with EF and LINQ, this model should seriously reduce the complexity of data access, resulting in more developer productivity - giving us more time to focus on the important stuff: object-oriented design ;) .

Wednesday, February 07, 2007 12:08:20 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [6]  | 

I have a custom data source control as part of my CSLA .NET framework. It is somewhat like ObjectDataSource, but works with objects that are created through factory methods rather than default constructors (and some other variations).

 

All is pretty well with this control, except one issue: it fails when adding a CslaDataSource control to a page as a new data source from a DetailsView or other control.

 

In other words, you add a DetailsView to the page, then tell that control you want it to bind to a new data source and it brings up a wizard, where you pick CslaDataSource so a new one is added to the page.

 

The problem I’m getting is a VERY odd exception: Csla.Web.CslaDataSource can not be cast to Csla.Web.CslaDataSource.

 

Yes, that’s right – the type can’t be cast to itself.

 

I believe this is because the wizard is loading its own copy of Csla.dll into memory, separate from the one used by the web forms designer. Or something like that. This even confuses the debugger – it can’t show details about the type because it says the type is loaded into two different GUIDs. I don’t know what the GUIDs represent (appdomains, versions?), but it is obviously not good.

 

This is very weird, and after hours of time on this, I’m quite stumped. Any help, clues, pointers or ideas are VERY welcome!

 

Thanks! Rocky

Wednesday, February 07, 2007 12:40:18 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [10]  | 

 Wednesday, January 17, 2007

I recently had an email discussion where I was describing why I needed to solve the problem I described in this article for WPF and this article for Windows Forms.

 

In both cases the issue is that data binding doesn’t refresh the value from the data source after it updates the data source from the UI. This means that any changes to the value that occur in the property set code aren’t reflected in the UI.

 

The question he posed to me was whether it was a good idea to have a property set block actually change the value. In most programming models, goes the thought, assigning a property to a value can’t result in that property value changing. So any changes to the value that occur in the set block of a property are counter-intuitive, and so you simply shouldn’t change the value in the setter code.

 

Here’s my response:

 

The idea of a setter (which is really just a mutator method by another name) changing a value doesn't (or shouldn't) seem counter-intuitive at all.

 

If we were talking about assigning a value to a public field I’d agree entirely. But we are not. Instead we’re talking about assigning a value to a property, and that’s very different.

 

If all we wanted were public fields, we wouldn't need the concept of "property" at all. The concept of "property" is merely a formalization of the following:

 

  1. public fields are bad
  2. private fields are exposed through an accessor method
  3. private fields are changed through a mutator method
  4. creating and using accessor/mutator methods is awkward without a standard mechanism

 

So the concept of "property" exists to standardize and formalize the idea that we need controlled access to private fields, and a standard way to change their value through a mutator method.

 

Consider the business rule that says a document id must follow a certain form - like SOP433. The first three characters must be alpha and upper case, the last three must be numeric. This is an incredibly common scenario for document, product, customer and other user-entered id values.

 

Only a poor UI would force the user to actually enter upper case values. The user should be able to type what they want, and the software will fix it.

 

But putting the upper case rule in the UI is bad, because code in the UI isn't reusable, and tends to become obsolete very rapidly as technology and/or the UI design changes. There's nothing more expensive over the life of an application than a line of code in the UI. So while it is possible to implement this rule in a validation control, in JavaScript, in a button click event handler - none of those are good solutions to the real problem.

 

Yet if that rule is placed purely in the backend system, then the user can't get any sort of interactive response. The form must be "posted" or "transmitted" to the backend before the processing can occur. Users want to immediately see the value be upper case or they get nervous.

 

So then we're stuck. Many people implement the rule twice. Once in the UI to make the user happy, and once in the backend, which is the real rule implementation. And then they try to keep those rules in sync forever - the result being an expensive, unreliable and hard to maintain system.

 

I've watched this cycle occur for 20 years now, and it is the same time after time. And it sucks.

 

This, right here, is why VB got such a bad name through the 1990’s. The VB forms designer made it way too easy to write all the logic in the UI, and without any other clear alternative that's what happened. The resulting applications are very fragile and are impossible to upgrade to the next technology (like .NET). Today, as we talk, many thousands of lines of code are being written in Windows Forms and Web Forms in exactly the same way. Those poor people will have a hell of a time upgrading to WPF, because none of their code is reusable.

 

What's needed is one location for this rule. Business objects offer a workable solution here. If the object implements the rule, and the object runs on the client workstation, then (without code in the UI) the user gets immediate response and the rule is satisfied. And the rule is reusable, because the object is reusable - in a way that UI code never can be (or at least never has been).

 

That same object, with that same interactive rule, can be used behind Windows Forms, Web Forms, WPF and even a web services interface. The rule is always applied, because it is right there in the object. And for interactive UIs it is immediate, because it is in the field's mutator method (the property setter).

 

So in my mind the idea of changing a value in a setter isn't counter-intuitive at all - it is the obvious design purpose behind the property setter (mutator). Any other alternative is really just a ridiculously complex way of implementing public fields. And worse, it leaves us where we've been for 20+ years, with duplicate code and expensive, unreliable software.

Wednesday, January 17, 2007 3:45:30 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [14]  | 

 Tuesday, January 09, 2007

Here's an issue from Windows Forms that appears to have crept into WPF as well – along with a solution (thanks to Sam Bent and Kevin Moore from the WPF team):

 

Consider a class with a property that enforces a business rule - such as that the value must be all upper case:

 

public class Test : INotifyPropertyChanged

{

  public event

    System.ComponentModel.PropertyChangedEventHandler

    PropertyChanged;

  // ...

 

  private string _data;

 

  public string Data

  {

    get

    {

      return _data;

    }

    set

    {

      _data = value.ToUpper();

      OnNotifyPropertyChanged("Data");

     }

  }

}

 

Bind this to a TextBox and type in a lower-case value. The user continues to see the lower-case value on the screen, even though the object obviously has an upper-case value. The PropertyChanged event is blissfully ignored by WPF data binding.

 

I believe this is the same "optimization" as in Windows Forms, where the assumption is that since the value was put into the object by data binding that it can’t be different from what's on the screen - so no refresh is needed. Obviously that is a unfortunate viewpoint, as it totally ignores the idea than an object might be used to centralize business logic or behavior...

 

In Windows Forms the solution to this issue is relatively simple: handle an event from the BindingSource and force the BindingSource to refresh the value. Bill McCarthy wrapped this solution into an extender control, which I included in CSLA .NET, making the workaround relatively painless.

 

In WPF the solution is slightly different, but also relatively painless.

 

It turns out that this optimization doesn’t occur if an IValueConverter is associated with the binding, and if the binding’s UpdateSourceTrigger is not PropertyChanged.

 

For the TextBox control the UpdateSourceTrigger is LostFocus, so it is good by default, but you’ll want to be aware of this property for other control types.

 

An IValueConverter object’s purpose is to format and parse the value as it flows to and from the target control and source data object. In my case however, I don’t want to convert the value at all, I just want to defeat this unfortunate “optimization”. What’s needed is an identity converter: a converter that does no conversion.

 

namespace Csla.Wpf

{

  public class IdentityConverter : IValueConverter

  {

    #region IValueConverter Members

 

    public object Convert(

      object value, Type targetType,

      object parameter, System.Globalization.CultureInfo culture)

    {

      return value;