by Nik Kalyani
Sunday, February 27, 2005 10:39:34 AM (Pacific Standard Time, UTC-08:00)
pmgerholdt asks:
If you could field a newbie question - I have your "My Modules" solution open in VS. Say I start a VB Web Project. I can do that much - build a web project. How then do I get it to appear in DNN? Do I have to copy files to a zip file and load it via DNN's interface for modules? Or does it automagically appear in DNN by virtue of sharing its space? (That's why I recompiled DNN - I thougth your RandomImage Mod would become part of DNN ...)
And is there a difference between a module and a PA ... or is a module an instance of a PA - or is a PA one way of making a module while there are others?
Aside from just building from scratch, I've seen three approaches. Yours looks most simple and direct to me if I can get past the fact that I don't understand some essential basics. I've also looked at Bo's instructions and gone a ways down that road. But that really is extending the core, isn't it, rather than providing modules? Finally there are the code templates on DNNJungle.
Am I right in seeing these as three different approaches toward a similar goal?
Nik's answer:
Newbie questions are good. They force new synaptic links.
To answer your first question, there is no co-relation between the process of adding modules (controls) to the DotNetNuke DesktopModules folder and the module listing in your DNN portal. It would be nice if this happened automagically, but the unintended consequences would not be pleasant. For this reason, you must do one of the following to have a module appear in the listing:
1) Add it manually: This is the quickest way, especially when you're developing. Login as Host, and go to the Module Definitions page. Create a new Module definition and add the controls corresponding to your module to this definition. (I have intentionally left this description vague as it is a topic that deserves its own item.) Once this is done, your module will appear in the Modules Listing.
When you use the My Modules approach, you only need to build the custom module you are working on at that time. If you have a reference to your project from the _DNNStub project as recommended in the instructions, the important task of ensuring that your module's PA (private assembly or DLL) is correctly placed in the DNN "bin" folder is automatically handled.
Anyway, adding the Module Definition is all you need to do. After this, you can go to a portal page and add the module to the page. At this point, you will realize that you goofed somewhere. I have no statistical evidence, but I am inclined to believe that no one has ever created a module (that does anything worthwhile) that got displayed the first time it was added to a page during development.
There are a multitude of things that could be wrong. The most likely -- a problem in your ascx script file. This is where the DNNDebug.aspx script that's included is of use. Fire up a new browser window and call up the DNNDebug.aspx script. Type in the path to your control (example: ~/DesktopModules/ModuleName/somecontrol.ascx) and DNNDebug.aspx will tell you where the problem is. If it loads without error, then you know that the problem is in code-behind. Pat yourself on the back for successfully creating a working script with ASP.Net's mind-numbingly annoying syntax, and go back to VS.Net and your module's code-behind.
From here, you are on your own (unless you have a specific question).
2) Add it with the installer: This is a task best left for when your module is working beautifully on your development machine and you are ready for your ego to be crushed by end-users. Packaging a module for deployment basically involves zipping up the resources and creating a .dnn file. This is too detailed a topic to discuss here so I will (lazily) skip it.
Modules, PAs and Skin Objects
When a new platform evolves, so does its terminology. Often, to the chagrin of newbies as the terminology tends to make confusing some very simple concepts. Here then, is the non-authoritative guide to these terms:
Module: A module in the DNN context is a mini-application that runs within the DNN portal framework. It is a term that represents the composite product as viewed by users of the portals (regardless of whether they are host/admin/end-user). A module may consist of ASP.Net controls, assemblies, images, stylesheets, the kitchen sink, SQL script etc.
PA: PA is an abbreviation of "Private Assembly" and is a synonym for DLL (dynamic link library). .Net assemblies can be DLL's or executables (EXE's). Executables are standalone Windows programs, while DLL's need a host. In the case of DNN, the host is the ASP.Net engine. When you have an assembly that is stored in a (web) application's bin folder it is called a "private" assembly as it is usable only by that application. At this point, as an attentive reader, you are probably thinking, "oh cool...maybe there are also public assemblies?" Well yes and no. Public assemblies exist but to avoid the syntactic challenge of having the same abbreviation, public assemblies are called Shared Assemblies. They are stored in an area of your computer called the GAC (Global Assembly Cache) and are available to all applications. More about this here.
Skin Object: DNN skins can use standard ASP.Net usercontrols and components to enhance the portal. You can develop skins as HTML files (parsed and converted to ASP.Net user controls when uploaded), or you can bypass this process and code them as an ASP.Net user control (ascx) yourself. If you go the HTML route, there has to be a mechanism by which the HTML code can indicated how/where the ASP.Net usercontrols/components that are to enhance that skin are to be embedded. For this, DNN has an XML support file that must accompany the skin. Altogether time-consuming and quite useless. I recommend you create a skin as an ascx file from the get-go. It is not that different from HTML and is a lot easier to use and troubleshoot.
Anyway, coming back to definitions. My definition of "skin object" is "a term that is useless and should go the way of the Dodo." In all seriousness, why have a new term when ASP.Net usercontrol or ASP.Net component work. So when you see "skin object" just thing ASP.Net usercontrol or component.
Different approaches
I cannot speak for other people's work/resources. The "My Modules" solution exists for one simple reason -- to make it easy to develop modules if you have no interest in modifying the DNN core code. The solution provides clean upgradability, since when you upgrade the DNN code, you have to do nothing in the "My Modules" solution configuration. You will have to rebuild the solution and if there are breaking-changes in DNN itself, handles those in your code, but other than that, you no longer have to struggle with DLL conflicts and VS.Net cache issues while compiling. I have almost 50 projects and never see any DLL conflicts with this approach.
I will point out one thing that will help you distinguish how a resource is applicable. My approach falls in the realm of VS.Net "organization." A way to ensure that your VS.Net solution/project works with minimal headache and maximum efficiency. The other realm is VS.Net "development." Templates/scripts etc. are all aids to speeding up the process of development with the goal of creating an "end-user solution."
As developers, we frequently lose sight of the end-user. Although it is fun and challenging to play with code, ultimately most of us get a pay-check only if our experimentation produces a solution -- not a module, skin object, PA or executable -- but a solution, for the end-user. I encourage you to use as many resources others have generously made available to create a development environment that accelerates solution development by allowing you to focus on the task and not the tool.
Peer I/O out.
by Nik Kalyani
Sunday, February 27, 2005 9:33:16 AM (Pacific Standard Time, UTC-08:00)
I frequently get emails from random people asking me questions about random issues, mostly technical. I am extremely curious by nature and have a hard time leaving a technical problem unsolved and so I end up finding an answer. It's a good way to learn new things and also hone problem-solving skills.
Since the knowledge gained is lost in that email transaction, I have decided to formalize the process and make it part of my blog. If you have a technical question, email me at asknik ATnospam speerio.net. I will try and post an answer to interesting questions in the Ask Nik category of my blog.
by Nik Kalyani
Saturday, February 26, 2005 10:47:53 PM (Pacific Standard Time, UTC-08:00)
Making progress. I now have DasBlog running as an app but in the same app space as DNN 3. I put it into ~/DesktopModules/DasBlog.
Most of the work today was in getting the VS.Net solution setup so file and assembly references work correctly. The result is a VS.Net solution called DasBlogDNN. I can build it and all the assemblies get correctly deposited into the DNN bin folder.
I am particularly excited by the shared app working correctly. As you may already know, it is a pain to get another ASP.net app to work in a DNN sub-folder. That's because of the HttpModules referenced in the DNN web.config. Because of how ASP.Net manages child apps, in order to get an ASP.Net app to work as a DNN child app, you have to do two things:
1) add a <clear /> element in the <httpModules> section
2) add all the DNN HttpModule assemblies (and referenced assemblies) into the bin folder of the child app.
This sounds counter-intuitive, but that's what has to be done to make it work. Basically, when ASP.Net starts initializing a child app, it first attempts to load all HttpModules declared in a parent app. This is why you need the assemblies in the child app bin folder. Once it encounters <clear /> those assemblies become irrelevant.
Anyway, because of all this craziness, to setup DasBlog as a child app, I would have had to copy all the DNN HttpModules into the DasBlog bin folder. Ugly any way you look at it.
After examining both web.configs (DNN and DasBlog), I managed to get all the relevant DasBlog items ported over to the DNN web.config. Then I had to change a boat-load of relative paths (in script and code-behind) to account for the new app root. Now I have DasBlog running inside the DNN folder.
Next step: integrated authentication.
by Nik Kalyani
Friday, February 25, 2005 2:52:41 AM (Pacific Standard Time, UTC-08:00)
A couple of days ago, I blogged about my VS.Net Solution for DotNetNuke that allowed me to work on custom modules without making my solution file bloated with unnecessary DNN project references. After I posted about this in the ASP.Net forums, I got quite a few questions and comments. This led me to investigate further and see if it was possible to create a DNN development environment that would leave the core package untouched, yet allow you to develop your modules without having to worry about file references.
After several iterations, I believe I have a good solution. I have decided to call the solution "My Modules." Here is how it works:
1) The "My Modules.sln" file resides in the root of the DNN folder. It consists of one required project and as many custom module/control projects you wish to add to it.
2) The required project I have named _DNNStub. This is a VB web project that is so named because it will always appear at the top of your list of projects. The only purpose of this project is to have a startup project for the solution. The project has one file -- Default.aspx. This is the standard (unmodified) DNN Default.aspx file. In the file properties within the solution, the compile option is set to "None". This file is included so the solution can have a startup page for debugging.
3) You may now add any of your custom modules projects from DesktopModules to this solution. I prefer to use web projects because I can easily add web-related resources to my project without resorting to tips/tricks. Also, once I load VS.Net, I have it open for days on end so the issue of load-time (which is frequently cited as a reason not to have web projects) is not relevant for me.
4) Whenever you add a custom module project, you must remember to add a reference to this project from the _DNNStub project. This will ensure that whenever you recompile, your compiled assembly will be placed in the root "bin" folder where it belongs. Alternately, you can set your project to build directly to the root "bin" folder. However, this may cause file locking problems and is not something I would recommend you do.
I have packaged everything you need into the Speerio My Modules zip file that is attached to this post. As an added bonus (and to prove that my solution really works), I have also added two custom modules projects -- one C# and one VB.Net to the package. I have also added one webcontrol C# project. Here's the 411 on these:
- Speerio RandomImage Module: This is a C# DNN module project. This module will randomly display one image from a folder of images. As a shortcut to creating a settings page, I coded the module so that it looks for images in a sub-folder based on the title of the module. So if your module's title is "Random Images," it will look in portals/{portal id}/Random Images. The complete source code for this is included and you may do with it what you wish. If you just want to install the PA, use the included zip (in the root).
- Speerio WeatherOutlook: I have setup a Speerio webservices server with some free webservices. One of these is a simple weather service. To illustrate use of webservices in DNN modules, I have included the Speerio WeatherOutlook module. This module will display the 7-day weather outlook for any U.S. zip code (sorry to others). It calls the Speerio Weather webservice at http://speerio.ws/Weather/Weather.asmx. Same as the Random Image module, full source is included, but in VB.Net
- Speerio Stock Quotes control: Another freebie in the package, is the Speerio Stock Quotes control. Written in C#, this calls the Speerio StockQuotes webservice at http://speerio.ws/StockQuotes/StockQuotes.asmx. A test page is included called Test.aspx.
Finally, I have included a script called DNNDebug.aspx in the package. I use this script anytime I see a parser error because it tells me that something is amiss in my ascx file. DNNDebug will let you load any ascx control and will display the exact error message that is preventing it from loading. Within the DNN environment, this message is obscured by the skinning engine and you see a generic parser error. I am confident this script will save you many hours of debugging. It has saved me on countless occasions.
I have tested all of these as best as I can, but it is possible that I have overlooked something. If so, please let me know so I can fix the problem.
Enjoy, and happy DotNetNuking!!! Speerio My Modules.zip (110.12 KB)
by Nik Kalyani
Wednesday, February 23, 2005 4:12:06 PM (Pacific Standard Time, UTC-08:00)
I like to do my DotNetNuke development treating DNN as a black-box. With version 3.x, DNN has around 50 projects and to use any of the solutions in the package is time-consuming as they contain projects that are rarely needed during module development. Is there a way in which you can keep your module development separate from DNN, maintain references to controls etc. in your module script files and maintain a way to easily upgrade? I believe there is and I have been working with such a setup for a couple of weeks now, and everything seems fine. Before I describe my solution, a few things to note:
1) This works for me. Your mileage may vary.
2) I do all of my development in C#. I did however test this with a VB.Net module and it worked fine.
3) Unlike what a lot of other DNN experts recommend, I do not setup my modules as Class projects. I prefer to set them up as a web project because it gives me the ability to use all the web capabilities of VS.Net without messing around with registry keys and such. It takes only a few seconds to remove the application flag from the IIS MMC when VS.Net creates the module project and this is too small an inconvenience to forego all the benefits of having a web project.
OK, now for my solution.
I first created a new Solution in VS.Net. I named my solution DNNDev and created it in my existing DNN3 folder. VS.Net wants to put a new Solution in a folder with the Solution name, so I exit VS.Net, moved the DNNDev.sln and DNNDev.suo files to the DNN3 folder and then deleted the DNNDev folder. Now, I had my DNNDev.sln file in the same folder as the DotNetNuke.sln file.
The next thing I did was make a copy of the Default.aspx file. I named my copy DefaultOriginal.aspx. I then opened up Default.aspx in Notepad, and removed the CodeBehind attribute of the Page directive. (This is the only change to the DotNetNuke package that my solution requires.)
I opened up DNNDev.sln in VS.Net and added a new VB.Net web project. I named the project DNNShell and created it in the DNN3 root folder. I deleted the AssemblyInfo.vb, Global.asax and WebForm1.aspx files that VS.Net automatically created. I then removed the project from the DNNDev Solution, saved the solution and exited VS.Net.
Next, I moved the files DNNShell.vbproj and DNNShell.vbproj.webinfo that VS.Net put into a DNNShell sub-folder, into the DNN3 root folder and deleted the now useless DNNShell sub-folder. I edited DNNShell.vbproj.webinfo with Notepad and fixed the project URL reference to exclude DNNShell from the path.
I then re-opened DNNDev.sln in VS.Net and used Add Existing Project to add DNNShell back to the solution. With this setup, I am now able to add my custom module projects to DNNDev Solution, and treat DotNetNuke as a black box. Each time I add a custom module project to the Solution, I add a Project Reference to that project in the DNNShell Project. This ensures that my custom module's assemblies end up in the DNN3 bin folder.
That's all there is to it. You can now develop/debug without any regard for assembly conflicts or have to wait for projects to load up in VS.Net.
If anyone wants it, I will be happy to package up my solution files so you can zip and go...
by Nik Kalyani
Tuesday, February 22, 2005 5:29:13 PM (Pacific Standard Time, UTC-08:00)
A large number of DotNetNuke portals have a dependency on third-party modules. Being a "third-party module developer," I am interested in finding out how much of an impact modules make on the decision to upgrade to DNN3.
If every module you use on your DNN 2.x portal has a 3.x-compatible version available (for free) on the day DNN 3.x is released, would you upgrade your portal to DNN 3.x?
by Nik Kalyani
Tuesday, February 22, 2005 5:24:30 PM (Pacific Standard Time, UTC-08:00)
There is a lively discussion on the DotNetNuke Core Team forums about DNN stylesheets. If there is one area of DNN that I don't care much for, it would be in how DNN handles stylesheets. It's a bit messy and leaves even the most CSS-savvy designer scratching their head about how/where/why a particular style was inherited by a particular element.
Personally, I don't think there is a need for host, portal, skin, container and module stylesheets. There should be one stylesheet used on the page and that is the skin stylesheet. All classes required by a page where the skin is applied should be defined in this stylesheet. While this may require a bit more work, it is definitive and portable.
by Nik Kalyani
Saturday, February 19, 2005 12:17:29 PM (Pacific Standard Time, UTC-08:00)
Continuing my quest to have a fully-integrated version of DasBlog with DotNetNuke, I have made some progress.
My original intent was to leave the DasBlog core untouched, but as I poked around, it became clear that this is not to be. I started by putting the DasBlog source in a folder structure that would allow seamless conversion of the DasBlog aspx pages to DNN controls. I created something like this:
/DotNetNuke/DesktopModules/Speerio_DasBlog/{main DasBlog web files}
/DotNetNuke/DesktopModules/Speerio_DasBlog/SiteConfig
/DotNetNuke/DesktopModules/Speerio_DasBlog/Themes
etc.
After several false starts in getting the IIS application mapping correctly, I had a DOH! moment. I moved the DasBlog web.config into /DotNetNuke and made /DotNetNuke into an application. That worked...almost...got a bunch of compiler errors, but at least I was making progress.
The source of the errors was that in several places in the code, DasBlog uses Server.MapPath("somefolder/somefile"). Of course, this doesn't work too well if it's not in the app root. Time to break out the trusty and hard-working Search and Replace and replace all such instances with "~/DesktopModules/Speerio_DasBlog/". Lift-off!? Nope...no such luck. Ran into an annoying VS.Net bug that prevents strong-named assemblies from working properly some of the time. Google says lots of people are having the same problem and the known solution is to not have strong-named assemblies (what kind of solution is that?) or build twice. The assembly in question is FTB and since I am not at the point where I can yank it out, I opted for the build twice.
After more of this, I now have DasBlog working using the revised folder structure. Next step, blow away the DasBlog security and have it look to the HttpContext instead.
by Nik Kalyani
Friday, February 18, 2005 1:50:51 PM (Pacific Standard Time, UTC-08:00)
Although my graphic illustration skills range from crappy to mediocre, on occasion, I will surprise myself by creating something that looks cool. For the longest time, I used a program called Xara. I then switched to Illustrator when I got a discounted license. I have never really liked Illustrator, because although it is very powerful, the tools are not intuitive. Once you RTFM and figure it out, it seems obvious, but I have had to do it often enough now that I am fed-up and have decided to switch back to Xara.
Since I last used it (about two years ago), Xara has evolved signficantly and there are now a number of features that make web graphics amazingly easy to create. I am switching back. So long Illustrator.
by Nik Kalyani
Thursday, February 17, 2005 9:11:32 PM (Pacific Standard Time, UTC-08:00)
Although I don't rent from BlockBuster, a news story on the D.C. NBC affiliate caught my eye. To stem the steady flow of customers to NetFlix, BlockBuster recently changed its late fee policy. Heavily publicized in a TV campaign, the ad clearly communicated the message that BlockBuster no longer charges late fees. Turns out that's only half the story.
If you don't return the movie within seven days, on the eighth day you own the movie. Your credit card is charged at the time. You can supposedly come into the store within 30 days and get back the money less a re-stocking fee.
What a scam!
by Nik Kalyani
Tuesday, February 15, 2005 9:03:26 PM (Pacific Standard Time, UTC-08:00)
Well, it's official. I am writing a book for Packt Publishing on DotNetNuke Module Development Techniques.
by Nik Kalyani
Monday, February 14, 2005 3:55:15 PM (Pacific Standard Time, UTC-08:00)
So what's up with Yahoo and MSN? Are their designers collaborating behind the scenes or are they just oblivious to the competition. Check-out the home pages (the category area). It is hard to believe that's coincidence, and if it is, someone is not doing their homework...

by Nik Kalyani
Monday, February 14, 2005 10:00:38 AM (Pacific Standard Time, UTC-08:00)
Fooling around with the Technorati API, I chanced upon Touchgraph. I know hyperbolic visualizations have been around for a while since PARC first published the concept, but Touchgraph is something else. I am amazed at the fluidity of the nodes. The TG GoogleBrowser gave me more information about my site than pages of standard Google results.
I have always been an avid follower of social networks and after reading Linked I became much more interested in scale free and social networks. Touchgraph makes me wonder if existing dating sites have it all wrong. I think the efficiency and accuracy of matchmaking can be greatly increased by combining social networks and visualization technology like Touchgraph. I may have to start a project to explore this.
by Nik Kalyani
Saturday, February 12, 2005 12:00:20 PM (Pacific Standard Time, UTC-08:00)
The Apollo moon landing high-res pictures have been stitched into QuickTime VR movies.
http://www.panoramas.dk/fullscreen3/f29.html
by Nik Kalyani
Saturday, February 12, 2005 9:26:26 AM (Pacific Standard Time, UTC-08:00)
As I prepare new releases of my modules for DNN 2.x, I am trying to add as many features as possible that will make the transition to DNN 3.x easy. One of these is localization. DNN 3.x uses non-compiled .resx files to store localized resource strings. The files are stored in sub-directories of the control to which they apply.
This is all quite good because it allows different modules to be installed with their supporting resx files. However, after careful consideration, I decided I am not going to follow this route for any Speerio products. There are two reasons for this:
1) The resx format is too verbose for my needs and does not offer any significant advantage to a standard XML file other than the ability to store binary resources.
2) The location of files is difficult to manage. I think grouping of files by locale is more logical than grouping based on the control the file belongs to.
So, I have created the Speerio.Web.Globalization class which I can use interchangably in DNN 2.x and DNN 3.x. The file format is very simple:
The file is named {AppName}.locale.xml (example: FileManager.en-US.xml)
All files go into ~/Controls/Speerio/Globalization/{locale}
Example: ~/Controls/Speerio/Globalization/en-US/FileManager.en-US.xml
Now, when I am ready to have a Spanish version of my modules, I have to copy the contents of the en-US folder into es-US, rename the files to include the correct locale, zip up the folder and email it to the translator. With a handy batch file and using the cool command line WinZip add-on, I can do this in about a minute. When the translated files arrive, I unzip them back into the folder and I am done.
I am assigning each Speerio control a "Locale" property. Once set, this will ensure that the correct language file is read and cached (by a class that inherits from DictionaryBase and caches based on a filedependency on the xml file). The property also
I am not sure my way is better. From a performance standpoint, there is no difference since after first request strings are read from cache. But I do think my way is easier to manager and more intuitive. Besides it gets me localization in DNN 2.x and DNN 3.x.
by Nik Kalyani
Wednesday, February 09, 2005 7:36:12 PM (Pacific Standard Time, UTC-08:00)
Google is making a strong play into the mapping area. First, there was the acquisition of Keyhole, which I must confess, is mind blowingly cool. I have spent a lot of time looking at the cool satellite imagery of the globe. (Not surprisingly, the top of the White House and the Fort Meade area have detail removed.)
And, now Google Maps. It is amazingly fast and the ability to drag the map around is a fantastic usability improvement.
by Nik Kalyani
Wednesday, February 09, 2005 12:36:15 PM (Pacific Standard Time, UTC-08:00)
Today has been frustrating. I have been looking for a decent component that can accept a URL and generate a PDF. There are many available, but they all have server-based licensing. Does anyone know of a component that will do that, has royalty-free licensing and costs less than $1,000?
by Nik Kalyani
Monday, February 07, 2005 11:10:19 PM (Pacific Standard Time, UTC-08:00)
I recently switched to Das Blog as my blogging software and so far I am loving it. It has all the features one expects and then some.
Since DotNetNuke lacks a good blogger, I have started a project to make Das Blog into a DNN module. There are several challenges to this, and over the coming weeks, as I delve deeper into this project, I will document my findings here.
Just to be safe, I asked Omar Shanine for permission, and he was kind enough to grant it.
So off we go...
by Nik Kalyani
Sunday, February 06, 2005 5:50:33 PM (Pacific Standard Time, UTC-08:00)
by Nik Kalyani
Sunday, February 06, 2005 5:46:11 PM (Pacific Standard Time, UTC-08:00)
|