One of the things you have to weigh when relying on a particular technology is the level of acceptance and penetration that technology has. In general, the bigger the user base, the more active the user community, and the more mature the product, the safer you are in the long run. Reputation is huge, too. But there is another factor that is sometimes overlooked, and that is whether your use of the technology is “typical” or more of an “edge case”.
I have to admit in fairness to DNN, that the problem I’m about to describe came about because we are stretching the boundaries of what DNN’s designers contemplated the product doing. DNN won’t get an “A” on their report card from me in the design, documentation or support departments, but to be absolutely truthful, I suspect that 95% or more of their users will never encounter the issues I describe in this post. They simply won’t use the features we do. With DNN, although the user base is very diverse, I suspect that the typical DNN site is 100% DNN driven.
The application I’m working on, however, started as a non-DNN application of some complexity. DNN was bolted on after the fact. It’s come to the point where DNN handles most of the pages served to users, but users still authenticate against the legacy application and certain use cases are handled within legacy code.
Without going into proprietary details, a user authenticated on the legacy site has to be authenticated within DNN. That means we actually have user data in two places: a database owned by the legacy app, which is the authoritative source of user information; and DNN’s database.
Because of this, when the legacy app registers a new user it must create the user record in its own DB and then call into DNN’s API to create the same user in the DNN database.
The main problem we encountered was that a DNN core method, AddUser(), had been deprecated and replaced with a shiny new CreateUser() method. The old method is marked deprecated and makes a call to the new method, and both the old and new method take a UserInfo instance as an argument; so in theory our existing code should have worked. But it didn’t; the AddUser() call had no effect at all.
AddUser() simply returns a userID from the database. It’s not documented but I suspect it returns zero if not successful. The new function returns a value from an enumeration, so the first thing I did to trouble shoot the problem was to change our code to call the new method and see what the enumeration was returning.
It turned out that the value coming back was “InvalidUsername”, no matter what user name we provided. On further examination I realized that we had been setting Membership.Username in the passed UserInfo instance, where Membership is a reference to a UserMembership instance associated with the UserInfo. But now there is a new Username property in UserInfo itself that has to be filled. In fact there are several properties that exist both in UserInfo and in its Membership field, and we now stuff the same info into both, and the new user is correctly created.
So … the problem here is a change in how certain bits of info are passed which was not, as far as I could find, documented either in the code or elsewhere. One point against DNN. However, so few DNN users would call this method that I suspect not many users have been bitten by this issue. It all boils down to safety in numbers; if enough people had show-stopping problems with this change it would surely have been fixed by now.