Last weekend I attended a local .NET Developer conference - the St. Louis Day of .NET. It was a regular work day (9-5) of .NET-centric one-hour sessions. Most of the sessions were based (to varying degrees) on content from the recent Professional Developer's Conference (PDC) in Los Angeles.
There were two main reasons I couldn't pass it up, aside from the fact that there were going to be a few interesting sessions. The first was that Engage Software was one of the sponsors, so I wanted to represent our company at the conference. The other reason was that it was located in Washington University's CAIT Facilities in Clayton, MO about 1.5 miles from my house. If I was going to get up early and do "work like stuff" on a Saturday - at least it was close!
I was impressed at how well the conference was put together. The three guys responsible (Kevin, Jeff, and Scott) rounded up BusyEvent to help with the details. I must say it worked out very well. Registration was especially painless, and except for hearing groans about running out of coffee at one point, I didn't really hear anyone talking about logistics of any kind, just the sessions (which is a good thing). Thought I haven't been to too many conferences, I get the sense that people not complaining about the logistics is unusual. So kudos to everyone who helped put this one together.
New ASP.NET Stuff
The session I enjoyed the most was on a subject that I'm already a bit familiar with - ASP.NET 3.5 SP1 New Features. The speaker was knowledgeable, the presentation was straightforward, the demos worked, the content was relevant -- it was everything I could want out of a presentation/session.
The session really consisted of introductions to the ADO.NET Entity Framework, ADO.NET Data Services, and Dynamic Data. I am really excited for these technologies to become more mainstream (and no matter how they stack up compared to non-Microsoft-issue tools doesn't even really matter because it's a ton better than hand coding or using DataSets for everything!)
The Entity Framework (EF) hit home for me, because I've been writing data access layers from scratch for a few years now and I'm really looking for something to do all that busy work for me. Given that EF is supposed to be Microsoft's Way Forward in the ORM Space and that it looks to be pretty quick and painless to use - I'm ready to dig in.
I'm going to be experimenting a bit over the next week and will sum up the results in presentation format for the rest of the Engage crew before we leave for Christmas break. If you're lucky I'll share with you as well. I'm especially interested in figuring out how to make it work well in the DotNetNuke world.
A related side-note - Brandon Haynes has what looks to be a fun little project going on CodePlex.
Design? Design!
In addition, I attended the Windows 7: Design Principles for Windows 7 session. This was a great session because I got to see that Microsoft is finally catching on. Things that seem trivial or minor simply aren't. Your product is evaluated not just by functionality but by the experience and how the product makes the user feel.
This is great news because I personally believe that the flexibility complexity of Windows is what your grandma is really scared of - not the fact that it's a computer and all technology is scary - Windows itself can be pretty scary!
The tweaks that they've done to the Windows operating system for Windows 7 are very subtle and each are pretty minor on their own, but when you add things up, we're going to get a much better experience out of the next OS - about time! Check out the video (wmv) from the original PDC talk.
Other Sessions
I also went to the Expression Blend 2 Tips and Tricks session, which was cool because I haven't messed with Expression Blend at all yet. I did get a better feel for the tool through the presentation, and some insight into some of its capabilities. One of my favorite ways to learn is by watching someone who is better than me, and even watching the presenter click around a bit helped me get my head around the features. Now I wish I had an excuse to fire Blend up at work!
Finally, I caught the first 1/3rd of the Future of C# session before I headed out. It was a very promising topic, as it's something I'm very interested in, but because it was packed (standing room only), hot, and the projected image of the presenter's computer wasn't even viewable (by me) from the back of the room, so I ducked out early. I did see the part about how dynamic languages are all the rage, and that (better or worse) C# 4.0 is headed, in-part, in that direction. Cool. I'll keep an eye on my Google reader for updates :)
Until next year STLDODN! Oh yeah -- check out what twitter folks are saying about the conference.
If you went - what sessions did you see? What were your thoughts?
In Improving the Secured File Download UX for Unauthenticated Users I elaborated on a workaround hack to display a friendly error message and redirect to the login page when trying to access a file that had been through DotNetNuke's file ticket system.
If you're in a situation where that solution makes sense for you - great. But what about future releases of the application? Should this functionality exist within the framework itself? Is it too trivial? Does it make sense for everyone that uses the framework so much so that it should be a part of it?
To find out, I put the issue in DotNetNuke's Gemini.
I suggest that when you encounter a workaround/hack/enhancement such as this:
- Don't just fix it for now
- These "fringe areas" are one of the places where the "community at large" can be of most help. Let the core team focus on the big stuff.
- So...put it in Gemini!
- And, ideally, try to give the core team a head start.
So, in an effort to follow the above path, I cracked open my handy DotNetNuke source code and made a few changes.
update: I'm providing the following information for reference only, I really don't think you should make this change to your DNN application. My intention is just to remind you that the core code is there, we can easily make changes, test them out, and suggest to the DotNetNuke team that they incorporate those changes into the application.
Background
When the user requests the file, the LinkClick.aspx "page" is requested. (e.g. "http://localhost/DotNetNuke_2/LinkClick.aspx?fileticket=XKDsP6pHvtQ=&tabid=36&mid=410"). This really isn't a page, but is a handler registered in the application's web.config.
The actual class that handles the file request is called "FileServerHandler" and is found in Library\Components\FileSystem\FileServerHandler.vb in version 4.9 and \Library\Services\FileSystem\FileServerHandler.vb in DotNetNuke 5.0 RC2.
While some slight refactoring has been done to this class between 4.9 and 5.0, the portion we're concerned with has not changed:
' serve the file
If TabId = Null.NullInteger Then
If Not FileSystemUtils.DownloadFile(_portalSettings.PortalId, Integer.Parse(UrlUtils.GetParameterValue(URL)), blnClientCache, blnForceDownload) Then
context.Response.Write(Services.Localization.Localization.GetString("FilePermission.Error"))
End If
Else
If Not FileSystemUtils.DownloadFile(_portalSettings, Integer.Parse(UrlUtils.GetParameterValue(URL)), blnClientCache, blnForceDownload) Then
context.Response.Write(Services.Localization.Localization.GetString("FilePermission.Error"))
End If
End If
The above code is responsible for the original behavior of showing the localized file permission error message.
Goals for Improvement
If the user is not able to download the file:
- If they are not logged in, let's take them to the current portal's login URL with a return URL for the file ticket.
- If they are logged in, display the localized FilePermission.Error message, as usual.
Adding a Utility Method
First, let's add a method to help us get the current portal's login URL:
Private Function GetLoginUrl(ByVal portalSettings As PortalSettings, ByVal request As HttpRequest) As String
If Not portalSettings Is Nothing AndAlso Not request Is Nothing Then
Dim tabId As Integer = portalSettings.ActiveTab.TabID
Dim controlKey As String = "Login"
If Not Null.IsNull(portalSettings.LoginTabId) AndAlso String.IsNullOrEmpty(request.QueryString("override")) Then
controlKey = String.Empty
tabId = portalSettings.LoginTabId
ElseIf Not Null.IsNull(portalSettings.HomeTabId) Then
tabId = portalSettings.HomeTabId
End If
Return DotNetNuke.Common.Globals.NavigateURL(tabId, controlKey)
Else
Throw New ArgumentNullException(If(portalSettings Is Nothing, "portalSettings", "request"))
End If
End Function
This method is intended to yield the correct login page whether a custom one is specified or not. It could potentially use the current tab, or the home tab as well. Just playing it safe.
Adding the core enhancement
Now, we need to figure out whether or not the user is logged in, and perform one of two actions. Either redirect them to the login page, or let them know that they don't have sufficient privileges to view the file.
Private Sub RedirectToLoginOrDisplayErrorMessage(ByVal context As HttpContext, ByVal _portalSettings As PortalSettings)
If (context.Request.IsAuthenticated = False) Then
Dim loginPage As String = GetLoginUrl(_portalSettings, context.Request)
Dim returnUrl As String = HttpUtility.UrlEncode(HttpContext.Current.Request.Url.PathAndQuery)
context.Response.Redirect(loginPage + "?returnurl=" + returnUrl)
Else
context.Response.Write(Services.Localization.Localization.GetString("FilePermission.Error"))
End If
End Sub
Wiring it Up
Now, without changing the original code much, we can replace a couple lines of code, set a few break points, and try this thing out.
' serve the file
If TabId = Null.NullInteger Then
If Not FileSystemUtils.DownloadFile(_portalSettings.PortalId, Integer.Parse(UrlUtils.GetParameterValue(URL)), blnClientCache, blnForceDownload) Then
RedirectToLoginOrDisplayErrorMessage(context, _portalSettings)
End If
Else
If Not FileSystemUtils.DownloadFile(_portalSettings, Integer.Parse(UrlUtils.GetParameterValue(URL)), blnClientCache, blnForceDownload) Then
RedirectToLoginOrDisplayErrorMessage(context, _portalSettings)
End If
End If
Summary
Mission accomplished. Now to see if it gets picked up anywhere along the way. Let me know what you think of this enhancement or the process in general. Also, I did enjoy picking apart this one trivial thing, so if you have any suggestions for future experiments, please let me know.
DotNetNuke has extensive security features. One of which is enforcing role based permissions when accessing files. The general workflow is to say that "Registered Users" get to see a particular file, you then create a link to that file using DNN, and as a matter of course, the roles are enforced. This uses what's known as a file ticket to request the file, so that it is not linked to directly.
This is great if you are only providing those links to currently authenticated users. However, if you want to provide these links to unauthenticated users, you get a pretty unfriendly experience. Granted, this is an edge use-case, and an argument could be made against doing this in the first place, but every project is different, and this just might make sense for you.
Background
There are a couple of ways to get yourself into this situation - the one I set up was the following:
- Drop a links module on the page,
- add a new link to a file
- Go to the file manager, and make that file's folder available only to registered users.
- Make sure the module is visible to all users
Currently, in DNN 4.9, you get a blank white page (even if you view source) with the following content:
You do not have permission to view this file.
Getting better
We could easily make that better by localizing it with a link to the login page. This improves the user experience a little bit. But really, we can put anything we want in here. Including a full HTML page with web site branding to give the user a more pleasant experience.
The value to localize can be found in GlobalResources\SharedResources.resx under the "FilePermission.Error" key. Note that any time you make a change to this file, the app restarts. So try to be patient when making changes.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Temporary Page</title>
</head>
<body>
<p>Dear user, please <a href="http://localhost/dotnetnuke_2/Home/tabid/36/ctl/Login/Default.aspx">Login</a> to view the file you have requested. Thanks, Admin.</p>
</body>
</html>
Actually useful?
To take it a step further, we could add a timed redirect to the page, using a meta refresh. This will give the user the ability to see a custom informational page, as well as automatically be redirected.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Temporary Page</title>
<meta http-equiv="REFRESH" content="10;url=http://localhost/dotnetnuke_2/Home/tabid/36/ctl/Login/Default.aspx" />
</head>
<body>
<p>Dear user, please <a href="http://localhost/dotnetnuke_2/Home/tabid/36/ctl/Login/Default.aspx">Login</a> to view the file you have requested. You will be redirected in 10 seconds. Thanks, Admin.</p>
</body>
</html>
Probably a lot better now...
Now, if we wanted to get really fancy, we could ditch the meta refresh, and enhance our HTML page to use JavaScript to redirect. The great benefit of this is that we can tack on a returnurl parameter to our redirect with the file ticket's URL. This will tap into the core login behavior and deliver the appropriate content after the user has logged in.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Temporary Page</title>
<script type="text/javascript">
<!--
function redirectToLogin() {
var l = document.location.href;
if (l.toLowerCase().indexOf("fileticket") != -1) {
var virtualDirectory = "";
var loginPage = "/Default.aspx?ctl=login&returnurl=";
var returnUrl = encodeURIComponent(l.substr(l.lastIndexOf("/")))
window.location = "/" + virtualDirectory + loginPage + encodeURIComponent("/") + virtualDirectory + returnUrl;
}
}
-->
</script>
</head>
<body onload="setTimeout('redirectToLogin()', 5000)">
<p>Header with site branding, navigation</p>
<p><a href="javascript:redirectToLogin();">Dear user, go to the login page!</a></p>
<p>Footer with site branding, navigation?</p>
</body>
</html>
There are a few things that you may want to modify above for your implementation:
- timeout (on body onload)- this is how fast your page will redirect to the login page/control. If you don't want a "landing page", set this to 0.
- virtualDirectory - if you are using a virtual directory (e.g. http://localhost/dotnetnuke_2/), you'll want to set this to "dotnetnuke_2"
- loginPage - relative link to the login page/control
Summary
When we want to provide a link for unauthenticated users to a file and enforce role security, we now have the ability to:
- provide that user with more information when they click on the link
- implement consistent branding on that informational page
- automatically redirect them to the login screen
- supply a return URL so that after they login, they are taken directly to the file.
As this is just a quick and dirty implementation, I'd love to see someone with a need for this actually make it awesome. (yes, that's right...I don't even have a project to implement this on...)
And as always, if you have a project to share with the community, you should submit it to dnnGallery!
A note about unwanted redirects
One catch with the meta refresh is that the DNN language editor shows you a preview of the content. So after you localize it with a meta refresh the first time, ever subsequent time you visit the SharedResources language file in the editor, the page will redirect.
I don't think the same is true of the JavaScript, but because different browsers could handle this differently, I went ahead and included a check so that the JavaScript redirect will only occur if the URL contains "FileTicket". Feel free to experiment.
This post is overdue. I wanted to use this image in my slide deck for a presentation I gave last month at the Bloomington, IL .NET user group, but...it really detracts from the look & feel of the presentation as a whole makes my eyes bleed when I look at it. So anyway...I have a friend in the business of making things look good, so I'll share the wealth.
Original:
New:
There's no excuses for using the old version anymore. Thanks Dang!
The current provider model in DotNetNuke is very flexible, but with that flexibility comes development overhead. Over the past few months I've started thinking about how much time I spend simply on [easy, repetitive] data access tasks, and its a little depressing.
I'm at the DotNetNuke OpenForce conference right now, and today I went to Jim Bonnie's presentation on data access layers in DNN. He likes to use SubSonic instead of doing everything manually. He presented NHibernate, Entity Framework, Linq to SQL, and many others as options for your data access layer. The bottom line of the presentation is that there are a lot of time saving solutions out there, and that we should probably just pick one we like and go with it.
Awesome. Let's do it.
But... we've been talking about this at the office for awhile, and there are a couple of things that I (as a commercial module developer) am not quite comfortable with yet. I have a lot of questions. Please let me know what you think. If you're at OpenForce, track me down because I'd love to talk about it.
Dependencies
If we want to create a module with any of these data access layer solutions do I have to include any new assemblies with my project? How many support issues will surface because someone else has a different version of it? How does the inclusion of the assembly impact the file size of the module package? Can the customer still upload this to a DNN site?
{databaseOwner} and {objectQualifier}
Does said solution support {databaseOwner} and {objectQualifier}. I know people use this stuff, but how many?
Provider Model
Who uses an Oracle or MySQL provider? Would they want to buy my module? Do I care? Is it really such a horrible thing to just flat out not support this because it's not worth the trouble? Is this a piece of information I can/should share
Big Picture
Is it appropriate to explain the lack of support for a particular nitty-gritty feature in pre-sale product documentation? How many customers would read it and know what it means? Can I live with the fact that some people might not realize the module won't work, so they effectively get a broken product?
How many people are not going to be able to use my module because of the decisions I made? How many people are going to request support because of issues that arise based on the decisions I made? Am I going to save development time, only to add that time back on in the form of support because of the decisions I made?
- Your latest DNN module utilizes in-line CSS like it was going out of style.
- You frequently need to release new versions due to changes that consist solely of updates to hard coded strings in your code-behind.
- Every time you implement your modules as part of a new solution, you spend the first few days just getting them to display correctly in the new skin
- You FTP into the production DNN site to upgrade your module.
- You spend more than 30 seconds packaging a new version of your module
- When you get a SQL script from source control you open up your favorite file comparison utility to see what’s changed so that you can run only those changes.
- You’ve been curious, for the last two years, about how to use the DNN UrlControl, but you never have the source readily available, so you still don’t know.
- The last time you upgraded your production environment you were up until 4AM trying to piece together outdated versions of your database.
- When creating your latest DNN module, you opened up the first DNN module you ever created to grab that same piece of code that you always grab when creating a new module.
I've installed a lot of DNN sites in the last couple of years, but this task just got even easier!
http://www.microsoft.com/web/channel/products/WebApplicationInstaller.aspx
The Web Application Installer Beta is designed to help get you up and running with the most widely used Web Applications freely available for your Windows Server. Web AI provides support for popular ASP.Net and PHP Web applications including Graffiti, DotNetNuke, WordPress, Drupal, OSCommerce and more. With just a few simple clicks, Web AI will check your machine for the necessary pre-requisites, download these applications from their source location in the community, walk you through basic configuration items and then install them on your computer.
The only down side is that it installed DNN 4.8.4 instead of DNN 4.9.
Here is the installation log:
[10/17/2008 9:09:55 AM] ----------------------------------------
[10/17/2008 9:09:55 AM] Start download the configuration file.
[10/17/2008 9:09:56 AM] Launch the app successfully.
[10/17/2008 9:10:00 AM] Download the configuration file completion.
[10/17/2008 9:10:00 AM] Start load the configuration file.
[10/17/2008 9:10:04 AM] The configuration file is valid.
[10/17/2008 9:10:04 AM] Load the configuration file completion.
[10/17/2008 9:10:26 AM] Change to the Select Application page.
[10/17/2008 9:10:48 AM] Change to the Prerequisites page.
[10/17/2008 9:10:49 AM] The prerequisite IIS has passed inspection.
[10/17/2008 9:10:49 AM] The prerequisite FastCgi has passed inspection.
[10/17/2008 9:10:49 AM] The prerequisite SQL Server or SQL Express has passed inspection.
[10/17/2008 9:10:49 AM] Change to the DotNetNuke Web Site page.
[10/17/2008 9:11:00 AM] Change to the DotNetNuke Configuration page.
[10/17/2008 9:11:45 AM] Change to the Application Prerequisites page.
[10/17/2008 9:11:45 AM] Testing SQL Connection on server localhost with uid sa
[10/17/2008 9:11:55 AM] Start download DotNetNuke
[10/17/2008 9:11:55 AM] Change to the Installation page.
[10/17/2008 9:12:10 AM] Download DotNetNuke successfully.
[10/17/2008 9:12:10 AM] Start extract DotNetNuke
[10/17/2008 9:12:23 AM] Extract DotNetNuke successfuly.
[10/17/2008 9:12:23 AM] Creating VDir with name DotNetNuker in site localhost, path=C:\inetpub\wwwroot\DotNetNukerMan.
[10/17/2008 9:12:23 AM] Began to add the default document "Default.aspx" for the web site localhost.
[10/17/2008 9:12:23 AM] Generating config file for DotNetNuke.
[10/17/2008 9:12:23 AM] Setting file system rights for file: C:\inetpub\wwwroot\DotNetNukerMan, user: IIS AppPool\DefaultAppPool
[10/17/2008 9:12:28 AM] Run the database script for DotNetNuke.
[10/17/2008 9:12:28 AM] Began to execute the SQL script. Database = DotNetNuker Server = localhost
[10/17/2008 9:12:33 AM] Change to the Summary page.
Pretty cool huh?
When creating a DNN module, you have the option to choose from the web site project (WSP), or a web application project (WAP). I prefer the web application project approach, and I'll explain it for developers who are new to module development, or unfamiliar with the WAP approach for developing modules.
There are two major reasons why I feel WAP is generally better than WSP for DNN module development.
1. Conciseness - the project contains only your module's code, nothing more. Separating your module from the DNN web site itself in Visual Studio really helps with performance and maintainability.
2. Compiled - I like having the code compiled into an assembly. This makes it easier for me to build a module package and distribute. I like to use a NAnt script for each module that creates the packages for me. The WAP project style lends itself to this approach.
If you'd like to give it a try - here are the steps involved.
- Create a new WAP project, or alternatively, use a C# DNN Module WAP Template
- Place the root of the project in the DesktopModules directory of your DNN development web site's file system (e.g. ..\DesktopModules\MyModule\)
- Set the project to build the assembly and place it in the "bin" directory of the DNN web site
- Set the project to launch your DNN web site (e.g. http://localhost/DotNetNuke) when you F5/run.
- In order for Visual Studio to know about your development web site, make sure to set your project to use your IIS server, and set the Override application root URL to the root of your web site. When you do this, Visual Studio knows that paths starting with "~" are really pointing to the DNN web site, and not just to your project. This makes it possible to include controls from within the DNN site, like the DNN Label or URL control.
After your module is set up, you can import it (by importing the .dnn manifest file) into your development site, and run any database scripts that the module may have. Your module is now fully integrated into your DNN site.
TIP: to debug the module, you may find it helpful to "attach to process" in Visual Studio while you already have the web site running in a browser. This saves you from having to launch the web site multiple times.
With the new skinning changes in DotNetNuke, it may be helpful to give an overview of available approaches to skin developers.
Each of these approaches attempts to answer the question "How do I embed and customize all that great functionality that DNN provides in my skin?" In other words, given that we have a pre-set base of options for functionality (core skin objects), and each of those options exposes certain customization points (skin object properties) that I'd like to set…how the heck do I get it done?
The answer may depend on which technologies you are familiar with (or willing to learn), but let's examine each of the different approaches and see if one clicks for you.
Note: For the sake of simplicity, I'm going to leave out the following buzz words: XTHML, CSS, table-based, and any other new age standards loving or old-school table defensiveness babble.
What's available pre-DNN 5
The "XML? I've heard of that!" approach
Technologies involved: HTML with DNN tokens, XML
Formula: HTML with DNN tokens + XML file with properties for each token = finished ASCX file
Background: Create an HTML file with tokens embedded, customize tokens with properties in an associated XML file. Package and upload to DotNetNuke. This method notably has two different file types that are used to pull together and generate a "real" skin file for use by DNN.
Benefits: It does not involve anything specific to ASP.NET or any other Microsoft technology for those that don't want to learn them.
Drawbacks: You have to maintain two files and use a DotNetNuke utility to parse the skin package every time you want to make a change. There is a fair amount of overhead associated with this approach.
Who's using it? This approach is very useful if you are a person who is comfortable with HTML and also comfortable with XML.
The Direct Approach
Technologies involved: HTML (without DNN tokens), ASP.NET Web User Controls
Formula: no math required!
Background: Create a user control in your application of choice and package it up with supporting files. Characterized by the ".ascx" file extension, lots of "<% %>" and runat="server" tags, this is, when it's all said and done, what DotNetNuke will use at run time.
Benefits: You can edit the file directly in your development environment without having to re-parse the skin package, which can lead to quite a bit of time saved if you are making frequent changes.
Drawbacks: You must be familiar with web user controls, the concept of embedding them in another user control, setting properties on those controls, and all the syntax and 'developer speak' that comes with 'em.
Who's using it? This is an approach used primarily by developers or those that are familiar with ASP.NET Web User Controls (ASCX files).
The Combo
Technologies involved: HTML with DNN tokens, ASP.NET Web User Controls
Formula: Generated "stub" ASCX file from HTML file with DNN tokens + revisions = finished ASCX file
Background: Create an HTML file with tokens, package up your module and then for each skin object, customize the generated user control with the properties you want to set.
Benefits: Quickly and easily generate the user control, and make changes to it directly within your development site and see them reflected immediately. Once you generate the HTML file, you leave it behind and only have to maintain one file (the .ascx).
Drawbacks: You must have a basic understanding of what ASP.NET elements NOT to remove from the user control when making changes to the file.
Who's using it? I speculate that people who are cranking out skins at high volume use this approach. They're probably the people that have been skinning for a long time.
The New Stuff
Now, there comes a new element to incorporate into our approach, if we so choose (I'm assuming that all of the other approaches are still valid, and that we're simply adding another one to the mix.)
The "Now with more friendliness" approach
Technologies involved: HTML with "uber-tokens"
Formula: HTML with skin objects and properties = finished ASCX file
Background: Create an HTML file with "object" tags that contain both a reference to the skin object to be used, and the parameters that allow you to customize that skin object.
Benefits: This approach allows you to avoid learning ASP.NET stuff and keeps you from having to create or maintain a separate XML file. This also uses the same syntax for including the new JavaScript widgets in your skin, which is a separate topic, but consistency is always good!
Drawbacks: I like HTML and all, but what is an "<object>"? I just got used to the skinning process, now you've changed it?
Who's using it? Nobody! It's not released!
Summary
So, we've learned there are multiple ways to skin a DotNetNuke site. In the end, it all comes down to what works for you. In the end, you'll probably either be creating a user control if you're a developer, or using the new skin object mechanism if you're not. But, if you like resisting change, you should be able to continue using the HTML/XML approach.
I would like to share with you information about the three St. Louis .NET related user groups that I attend:
St. Louis .NET User Group
This group generally meets the fourth Monday of each month.
St. Louis C# User Group
This group generally meets the second Monday of every other month.
St. Louis DotNetNuke User Group
This group generally meets the third Monday of each month.
Along with my coworker at Engage Software, Chris Hammond, I help facilitate the the DotNetNuke user group.
We've started pretty small but are getting more of a showing recently. In February the topic is Introduction to DotNetNuke Skinning. The presenter, Cuong Dang, also of Engage Software has deep knowledge of skinning with DotNetNuke and is also a very good presenter -- so it is my goal to get some more people out for this one!
See you out there!
Ian
More Posts