We didn’t want to let the first half of this year go without reaching a new milestone, and here it is: we’re excited to announce PostSharp 3.2 Preview 2, available for download on NuGet and our website. PostSharp 3.2 is now fully documented and has made it through the final API review.
We didn’t really know where we were heading to when we started to work on this version, but after a six-month journey we’re very happy of the result.
And here’s our proudest achievement:
PostSharp 3.2 allows you to write thread-safe code in C#. I mean, really. No, we don’t magically make your old C# apps thread-safe, but PostSharp 3.2 both extends and restricts C# to define an execution model that is verifiably thread-safe (we call that threading model). It’s still the C# you know: we extend the language using custom attributes, and we enforce the model using build-time and run-time verifications. So, if you write your code against of one of threading models of PostSharp 3.2, and if you cover your code with reasonable single-threaded tests, you are much more likely to have thread-safe code. Unsafe code would trigger build-time errors or deterministic runtime exceptions instead of allowing for random data races.
We would really like to say that if you use PostSharp you’re 100% sure to have 100% thread-safe code, but this would be absurd. No real-life programming language can claim that. What we do claim is that if you use the custom attributes provided by PostSharp 3.2 instead of writing thread synchronization code manually, you will have a dramatic reliability increase and an equally dramatic cost decrease.
PostSharp 3.2 supports the following threading models: Actor, Immutable, Freezable, Synchronized, Reader-Writer Synchronized, Thread-Affine and (the anti-model) Thread-Unsafe. For more information, read Working with Threading Models.
Object-oriented programming is a great paradigm to build business and consumer applications and we really, really don’t like the blind push for functional programming these days here at PostSharp. There is a word to describe this social phenomena: hype. Fortunately, people in charge for 7-plus-digit projects don’t make their decisions based on fashions. Although OOP has been criticized for being unpredictable in multi-threaded scenarios, we’re proving that well-understood technologies such as aspect-oriented programming, static analysis and runtime program verification can be used bring thread safety to mainstream programming languages. We still see bright days for OOP.
Although threading models definitively what we’re the most excited about, PostSharp 3.2 brings much more:
In this article, Alessandro Federici, System Architect at CODY Systems, talks about how and why he is using the Model Pattern Library and shows a pragmatic approach to make the PostSharp Code Contracts play nice with XAML-based applications. He also describes some of the other aspects he built himself: - InstantiateIfNullAspect, StringManipulationAspect and WrapExceptionsAspect.
The source code for this blog post is available for download.
I’ve been using PostSharp for several months at CODY Systems. For the sake of this article, I built a small WPF application that demonstrates our principal use cases. This application is very simple and is split into two assemblies:
- MyCompany.Contracts.dll: a simple assembly with the definition of data contracts such as User, PersonName and Phone. This is an assembly that is meant to be used in WPF client applications, MVC web apps and/or web services (if we were to build any). In addition, this assembly contains all the aspects required for validation and a few other utilities.
- WPFApp.exe: the main executable. It links to the other assembly and contains just one view, its view model and some helper classes.
When you run the application, you will see a dialog that will look like this:
As soon as you change the text of some controls, if the values are invalid and validation rules fail, you will get the following hints being displayed:
The two buttons at the bottom of the dialog show how to trigger validation manually (the 'Validate' button) and how to use my WrapExceptionAspect (the 'Throw Exception' button).
To use IDataErrorInfo/IValidatableObject, or to throw exceptions, this is the question
When you build XAML applications (i.e. WPF, Silverlight or Windows Phone), you are supposed to use the IDataErrorInfo interface to collect errors. These errors are then intercepted by using specific triggers and the collection 'ValidationRules' of the bindings of your view. MVC also respects the interface, although it does so by using the MVC approach to binding and using post-backs.
IValidatableObject is a newer approach in the realm of .Net data validation. It was introduced by MVC 3 and, as far as I know, it is an MVC-only item (by default, at least. You can certainly support it in WPF or Silverlight with some coding).
My main beef with IDataErrorInfo and IValidatableObject is that they expect you not to raise exceptions in property setters which is precisely what the PostSharp Model Patter library does. They treat such situations as something either “bad” or un-common.
In my opinion, property setters that throw exceptions are common and, in many cases, the behavior is a useful feature that makes classes easy to use and understand. The approach follows the same logic of good methods that raise ArgumentNullException(s) or similar exceptions. Good stuff, if you ask me.
For instance, if you were to code a Person class by using IDataErrorInfo guidelines, you would receive no errors assigning Age the value -22 or FirstName a null value. You would not find out about the problem unless you read the Errors property and then acted accordingly.
There are good reasons for designing interfaces that work like this, but in my opinion this is a case where user-interface concerns got mixed up with elements that should follow user-interface-agnostic guidelines.
I understand that sometimes a certain value is invalid only if another property has a specific value (e.g. you cannot have a boolean Juvenile flag being set if the Age is more than 18). Yet, what I found in my experience is that this kind of validation should (more-often-than-not) be delegated to other classes. I call those classes “Validators”.
Complex or cross-property business logic often needs parameters or very configurable rules that might change, depending on the customer. In some systems I worked on, some business rules might be completely eliminated during certain implementations while they could be replaced in their entirety in others Cluttering classes like User, Customer, etc. with those rules usually lead to suboptimal situations (code-wise).
Let me explain by expanding on the Juvenile example above.
The type of software I write relates to law enforcement. If a crime is committed by a Juvenile there are a number of rules that have to be considered. Some rules affect the flow of data (e.g. where are these objects stored? Who can see juveniles and work on them?), others rules determine validity of a Person's object state (e.g. Juvenile can be true if (Age<SysConfiguration.AgeOfAdults) or (Age is null and SysConfiguration.AllowNullAgeForJuveniles)).
The tricky part is that a juvenile is not always a juvenile: what one State considers a juvenile (age of 17) might be considered an adult in another State (e.g. Illinois vs California). If we were to enforce cross-property rules between Juvenile and Age inside the Person class, we'd have to know the configuration of the system inside Person and act accordingly. That, in my opinion, is really not a concern of the Person class.
Person is a class that should never allow a negative Age or a null FirstName. That's about it, and that is what aspects do well. Those rules always make sense, in Person, and belong to the Person “contract”.
The fact a state considers adults at the age of 17 or 18 and the need to check the values of two properties is a problem that originates from ‘where Person’ is used (our system, with a given configuration applied), not what a Person is or should allow for. In addition, it has been advantageous to be able to completely replace certain business logic for some of our customers, so the pluggable 'Validator' played much nicer than embedded (and quasi hard-coded) rules.
Validator classes are then used by view models and server side services (I always double check for such things, as the user of our API might not have access to our C# contract libraries and might need to rely solely on server-side validation).
So, having said this, what I wanted to see is if I can use the PostSharp aspects that ensure 'universal' (i.e. always necessary) object-state integrity, proper formatting of some text (e.g. capitalization of names or other helpful thing of this nature) and, at the same time, build a WPF interface that shows nice errors just like using the IDataErrorInfo interface.
The contracts library is where all the validation rules I choose get defined. The idea is to create a set of classes that are reusable regardless of the user-interface framework you will build clients with. WPF, ASP.Net, ASP MVC... It shouldn't matter. Actually it shouldn't matter if you have a user-interface layer at all. Business contracts should work even without a client and allow you to just write a web service API which is used as-is.
The contracts library in the sample application is very simple. It defines three classes: User, PersonName and Phones. User is defined as follows:
As you can see, there isn't much to it, except an abundance of aspects.
The properties Age and EMail use two aspects that should be obvious to anybody reading the code. That is a very important part of using aspects: they often help making behavior obvious and forego the need to read documentation or dive into code. Range and EmailAddress are part of the Model Pattern Library shipped with PostSharp 3.0. The first will check that the Age is positive and won't allow values bigger than 110. The second will ensure that the email address is properly typed (i.e. firstname.lastname@example.org).
INotifyPropertyChanged No More
At the very top of the class, I used the well-known NotifyPropertyChanged aspect that is probably the most used and most famous aspect that ships with PostSharp. That aspect alone probably eliminated half the code needed to implement the class User. The feature will come handy in WPF and Silverlight apps and it will have no noticeable impact on an MVC app or a web service.
It's also possible to have code that inspects properties and, by looking at what aspects are applied to them, can generate automatic tooltips or verbose documentation.
My Custom Aspects
The Name property is decorated with my very own InstantiateIfNullAspect. That aspect (which I included in this sample) creates instances of the property it is applied to, without the need for repetitive code such as “if (_name==null) _name = new PersonName(); return _name;”. I use this aspect extensively in my contracts library. It allows me to create a new Person and immediately start populating its pieces without thinking about nulls or redundant extra code.
You can see this in the CreateDesignTimeData() method of the view model:
The principle that guides its use, for me, is the following: certain parts of a class (owner) might be defined using other classes, but the owner describes something that would not make sense without the other piece(s). Whenever this rule is met, it probably makes sense to use InstantiateIfNotNullAspect, auto-create inner instances and cut all the boiler-plate code that would be otherwise necessary (especially in the calling code, which is much easier to plague with NullReferenceException(s)).
While the aspect supports interfaces (e.g. you can have a property of type IList and specify that the 'ConcreteType' you want to use to create it is either List, ObservableCollection, etc.), I rarely use it with interfaces. I leave those as properties that are to be filled in, for instance, after fetching data from the server. The fact those properties are null are a reminder that a web-service fetch is necessary. It's up to you to decide if this fits with your needs or not, but I wanted to mention it.
The PersonName class is similar, but I user more aspects, including my StringManipulationAspect. This aspect changes strings by performing one or many common transformations (e.g. remove some type of characters, capitalize text, lower-case it, upper-case it, etc.) that we often need in applications.
Once again, pretty obvious to understand, thanks to aspects.
The Application's View
As you would expect from any decent MVVM application, the view is 99.99% code-free. Specifically, the only code in the main view is the automatically-generated constructor.
The interesting parts are in the XAML code.
The first thing I did was to define a couple of resources that will be needed for my error interception.
The first is a converter ('ErrorMessageConverter') which is capable of getting an exception message and convert it to nicely readable text. This was necessary because the messages coming from the PostSharp validation aspects don't read well (as tool-tips), even if we provided our own error text like I did in the properties First and Last of the class PersonName. Some text-transformations were necessary and the nicer text is what will be displayed by the tool-tips, whenever a validation rule is violated.
The second resource is a style that I want applied to all TextBox(es). This style contains a trigger that binds to the error that was raised (if an error was raised) and uses the previously defined converter 'ErrorMessageConverter'.
With these two resources, I can now continue my XAML coding and have all TextBoxes react to errors by displaying a red box and a tool-tip just adding an ExceptionValidationRule element to its binding:
The purpose of the button 'Validate' is to show how to invoke validation manually. This is something you will need if the form starts without data and you want to guide the user actions. To see it work, enable the commented code in the constructor of the view model, run the application and then click the button.
What happens, when you run the application, is the following: a regular Exception is thrown with the message 'This is the inner exception (…)'. The aspect catches that and wraps it in a GuiException whose message then becomes 'An unexpected error occurred. The error was 'This is the inner exception (…)''.
It's easy to get in situations where some exceptions occur and you don't immediately know what caused them. Often we are given mysterious and miss-leading bug reports that read as 'A 'NullReference crash occurred when I clicked the button', or more nonsense like that.
When I read those reports, I usually get angry for two reasons: the completely useless error report and, right after, the knowledge that I have no immediate pointer to what really happened. The WrapExceptionAspect allows me to wrap exceptions into more meaningful ones, so that I immediately know the area where the problem occurred. Obviously all that happens automatically, since we use aspects.
Server-side, in my web servoces, I tend to create exception types for each area of my API (e.g. FileService, ImageService, SecurityService etc. with the relative FileServiceException, ImageServiceException and SecurityServiceException) and I then wrap the accessible web-methods with the aspect. What happens then is that, instead of getting useless NullReferenceException(s), I get xxxServiceException(s) that wrap the other errors (whatever they are). The exception now immediately points me to the right area so I can focus my attention on the right service or area.
The Model Pattern Library is a great addition to the arsenal provided by PostSharp. While powerful, very easy to use and fall in love with, it's hard to use the validation aspects cleanly, in XAML applications. This article showed a possible solution to the problem so you can plug validation aspects in XAML front-ends without having to duplicate validation logic in IDataErrorInfo of IValidatableObject interfaces.
We’re sorry to announce that a critical defect affects all builds of PostSharp versions 3.1.0-3.1.40 and 3.2.0-3.2.20. We strongly recommend all projects
using PostSharp 3.1 to be upgraded to PostSharp 3.1.42.
Which projects are affected?
It is important to understand that the defect acts as a “time bomb”. You will be affected by the project even if (a) you did not modify its source code, (b)
you did not upgrade PostSharp and (c) you did not install any Windows update.
Projects that (a) are bound to PostSharp 3.1.0-3.1.33 AND (b) that don’t cause PostSharp to emit an error or warning message are not affected.
Does the issue affect run-time behavior of applications built with PostSharp?
No. The defect only affects build-time behavior.
What are the symptoms of the error?
You may see one of the following symptoms, according to the kind of host:
With PostSharpHost=PipeServer (typically on developer workstations): “connection unexpectly closed by the server” followed by
“Retrying to execute the pipe server” followed by “Error connecting to the pipe server. See previous warnings for details”
With PostShatpHost=Native (typically on build servers):
error MSB6006: "postsharp.4.0-x64.exe" exited with code -199
error MSB6006: "postsharp.4.0-x86.exe" exited with code -199.
error MSB6006: "postsharp.4.0-x64-cil.exe" exited with code -199
error MSB6006: "postsharp.4.0-x86-cil.exe" exited with code -199.
With PostSharpHost=Managed: The license dialog of Nove.CodeDOM appears.
Upgrade all projects using PostSharp 3.1.0-3.1.40 using NuGet Package Managers:
Open the solution in Visual Studio
Click on menu item Tools / NuGet Package Manager / Manage NuGet Packages for Solutions…
Go to the Update tab.
Update all PostSharp packages to version 3.1.42 or higher.
Deploy the new source code to build server and team members.
Note: Updating the PostSharp Visual Studio Extension (VSiX) is not required and does not solve the issue.
What happens if I don’t upgrade the projects?
If you don’t upgrade the project, the issue may appear later, and your team may lose productivity in diagnosing it.
What is I don’t have an active maintenance subscription?
We “tricked” the 3.1.42 build so it is available to anyone who was properly licensed for PostSharp 3.1 RTM, even with an expired license subscription. You should then specifically upload to build 3.1.42. Other builds don’t have the license “trick”.
What is the cause of the defect?
The error is caused by the license enforcement component of Nova.CodeDOM, a library that we lawfully sourced from Inevitable Software. PostSharp uses this
library to provide file and line number information of error messages.
Previously to 3.1.33, PostSharp initialized Nova.CodeDOM lazily, when the first error message needed to be resolved. Starting 3.1.33, PostSharp initialized
Nova.CodeDOM unconditionally. This is why projects built with PostSharp 3.1.33 and later are more likely to be affected by the issue.
Why was this issue not anticipated?
We anticipated issues in the Nova.CodeDOM library and implemented a fail-safe behavior, so that a failure in the library would just cause a failure to
locate the file and line number of error messages, but except of having no file and line information, the build would work as usually. However, we did assumed that all failures would be in the form of a managed exceptions. We did not
anticipate that the library would terminate the process.
When did the symptoms first occur?
The issue first hit our support line on May 20th at 16:00, Central Europe Time. We became aware of the severity of the issue on May 21st at 10:00 when more support tickets were filed.
When was a fix released?
We uploaded the build 3.1.41 fixing this issue on May 21st at 14:00, Central Europe Time.
Completed in a rush, this build contained two non-blocking issues, which were fixed in 3.1.42 and uploaded on May 23rd.
How was the issue solved?
As we lost trust in Nova.CodeDOM, we decided to immediately remove the library from our product. As from version 3.1.41, we will no longer ship
Nova.CodeDOM with our products.
Therefore, we unfortunately had to surrender the feature that was using Nova.CodeDOM. Namely, current versions of PostSharp no longer resolve the file and
line number of error messages. We will restore the feature with Roslyn as soon as the license will allow for redistribution.
At PostSharp, we are taking our customers’ productivity extremely seriously. We are aware that this issue prevented whole teams of developers from working
during several hours, and that the potential impact of the issue may account for dozens of thousands of dollars of combined productivity losses.
Although the defect was caused by a third-party component, we are ultimately responsible for the overall quality of our product, and this includes
selection of suppliers.
Therefore, on behalf of PostSharp Technologies, I would like to profoundly apologize for the inconveniences caused by the issue.
UPDATE: Edited the article to mention our build 3.1.42 fixing minor issue and licensing friction.