Tuesday, July 6, 2010

Turning a lemon into lemonade: Multiple galleries in a single web application

A clash between DotNetNuke portals and Gallery Server Pro architecture

Back in March I released an alpha build to a few select users for a new DotNetNuke module version of Gallery Server Pro. At the time I thought I was nearly done. Well, it turns out that DotNetNuke has one feature that conflicted with GSP’s architecture: Multiple Portals. And I’ve been working to resolve this ever since.

Portals are a concept in DNN where a single web application can have one or more mini-web sites that appear – to the outside world – as if they are separate applications. They can even have different URLs: www.p1.site.com, www.p2.site.com, etc. For example, a user navigating to www.p1.site.com would see a site that looks completely different than www.p2.site.com. It can have a different theme, different content, and even different users, but behind the scenes it is a single web application connecting to a single database.

My alpha testers noticed that the GSP module worked fine EXCEPT that media objects were shared across multiple portals. Not cool - Each portal must have its own set of media objects and its own administration settings. At first I thought – no big deal – GSP already has the concept of a gallery – all I need to do is create a unique gallery for each portal.

The problem, however, was that the Gallery ID was specified in galleryserverpro.config, and there is only one of those per web application. I had to figure out how to manage multiple galleries within *one* application. There was no way to shoehorn the config file to support multiple galleries unless I radically changed its structure. Even then, an administrator updating a setting in one portal would cause the entire application pool to recycle, since that is how the ASP.NET configuration system works. Something big had to change.

Refactoring gallery settings to the database

In the end, I abandoned the galleryserverpro.config file and moved everything into the database. There are now five new tables:

gs_GallerySetting – Stores most of the items in the <core> section of galleryserverpro.config, such as ShowErrorDetails and MediaObjectPath. The column FKGalleryId is a foreign key to gs_Gallery, so each gallery gets its own set of settings.

gs_AppSetting – It made sense to keep a few items from galleryserverpro.config at the application level, and these are stored here. It has just a few records that apply to all galleries, such as JQueryScriptPath and ProductKey.

gs_BrowserTemplate – These are the HTML templates from galleryserverpro.config.

gs_MimeType – This is a read-only list of all MIME types.

gs_MimeTypeGallery – This stores whether each MIME type is enabled or disabled for a gallery.

These changes were applied to the source code trunk, meaning it affects the main release of GSP in addition to the DotNetNuke branch.

With these changes, the next version of GSP will support multiple, distinct sets of media objects within a single web application. Each set – called a gallery – has its own settings, users and roles. From the user’s perspective, the media objects are completely isolated from each other, although a site administrator can move or copy objects between galleries. And the galleryserverpro.config file has been confined to the dustbins of history.

A quick note about users and roles: GSP continues to use the membership and role provider model. This model enforces a unique set of user and role names across the entire application. That means that once a user is created, that username cannot be created again in other galleries. You can, however, *share* users and roles across galleries. For example, you can assign user ‘Bob’ to have view permission in gallery 1, write permission in gallery 2, and no permission whatsoever in gallery 3.

I used the phrase “turning lemon into lemonade” in the title because this was not something I wanted to spend three months working on, nor do I think this is a feature that regular GSP users are clamoring for. I would have rather spent this time adding tagging support, improving the upload experience, or just about any of the one hundred items on my to-do list.

Making lemonade

However, it turns out there are significant benefits to this change. One of my favorites is that the application pool no longer recycles when you update a setting. Now you can edit a setting without affecting any in-progress uploads or synchronizations.

Plus, more complex scenarios suddenly become possible:

  • You want to have one gallery for staging and another for production. Media objects are first added to the staging area, where they are organized and prepped. When they are ready to be deployed, they can be moved or copied to the production gallery.
  • You have departments in your company that should each have their own gallery. Each gallery should have its own administrator and can have its own settings, such as user accounts, watermark, permissions, etc. Rather than setting up and maintaining multiple web applications, this can now be handled in a single app.
  • You have media files in multiple locations you want to expose, such as D:\Pictures and D:\Video.
  • You want to set up a gallery for each member of your family. Each person is a mini-administrator for their area and can't edit another person's media objects, yet everything is contained within a single web application and database.
  • You want some images to be 640x480 and others to be smaller (or larger).
  • You want to have a watermark applied to one set of images but another set should have no watermark, and all images are to be accessible to anonymous users. Or you have different watermarks that should be applied to different sets of images.
  • You want to provide a user with different gallery-wide permissions. For example, user 'Bob' should be a gallery administrator for one set of objects, but have edit-only permission for another set.
  • You want to allow some users to upload any file type of any size, but others should only be able to upload .JPEG's that are less than 5 MB.

Gallery administration

To accommodate this change, the concept of a “gallery administrator” has been introduced. A gallery administrator can change settings for a particular gallery but has no rights to other galleries. She can add users and roles, but those accounts are restricted to the current gallery.

The previous concept of a site administrator remains. The site administrator has complete access to all galleries.

Creating multiple galleries

The desired gallery is now specified on the Gallery user control defined in the web page. For example, the Gallery definition in default.aspx now looks like this:

<gsp:Gallery ID="g" runat="server" GalleryId="1" />

To create a second gallery, just add a new ASPX page and specify a new gallery ID:

<gsp:Gallery ID="g" runat="server" GalleryId="2" />

The first time you load this page, GSP will automatically create the gallery and a default set of gallery settings. One of the first things you may want to do is check the media object path to ensure it is at a unique location. You *can* use the same media object path in multiple galleries, but note that updating an object in one gallery does not update the database record associated with the other gallery.

Example: Create a staging gallery

To create a staging gallery where you can prep objects before pushing them to the production gallery, copy default.aspx to create a second ASPX page called gallerystaging.aspx. Change the gallery ID to a new value (such as 2). Open this page in your browser – you don’t need to run the install wizard or compile any source code. Log in with any account with ‘Allow site administration’ permission and configure the settings as desired, such as disabling anonymous access and changing the media object file path. Synchronize or add your media objects and organize them as you wish.

I’ll assume the original page default.aspx is your production gallery. While in your staging gallery, use the move/copy function to transfer the items to the production gallery. Voila! You have just deployed your items to production.


My priority is to get a beta version of the DotNetNuke module released as soon as possible. There are still some odds and ends to take care of, like how to implement licensing, but hopefully nothing significant. If I didn’t have any distractions, I think it would be ready within a few weeks. But my development time has been split to support a few customers, and it is unclear how much time will be devoted to them in the coming weeks.

My best guess is that I will have the DotNetNuke beta out by the end of August. That should be followed relatively quickly with the release of GSP 2.4, which contains the multiple gallery feature I am talking about here, some bug fixes, and some great new properties on the Gallery user control that website integrators will love. I will also try to squeeze in some high-value, easy-to-implement feature requests.

Once the DotNetNuke module and 2.4 is out, I plan to implement those top features requests you have:

  • Tagging
  • Better upload experience – especially the ability to upload a compressed version of an image rather than the original
  • Extract video thumbnails
  • Advanced sorting
  • Much more…


Dave Burke said...

Thanks for providing such a detailed description of what's coming, Roger. Looking forward to adapting to the new way of doing things.

Best regards,

RustyTools said...

I'm so excited to see you are continuing to work on the DNN integration! Can't wait for the beta and thanks for the great update.