The snowball effect soon revealed that the next major release would need to be labeled version 3.0. This is mostly because of "breaking" changes: modifications to the DotNetNuke core application that changed the primary interfaces to the point that plug-ins from the previous version 2.0 release would not integrate without at least some minimal changes. The catalyst for this was due to changes in the Membership API from Microsoft, but this only led to a decision of "If you are forced to break compatibility, introduce all of your breaking changes in one breaking release." The fact is there was a lot of baggage preserved from the IBuySpy Portal that we were restricted from removing due to legacy support considerations. DotNetNuke 3.0 provided the opportunity to reexamine the entire project from a higher level and make some of the fundamental changes we had been delaying for years in some cases. This included the removal of a lot of dead code and deprecated methods as well as a full namespace reorganization that finally accurately broke the project API into logical components.
DotNetNuke 3.0 also demonstrated another technical concept that would both enrich the functionality of the application framework as well as improve the extensibility without the threat of breaking binary compatibility. Up until version 3.0, the service architecture for DotNetNuke was completely uni-directional. Custom modules could consume the resources and services offered by the core DotNetNuke framework but not vice versa. So although the application managed the secure presentation of custom modules within the portal environment, it could not get access to the custom module content information. Optional interfaces enable custom modules to provide plug-in implementations for defined core portal functions. They also provide a simple mechanism for the core framework to call into third-party modules, providing a bi-directional communication channel so that modules could finally offer resources and services to the core (see Figure 1-9).