BKdotNET - Bill Knaus's Dev Blog

Better solutions through smarter code.

January 2006 - Posts

Gotchas with the Copy Database wizard in SQL 2005

Yesterday I needed to copy a database from my local machine to one of our development servers... both the server and my local pc are running SQL Server 2005 Dev.

My first thought was to simply detach my database from my local, copy to the server, and then reattach on the server.  As I right-clicked on the database, the last menu item caught my eye... "Copy Database..."  I decided to see what this would do for me and "click" I began what started out to be a pretty cool journey...

The Copy Database wizard allows you to do the copy by the "detatch and attach" method (which I was willing to do by hand) or using the SQL Management Object method, which I wanted to avoid... (I wasn't in the mood).

So I go through the wizard just fine - some of the things I had to do to actually make it work....

  1. These were both relatively "virgin" installs of SQL Server 05 Dev.  So the first obstacle I ran into was Microsoft's new security initiative: Install with minimal risk exposure.  In other words - I had to turn on Named Pipes and TCP/IP - on both servers.
  2. The account that the SQL Agent service was running under on my destination server had to be running under an account that had access to a file share to the database file on the source server.  Now-  this isn't just the proxy account you can configure in SQL Server... this is the actual account the service runs as.

Now - at this point - everything transferred over beautifully - it even created the server login for my database... at least I had thought.

So the next thing I encountered were reports that no one was able to log in to the database at its new location.  During the copy process, it might create the login, it might maintain the integrity of your database... but it doesn't link the server login to the database user.  In fact - it made it quite impossible because now my database user is configured "WITHOUT LOGIN" and I can't change it.  I unwire some of the dependencies that would allow me to drop the user - drop it - and recreate it for my login.

But my problems don't end there - people still are not able to use the account - final resort - I reset the password.  voila. 

Now - for this last part - is that all I had to do was change the password?  Did I have to go through dropping the account?  I don't know.  But doing all of this worked.  If you have a different experience - I'd be interested in hearing about it.

DotNetNuke ClientAPI and Microsoft's Atlas

Jon Henning, the lead for the DNN Core Team ClientAPI team and creator of the SOLPARTMENU featured in DNN, provided some thoughts on the future of the DotNetNuke ClientAPI and Microsoft's Atlas in his blog.  Having seen a recent video from MSDN on Atlas, due out sometime this year, there's a lot of potential for creating a richer user experience on top of DNN as this year unfolds. 

Here are his thoughts.

Here is the video/demo on Atlas on MSDN.

And finally - the Atlas web site.

DotNetNuke's IUpgradeable interface for module controllers...

I was going through the ASP.NET Forums for DotNetNuke and came across this post from "Sponge_Bob".

Is there anyway that I could run my own custom code on installation of my own PA's. I have a Module the need to be able to check and see if a certain Dll file is installed on the server before installing. Also I need the install to be able to check the version of the Dll file on the server an make certain the it is of the required version. Finally if the Dll not of the required version I want to point the person installing the PA to the place where to get the latest version of the install.

I have the option here to use Code (Preferred) or Sql to accomplish this task as I can make it so the required Dll I need to check for has its version entered into the database as it will be originally installed as a skin object.

It would be really sweet if Dnn could check the version of a Dll file before overwriting it with a dll file from a PA to make certain the it is not installing a Dll File of a lesser version. I am more that willing to write the code to accomplish this if the core team is willing to implement it.

So - I took a few minutes to help "Sponge_Bob" out.  Here's my response...

I have to answer a question from Sponge_Bob.  Dig yer username.

DotNetNuke provides an interface called IUpgradeable.  The interface is implemented on your controller class for you module, similar to the way IPortable and ISearchable are implemented.  There's very little written about this interface, however.  The interface contract contains one method definition -

Function UpgradeModule(ByVal Version As String) As String

So digging a little deeper...

The the lastest version of the Private Assembly Installer (V3) will check to see if your BusinessController class supports the IUpgradeable interface.  If it does support it, it will iterate through an ArrayList of versions and call your UpgradeModule implementation for each version.

So - similar to the way DNN does version control - you can handle each incremental upgrade... a nice litte switch / case statement on the version string sent in to your method.

Now if a needed DLL is not there - you could always throw an error... OR - use your string return to add an error to the module install... (that would be the kindler, gentler approach).  Use HTML within the string to color the text red so it stands out.  Well - you should always return a string at least letting the user know that each upgrade was successful.  Any string you return will be added to the module install / parsing results.

Seeing that this is done during install of your module or module upgrade - I wouldn't recommend putting any code in here to check for latest version or anything like that.  However, what I would recommend is creating a separate edit control for "Check for New Version" which can do that.  Unless it is mission critical to push latest versions (i.e. OS Security Patches, Virus Software) I personally prefer choosing an option like that.

Considerations for Creating a Custom DotNetNuke Install

I've just finished an article on how to customize the DotNetNuke installation package.  I spent a few hours today digging around the DNN framework looking at how DNN does installs, how portal and host templates work, and how to specify which modules need to be installed... as well as how to not install some of the basic dnn modules.  The more I dig around inside the framework, the more impressed I become with DNN (which says a lot since I've been impressed with DNN for quite some time).  A lot of times when looking through other people's code, specifically some of the open source stuff out there, you get to a point and say - "ah - they're going to regret that they did that".  I've been saying a lot of the opposite - "yeah - that makes sense" or "jeez, thats how I would have done it."

In this case, I was setting up a shared DNN development environment and realized that I hadn't "sanitized" my DNN 4 install yet... I ended up on a journey that has me dreaming about host templates, a common module set for all of our install points, and... and... our own portal that shows up after install with our own skin.  Nice. 

Take a read.  It looks pretty lengthy - but i try to make it an easy read.  If anything - especially for those developers visiting from work - you can get an idea of the capabilities this framework provides... and the power beneath your fingertips.

>> Article <<

Adding a Module DataProvider to DotNetNuke

So I have been doing quite a bit of research and debugging of the DotNetNuke provider model over the past two days. 

In the end I have come to two conclusions - one, the DNN model makes sense and two - the DNN Core Team needs to add a try / catch block here and there to add a better error message for those of us using this particular part of the DNN framework.

The scenario goes a bit like this: 

Create a common set of classes to be used by a number of business-specific modules for DotNetNuke.  This is created as a separate class library project that in ASP.NET 2.0 would be referenced by the DNN web site (/bin folder).

The business class library will contain the DataProvider specification (in the form of an abstract class) that any data provider would need to implement in order for the "front-end" module to save data. 

Now - all this is great - simple - straight forward.

I implement a Web Service Data Provider for my new business object library and go to wire it up... and realize one big problem... I have to specify the type and assembly to load from my base DataProvider.

"Ruh-Roh!"  Not to mention I couldn't get the thing to run. "Dubbuh Ruh-Roh!"

After going line by line through DotNetNuke's "CreateObject" method within their Reflection framework - I realized one thing - I wouldn't be able to specify multiple providers for my custom modules without adding a new provider configuration section within the web.config.  The reason is that all of the overloads that they provide that allow for using the DNN "data" section of web.config require you to specify the type and library of the provider you want to instantiate.

So I had to create a new section in the web.config.

<mydata defaultProvider="WSDataProvider">
  <providers>
    <clear/>
    <add name="WSDataProvider" 
	type="MyCompany.Library.WSDataProvider.WSDataProvider, MyCompany.Library.WSDataProvider"
	providerPath="~\Providers\DataProviders\WSDataProvider\" />
  </providers>
</mydata>

(Now, don't forget to copy the DNN "data" section config at the top of the web.config file and rename it to your very own.)

Now your call to instantiate your DataProvider can be simplified...

    objProvider = (DataProvider)Reflection.CreateObject("mydata");

What this briefer statement does is find your config for "mydata" (the config block above) and uses the defaultProvider setting to determine which provider to instantiate.  It reads in the value for type.  Which is the next place where I got hung up.  The documentation and parameter names for these are "Namespace" and "Assembly".  Wow.  But they don't quite work like that in the various CreateObject overloads provided by DotNetNuke's Reflection Framework.  When you're loading up the default provider, the two comma separated values for type should be, in order, the fully-qualified name of the class for the provider, and the name of the assembly where your class is located.  This can vary by each overload - so please be careful.  This is how you put the work totally behind DNN in determining which provider you want to use.

So my recommendation is actually two-fold.  If you plan on your module using the DNN database and work off of the fundamental DNN provider settings.. go the route prescribed in the template that's provided in the DNN Starter Kit for VS 2005.  If you plan on accessing a separate database either directly or indirectly, like through web services, I would recommend establishing your own provider settings.  In the end you will have a lot easier go of things, especially if you want to add variations on your implementation.

Posted: Jan 18 2006, 02:36 PM by BillKnaus | with no comments
Filed under:
Web Services as Data Providers

We use a lot of web services at work.  They provide a very effective means for creating accessible reusable code and all the other wonders and glories that come with web services.

When looking at the DNN DataProvider model, specifically when looking at how all the examples in the DNN world revolved around the IDataReader and other Microsoft interfaces, the models are driven toward supporting multiple native data sources, not necessarily multiple general sources.  For example, if I want to create a DataProvider for my contacts that has a method that returns all of my contacts from Mississippi, the code for my abstract dataprovider might look a lot like this...

    public abstract class DataProvider
    {
        // singleton reference to the instantiated object
        static DataProvider objProvider = null;

        // static constructor
        static DataProvider()
        {
            CreateProvider();
        }

        // method for instantiating a child class of DataProvider and holding reference
        private static void CreateProvider()
        {
            objProvider = (DataProvider)Reflection.CreateObject("data", "MyCompany.Modules.MyModule", "");
        }

        public static DataProvider Instance()
        {
            return objProvider;
        }

        public abstract IDataReader GetContact(int ContactId);
        public abstract IDataReader GetContacts();
    }

Notice the last two lines declaring the two abstract methods.  They both return IDataReaders.  From a "traditional" DNN perspective - this is right on.  A SQL DataProvider, MySQL DataProvider or Oracle DataProvider would have no problem returning an IDataReader.   In the DNN world, the final data provider provides the resulting IDataReader to a "controller" class which then dumps it to the DNN common business object (CBO) which can produce a nice pretty object if all the column names match the properties on the object.  Great. Wonderful. Fabulous.  But our front-end UIs don't go directly to the database - they go through a number of web services.  So, now what?

So I start thinking through a number of options... should I have my web service data provider convert its strongly-typed return into something that's an IDataReader?  (Is that even easily done?)  I am kind of stuck at this point, because I need to be able to consume my strongly-typed web service calls for the time-being.   In the future we're going to move to a more XML message set - but the past will need to be supported for a while longer.

My current solution to the problem is to return local business objects... now when I say local, I mean that they are business objects that are intended for the front-end, and in this age of ASP.NET 2.0, make use of the [DataObject] and its family of attributes which make attaching to ObjectDataSources that much easier.  My new abstract methods in this business object scenario may look like this...

        public abstract Contact GetContact(int ContactId);
        public abstract List<Contact> GetContacts();

My implementation for my existing web services, since they will not be modeled after my new front end objects, will require a bit of property mapping, but I will be able to hide that from the "consumer", even if that "consumer" is just me.  Here's an example of an implementation of the GetContact abstract above.

        public override IDataReader GetModuleItem(int ModuleId)
        {
            // create an instance of my web service
            ContactsProxy.WSContacts myWS = new ContactsProxy.WSContacts();
            
            // execute my web service method to get my contact
            ServiceContact wsContact = myWS.GetContact(ContactId);

            // create an instance of a local contact object
            Contact localContact = new LocalContact();

            // translate between my web service return and my local class
            localContact.FirstName = wsContact.fName;
            localContact.LastName = wsContact.lName;
            localContact.Email = wsContact.email;

            // return a local representation of data returned by web service
            return localContact;
        }

The approach sticks to the true spirit of the provider model, but removes the pure data level abstraction, simply because we don't return readers or datasets.  The beauty of this is, I can create one web service provider for the web services we have today, create a new provider in the future, and they are interchangeable to the UI. 

This approach still needs some good field testing to ensure its viability, but it's not a far cry from data provider implementations in place today.  The key difference is these data providers are actually more in tune with the needs of the UI as far as the front-end objects.  The down side to that is that it is not as easy to make changes as it is with SQL Server where you can change the result set and immediately get the feedback in the object without changing the middle-tier.

In the end, this may just be the way things need to be done for Web Services... odds are I'm overlooking something obvious that would make life easier... but for now - this works - it's not a far stretch from the model, and each of the web services provider implementations can provide an accurate translation of data.

A world of ASP.NET 2.0 Discovery

I have been spending a lot of time over the past two weeks knee deep in DotNetNuke and ASP.NET 2.0 code.

I have now realized that one of the best ways for me to keep this all straight - and to remember how I figured things out is to write it down.  Well - everyone on the Internet can learn from what I have discovered.

The first thing I have discovered of major relevance is that Microsoft is sadly understating some of the architectural changes in ASP.NET 2.0.  I think they're doing this simply to protect the more jumpy developers.  You know the type... the ones who finally get comfortable with a technology three months before the newest and greatest comes out.  In other words, some of these architectural changes are rather significant.  They're the kinds of changes that look extremely harmless... They're the kinds of changes that if not considered architecturally will cause you to lose sleep.  They're the kinds of changes that right now are making me drool.

I'm very excited about ASP.NET 2.0 now.  (notice the word _now_).   I really didn't see much benefit - however - that was because I was letting some of my prejudices about Microsoft's past performances with Visual Studio.NET 2002 and 2003 really skew my ideas on what this new upgrade had in store.

We all heard about fun things like the Provider Model or Web Parts or Login / User management controls baked in... but Microsoft had to make a fundamental change to make all that work.  I have started writing about that with Part 1 of.. well, however many it takes... You can view the article here.