Verwendung der Client Resource Management API in einem DotNetNuke Skin

DotNetNuke  bietet ja seit der Version 6.x an das die CSS und JavaScript Resourcen (Dateien) zusammengefasst werden. Auf die Vorteile muss hier nicht im Einzelnen eingegangen werden - nur so viel: Es kann die Ladezeit einer Seite deutlich erhöhen. Bei der Erstellung von einem Skin legt man im Regelfall eine skin.css ein, die dann alle relevanten Formatierungsanweisungen beinhaltet. Wenn man nun externe CSS Dateien noch mit in das Skin einbinden möchte (oder seine eigene Struktur über mehrere Dateien verteilt) wird vielfach der CSS Befehl @Import genutzt. In diesem Fall werden die importierten Dateien nicht berücksichtigt bzw. mit in eine große Datei gepackt.  Damit weitere CSS Dateien (oder auch JS Dateien) berücksichtigt werden, muss man die DotNetNuke SkinObjects DnnCssInclude bzw. DnnJsInclude nutzen. Vor der Nutzung muss man noch die Komponente registrieren in der Skin-Datei, das passiert über den üblichen Weg: <%@ Register TagPrefix="dnn" Namespace="DotNetNuke.Web.Client.ClientResourceManagement" Assembly="DotNetNuke.Web.Client" %> Ein konkretes Beispiel für die Einbindung könnte dann so aussehen: <dnn:DnnCssInclude runat="server" FilePath="menu/menu.css" PathNameAlias="SkinPath" /> Der optionale Parameter PathNameAlias kann mit den Werte SkinPath oder SharedScripts gefüllt werden. SkinPath ist dabei der aktuelle Pfad zum verwendeten Skin und somit lassen sich alle Dateien unterhalb vom Skinverzeichnis einbinden und bei SharedScripts wird das Verzeichnis ~/Resources/Shared/Scripts/ als Basisverzeichnis genutzt.  Zusätzlich kann man noch über die Option Priority die Reihenfolge der Dateien bestimmen. Weitere Informationen findet man dazu auch im offiziellen DotNetNuke Wiki.

DotNetNuke speichern von Zugangsdaten der Benutzer

DotNetNuke bietet drei Möglichkeiten die Passwörter von Benutzern zu speichern. Diese können im Klartext, als verschlüsselte Zeichenfolge oder als Hashwert in der Datenbank gespeichert werden. Das die erste Variante höchtens für Test- und Entwicklungsinstallationen in Frage kommt, muss wohl nicht weiter diskutiert werden. Konfiguiert wird die Behandlung von Passwörtern in der web.config direkt bei den Einstellungen des MembershipProvider:<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="SiteSqlServer" enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="false" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="0" requiresUniqueEmail="false" passwordFormat="Encrypted" applicationName="DotNetNuke" /> Worin besteht aber der genau Unterschied zwischen veschlüsselt und hashed?Verschlüsselte ZeichenfolgenBei diesem Modus werden die Passwörter durch einen Verschlüsselungsalgorithmus unleserlich gemacht, so das bei einem Auslesen der Tabelle, die Passwörter nicht im Klartext zur Verfügung stehen. DotNetNuke bzw. jedes DNN-Module ist in der Lage die Passwörter ohne Probleme zu lesen. Hashwerte Wenn man als Modus "Hashed" wählt, dann wird nur ein Hashwert vom Passwort abgespeichert und nicht das eigentliche Passwort. Aus dem Hashwert kann man das Passwort nicht mehr in Klartext umwandeln und somit hat auch kein Module mehr Zugriff auf die Passwörter. Das bedeutet aber auch, dass die "Passwort zusenden"-Funktion nicht mehr das Passwort dem Benutzer zur Verfügung stellen kann. Ob das eine Anwendung überhaupt machen sollte ist eine ganz andere Diskussion. Die Funktion "Passwort vergessen" funktioniert aber natürlich trotzdem, in diesem Modus wird von DotNetNuke einfach ein neues Zufallspasswort erzeugt.Welche VarianteEs gibt keine klare Empfehlung für eine der verfügbaren Methode. Für die Auswahl sollten im Vorfeld Überlegungen angestellt werden, ob man das Passwort wirklich jemals im Klartext benötigt. Aus der Perspektive eines Datenschützers wäre eigentlich nur die Möglichkeit "als Hashwert" akzeptable.

DotNetNuke Performance Optimierung

Die Performance einer Webseite ist heute aus vielen Gründen - die hier nicht weiter aufgeführt werden müssen - wichtig. DotNetNuke selber bietet eine Vielzahl von Einstellungen, die direkten Einfluss auf die Performance der Webseite haben können. Es gibt auf Codeplex ein Projekt, dass durch ein paar SQL Scripts die Einstellungen einer DotNetNuke Installation so modifiziert, das eine maximale Performance möglich ist. Natürlich muss man im Einzelfall über manche Einstellung extra entscheiden aber als Startpunkt für eine Optimierung finde ich das sehr gelungen.Das Projekt findet man unter http://dnnperformance.codeplex.com

Die web.config bei der Installation eines Modules verändern

Je nach Modul gibt es schon mal die Anforderung, dass neue Einträge in die web.config geschrieben werden müssen. Dieses kann man entweder im SourceCode erledigen oder aber die Änderungen in dem DNN Modul Manifest / Definitionsdatei (meinmodule.dnn) definieren. Verfügbar ist das ab der Version 5 von DotNetNuke. Um das zu nutzen, muss man in der Manifest-Datei folgendes hinzufügen:<component type="Config"> <config> <configFile>web.config</configFile> <install> <configuration> <nodes>             ..... </nodes> </configuration> </install> <uninstall> <configuration> <nodes /> </configuration> </uninstall> </config> </component>Wie man sieht gibt es zwei Bereiche. Der Bereich <install> wird während der Installation und der Bereich <uninstall> wird be der Deinstallation von dem DNN Modul ausgeführt.Innerhalb des Tags <nodes> können dann die entsprechenden Einträge hinzugefügt werden. Hier ein Beispiel womit ein HttpHandler hinzugefügt wird:<node path="/configuration/system.web/httpHandlers" action="update" key="path" collision="overwrite"> <add verb="*" path="myhandler.axd" validate="false" type="DNN.Module.Shop.MyHandler, DNN.Module.Shop" /> </node>Weiter Informationen findet man im Wiki auf www.dotnetnuke.com

FCKEditor Anzahl der Zeichen ermitteln und darstellen

Auch wenn der FCKEditor mittlerweile vielfach durch den CKEditor ersetzt wird, wird in älteren Projekten dieser immer noch eingesetzt. Vielfach gibt es den Wunsch das man beim Schreiben von Texten die Anzahl der Zeichen sieht, damit man z.B. in Teaserboxen nicht zu viel Inhalt unterbringt.Vor einiger Zeit habe ich ein Plugin für den FCKEditor gefunden der so etwas ähnliches macht. Das Plugin zählte die Zeichen und nach einem eingestellten Maximalwert, wird die Eingabe verweigert. Für meine gewünschten Fall war das aber zu viel, da lediglich die Anzahl der Zeichen angezeigt werden sollen. Da es auch noch ein paar Probleme mit dem Plugin gab, habe ich mich heute hingesetzt und dieses etwas umgeschrieben. Den Download gibt es am Ende des Beitrages.Die Einbindung ist sehr simple:Den Ordern als Unterordner von Verzeichnis plugins kopieren. Den Ordner Plugin findet man bei DotNetnuke normlerweise unter ({webroot}\Providers\HtmlEditorProviders\Fck\FCKeditor\editor\plugins\)Dann muss man die Konfigurationsdatei vom Editor anpassen und folgende Zeile hinzufügen:FCKConfig.Plugins.Add( 'CharsCounter', '' ) ;Ebenfalls in der Konfiguraationsdatei muss dann ein Button bzw. eine "Toolbar" hinzugefügt werden. Das ist sehr einfach und man muss lediglich das entsprechende Toolbarset erweitern um den Eintrag CharsCounter. Hier ein Beispiel:FCKConfig.ToolbarSets["Basic"] = [     ['Bold','Italic','-','OrderedList','UnorderedList','-','Link','Unlink','-','About'],    ['CharsCounter'] ] ; Die Konfigurationsdatei vom Editor befindet sich unter {webroot}Providers\HtmlEditorProviders\Fck\Custom.Dann wird in der Toolbar vom Editor die Anzahl der Zeichen angezeigt.Den benötigte JavaScript-Code gibt es hier als Download:FCKEditor_CharsCounter_Plugin.zip (1,81 KB)

DotNetNuke export Users with Passwords

Bei einem Ur-Alt Portal (DotNetNuke 3.2.2) das noch hobbymäßig betreut habe, steht nun der Wechsel z [Mehr]

Seitentitel im Breadcrumb Skinobject

Im Breadcrumb Skinobject von DotNetNuke wird per Default immer der Seitenname angezeigt. Es kann aber durchaus Fälle geben, bei denen es sinnvoll ist nicht den Seitennamen sondern den Seitentitel anzeigen zu lassen. Der Seitennamen ist die Bezeichnung im Menü und der Seitentitel ist der Browsertitel. Wenn man nun anstelle vom Seitenamen den Seitentitel nutzen möchte, dann kann man dieses per Konfiguration der Komponente ganz einfach erreichen. Hier gibt es die Eigenschaft "UseTitle" und wenn diese mit dem Wert "true" belegt wird, beeinflusst das die Darstellung. Hier als Beispiel:<dnn:BREADCRUMB runat="server" id="dnnBREADCRUMB"  CssClass="Breadcrumb" RootLevel="0" Separator="&nbsp;>&nbsp;" UseTitle="True" />

RibbonBar Control Panel jetzt auch in der Community Edition

Das bisher in der DotNetNuke Professional verfügbare RibbonBar Control Panel - eine Alternative zu dem normalen ControlPanel - steht jetzt auch für die Community Version zur Verfügung. Im Vergleich zu dem normalen Control Panel, hat der Bearbeiter hier deutlich mehr Möglichkeiten die wichtigen Parameter direkt zu beinflussen. Das RibbonBar Control Panel ist aufgeteilt in für Tabs / Bereiche:Common TasksCurrent PageAdminHostDer Bereich Commen Tasks ist relativ identisch zu den bisher eingesetzten Control Panel. Zumindest auf den ersten Blick. Hier sind aber auch einige wirklich sinnvolle Erneuerungen aufgenommen. Bei der Neuanlage einer Seite kann man jetzt hier direkt die Informationen Name, Position in der Sitemap, Template, etc. definieren. Das kopieren von bereits existierenden Modulen von anderen Seiten wurde angepasst und kann man nicht nur eine Referenz von einem Modul nutzen, sondern auch ein komplett neues Modul mit den identischen Inhalten und Einstellungen erzeugen - also ein wirklicher 1:1 Kopiervorgang von einem bestehenden Modul.Der Bereich "Current Page" ist neu und bietet die Möglichkeit wichtige Parameter wie Name, Position in der Sitemap oder das vererben von Rechten direkt durchzuführen. Die beiden Bereiche Admin und Host zeigen die Punkte aus dem Administrationmenü an. Das finde ich ganz praktisch, das es immer wieder mal Unterseiten gibt, die über kein Hauptmenü verfügen und somit war man nie in der Lage direkt in einen Bereich von Admin oder Host zu gelangen.

DotNetNuke Context Menu Hiding / Firefox 3.6

Bei Anwendern die mit einer aktuellen Version vom Firefox 3.6 DotNetNuke administrieren möchten, haben ein Problem an das Kontext-Menü eines Modul zu kommen, da dieses einfach nicht sichtbar ist bzw. nicht angezeigt wird. Um dieses Problem zu beheben muss man in der JavaScript-Datei vom Solpartmenu eine Zeile verändern und dort den z-Index erhöhen. Die entsprechende JavaScriptdatei für das Menü befindet sich vom DotNetNuke-Root aus im Verzeichnis "/controls/SolpartMenu/spmenu.js". In der Zeile 948 befindet sich ein Eintrag: eMenu.style.zIndex = 1Die Wert von 1 einfach erhöhren z.B. 10000 und anschliesend wird das Kontext-Menü von den DotNetNuke Modulen auch wieder im Firefox angezeigt.

DotNetNuke Standardcontrol portal:url und die Auswahl "keine Auswahl"

Das DNN Control portal:url ist ja sehr flexibel und damit kann man vieles abfangen. Auwahl von Seiten, Verlinkungen, Benutzern, internes Dateisystem, etc. Wenn das Feld aber kein Pflichtfeld ist der Benutzer auch nachträglich noch die Möglichkeit haben soll den Werte wieder zu entfernen, dann muss bei dem Control eine Property setzen:required="False"Durch diesen Parameter erscheint dann "keine Auswahl" in der Drowdownbox.

Webservice Kommunikation zwischen .NET ASMX und PHP

Ich hatte das "Vergnügen" für die Integration eines Portals mit einem anderen die Schnittstellen zu definieren. Unsere Plattform ist natürlich eine ASP.NET Anwendung (DotNetNuke) und auf der Gegenseite wurde eine Umgebung mit PHP aufgebaut. Wir einigten uns auf einen Webservices ... mal davon abgesehen, dass mein Gegenüber sich noch nie ernsthafter mit den Webservice-Spezifikationen auseinandergesetzt hat ... ist das rein von der Interoperabilität doch bestens geeignet. In der Praxis war es dann aber nicht ganz so einfach, die Daten auch wirklich vom PHP-Code an den ASMX Dienst zu übertragen. Die Methode wurde zwar immer aufgerufen, leider kamen aber keinerlei Parameter an. Schweren herzens habe ich sogar den Kompromiss gemacht und hab in die Definition der Webservice-Methode einzelne Parameter aufgelistet - anstelle einer nachrichtenbasierten Kommunikation mit einem einzigen Parameter. Vereinfacht dargestellt sah die Methode bzw. die Definition der Schnittstelle so aus: [Webmethod]public string Gibmirdaten(string name, stirng vorname){ . . . . return "Ergebnis: " + name + ", " + vorname;}<pre><span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px">[Webmethod] <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px">public</span> <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px">string</span> Gibmirdaten(<span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px">string</span> name, strrng vorname) { . . . . <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px">return</span> <span style="color: #666666; background-color: #e4e4e4; font-family: Courier New; font-size: 11px">"Ergebnis: "</span> <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px">+</span> name <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px">+</span> <span style="color: #666666; background-color: #e4e4e4; font-family: Courier New; font-size: 11px">", "</span> <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px">+</span> vorname; }</span></pre<br><br><br>s<br>w<br>w<br>w<br>w<br>w<br>s<br><br><br>Man sollte meine, dass es in PHP genau so einfach ist, einen Webservice zu konsumieren, wie es in .NET ist (und dabei meine ich nicht so einen Schwachsinn wie Rechtsklick und Webverweis hinzufügen :)).Dank Google und einiger sehr hilfreicher Tutorials im Internet habe ich PHP-Krüppel es hinbekommen. Wichtig für die richtige Übertragung der Parameter ist die Umformung bzw. die Verpackung in ein Array. Die Methode new SoapParam(..) - wie man Sie des öfteren sieht - funktioniert leider nicht. Zumindest habe ich das in meine konkreten Beispiel und dem Zusammenspeil mit .NET festgestellt. Ein funktionierende SOAP-Client-Proxy (eigentlich tut es weh so etwas dazu zu sagen) sieht wie folgt aus:var $SOAP = new SoapClient('http://www.meinesite.de/ParterUserReg.asmx?WSDL'); var $params = array('name' => 'Müller', 'vorname' => 'Daniel'); $SOAP->Gibmirdaten($params ); Damit kann man die einzlenen Werte übermitteln.Wenn jemand einen anderen und vielleicht sogar besseren Weg kennt, dann bitte melden :)

Neuer DotNetNuke FCK-Plugin zur Nutzung von token-replacement

In dem Text/HTML Modul vom DotNetNuke Core-Team kann man ja bereits seit einiger Zeit ein paar Token wie z.B. Benutzername, EMail, Portal-Informationen, etc. nutzen. Dafür muss man in den Einstellungen vom Modul die Replacement-Funktionalität aktivieren. Bisher konnte man die Tokens zwar nutzen, musste die Liste der verfügbaren Tokens im Kopf halten. Jetzt gibt es endlich ein Plugin für den FCK-Editor, um eine einfache Auswahl und Nutzung der Tokens zu ermöglichen. Dieses Plugin gibt es hier auf CodeplexEcht sinnvoll und nützlich im Alltag!

Convert VS2003 Class Library to VS2008 Web Application Project

Bei der Weiterentwicklung eines recht alten Portals stand ich nun vor der Aufgabe eine aktuelle Entwicklungsumgebung aufzusetzen. Die bisherige Umgebung war DNN 3.2.2 und nun wurde das Portal auf die aktuelle Version von DNN (4.x) aktualisiert. Da ich auch nicht mehr mit Visual Studio 2003 entwickeln wollte, habe ich den SourceCode das Modul mit dem Conversion Wizard auf die aktuelle VSS Version 2008 konvertiert. Das Projekt vom Type ClassLibrary konnte aber nicht vernüftigt debugged werden, daher habe ich beschlossen das Projekt als WAP (Web Application Project) weiterzuentwickeln.Dafür muss man (nach erfolgreichem Durchlaufen des Conversion Wizard von VS2008) die Projektdatei mit einem Editor öffnen und anschließend die Zeile<ProjectType>Local</ProjectType>gegen <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>tauschen. Nach dem erneuten Öffnen der Projektmappe / des Projektes im Visual Studio wird diese nun als WAP angezeigt. Nun muss man nur noch die einzlnen ASCX / ASPX in eine Web-Anwendung konvertieren. Das ist auch sehr einfach zu erledigen: Die gewünschten Dateien Auswählen und im Kontextmenü den Punkt "In Webanwendung konvertieren" wählen. Nun werden im Hintergrund die *.designer.cs Dateien angelegt und gleichzeitig die Codebehind-Klassen als "partial" gekennzeichnet. Schon ist das Update von einer Class Library in ein Web Application Project fertig!Achso: Bitte die Konfiguration überprüfen und evtl. Anpassen...

Migration von benutzerdefinierter profile properties

Derzeit steht die letzte (für uns) Migration eines DotNuke-Portals von der Version 3.2.2 auf die aktuellste Version an. Da es sich hierbei um ein recht großes Portal handelt, bei dem der Communityaspekt im Vordergrund steht, wurden die Benutzerprofile hier sehr stark genutzt und erweitert. Dieses wurde in der Version 3.2.2 durch Veränderungen der web.config erreicht. Bei dem Testlauf einer Migration ist mir nun aufgefallen, dass die zusätzlich definierten benutzerdefinierten User-Propeties nicht mit in das neue Konzept übertragen werden. Um das zu erreichen, muss man das SQL-Upgradescript anpassen und die zu migrierenden Properties dort mit einfügen.Dafür muss man in das SQL-Script mit der Version 03.02.03 einige Änderungen machen:Die StoredProcedure AddDefaultPropertyDefinitions muss um die zusätzlichen Eigenschaften ergänzt werden - dabei wird der Datentyp definiert, die Gruppe, die Bezeichnung, Länge, etc. definiert. Später können diese Eigenschaften auch über die bekannte Benutzerprofilverwaltung angepasst werden.EXECUTE @RC = {databaseOwner}[{objectQualifier}AddPropertyDefinition] @PortalId, -1, @TextDataType, '', 'LowFett','Size' ,0, '', 21, 1, 250 EXECUTE @RC = {databaseOwner}[{objectQualifier}AddPropertyDefinition] @PortalId, -1,  @TextDataType, '', 'LowFett','Weight' ,0, '', 21, 1, 250 EXECUTE @RC = {databaseOwner}[{objectQualifier}AddPropertyDefinition] @PortalId, -1, @TextDataType, '', 'LowFett','Eyecolor' ,0, '', 21, 1, 300 EXECUTE @RC = {databaseOwner}[{objectQualifier}AddPropertyDefinition] @PortalId, -1, @TextDataType, '', 'LowFett','Haircolor' ,0, '', 21, 1, 300Die Tabelle FlatProfile wird temp. angelegt um die Daten vom ASP-Membership zwischenzulagern. Auch hier müssen ein paar manuelle Änderungen vorgenommen werden, damit diese Tabelle für die zu migrierenden Daten auch jeweils eine Spalte bekommt - der SQL-Syntax der "normale" für den den SQL-Server - hier zwei Beispiele: [Eyecolor] [nvarchar] (300) NULL , [Haircolor] [nvarchar] (300) NULL , Dann muss die Ausführug von "INSERT INTO {objectQualifier}FlatProfile" um die entsprechenden Eigenschaften ergänzt werden:{databaseOwner}{objectQualifier}GetProfileElement('Weight',PropertyNames, PropertyValuesString) Weight, {databaseOwner}{objectQualifier}GetProfileElement('Eyecolor',PropertyNames, PropertyValuesString) Eyecolor, {databaseOwner}{objectQualifier}GetProfileElement('Haircolor',PropertyNames, PropertyValuesString) Haircolor, Als letzer Schritt müssen dann noch ein paar zusätzliche SQL-Befehle eingefügt werden, damit die Daten aus der FLAT-Tabelle in die eigentlichen UserProfile-Tabelle geschrieben werden.EXECUTE {objectQualifier}TransferUsersFromFlatProfile N'Eyecolor' EXECUTE {objectQualifier}TransferUsersFromFlatProfile N'Haircolor' Wenn diese Schritte für jede zu migrieden benutzerdefinierte Property durchgeführt wurde, dann steht der Migration nichts mehr im Weg.

ASP.NET 2.0 Validatoren JavaScript Bug missing ; before statement

Bei der Entwicklung von DotNetNuke-Modulen (bzw. auch bei "normalen" ASP.NET Anwendungen) verwende ich recht häufig die Möglichkeit, Usercontrols (ascx) dynmaisch zur Laufzeit anzuzeigen / nachzu laden. Der entsprechende Quellcode dafür ist nicht wirklich neu und sieht so aus:PortalModuleBase objToLoad = this.LoadControl(_ControlToLoad) as PortalModuleBase; objToLoad.ID = System.IO.Path.GetFileName(_ControlToLoad); objToLoad.ModuleConfiguration = this.ModuleConfiguration; this.Controls.Add(objOrderCtrl); Wichtig dabei ist die Zeile, wo die ID des Controls gesetzt wird, damit die Resourcendateien durch DotNetNuke (durch die Property LocalResourceFile) angesprochen werden können. Bei der Verwendung einer Templateengine für ein Modul und der gleichzeitigen Verwendung von Standard ASP.NET 2.0 Validatoren, bekam ich im Browser immer die Javascript-Fehlermeldung  "missing ; before statement". Nach kurzer Recherche habe ich die Ursache gefunden: In den ID's von den Controls wurde ein Punkt verwendet und damit kommt JavaScript bzw. der JavaScript-Code der ASP.NET Validatoren nicht zurecht. Nach Abänderung der ID Zuweisung auf folgende Zeile:objToLoad.ID = System.IO.Path.GetFileNameWithoutExtensi(_ControlToLoad); funktionieren sowohl die Resourcendateien als auch die Validatoren wieder ohne Probleme.

Aktivierung der Human Friendly Urls bei DotNetNuke

Um in DotNetNuke für SEO besser geeignete URL's zu nutzen, muss man die web.config bearbeiten. Dieses läßt sich nur global und nich für jedes Portal einzeln aktivieren.<friendlyUrl defaultProvider="DNNFriendlyUrl">     <providers>         <clear />         <add name="DNNFriendlyUrl" type="DotNetNuke.Services.Url.FriendlyUrl.DNNFriendlyUrlProvider, DotNetNuke.HttpModules" includePageName="true" regexMatch="[^a-zA-Z0-9 _-]" urlformat="HumanFriendly"/>     </providers>  </friendlyUrl>Setzt man den Parameter urlformat auf "HumandFriendly", dann erhält man folgende URL:http://www.mydomain.com/DotNetnuke-installations-service.aspx Die unter DotNetNuke bezeichneten suchmaschinenfreundlichen URL's sehen wie folgt aus:http://www.mydomain.com/dotnetnuke/installation-service/tabId/566/default.aspx Eigentlich ist die Humanfriendly-Lösung auch deutlich besser für die Suchmaschine geeignet, die Namensgebung stammt wohl noch aus grauer Vorzeit - die Verwendung von HumanFriendly-Urls ist auf jeden Fall zu empfehlen. Jede Seite im DotNetNuke-Portal ist über die drei möglichen Adressierungen ansprechbar:http://www.mydomain.com/default.aspx?tabId=566http://www.mydomain.com/dotnetnuke/installation-service/tabId/566/default.aspxhttp://www.mydomain.com/DotNetnuke-installations-service.aspx Eine Abwärtskompatibilität ist somit gegeben, was rein technisch ist das sehr angenehm ist. Aus Sicht der Suchmaschinenoptimierung ist diese Möglichkeit aber gefährlich, da hier die Gefahr des "Duplicated Content" entsteht und identische Inhalt über mehrere URL's erreichbar sind. Es ist also darauf zu achten, dass man eine saubere Weiterleitung einrichtet!

Favicon in Dotnetnuke verwenden

Das "I-Tüpfchen" für eine Website ist ein pasendes Favicon. Dotnetnuke hat bereits einen Platz in der Verzeichnisstruktur dafür vorgesehen. Es ist ohne weiteres möglich im Root-Verzeichnis das Favicon von DNN zu ersetzen. Allerdings funktioniert dieses bei den aktuellen Version 4.9.0 nicht mehr. Es wird immer das Standard DNN-Favicon angezeigt. Zudem habe ich die Erfahrung gemacht, dass dieses oft nach einem DNN update überschrieben wird. Wenn man im Portalverzeichnis (z.B. /Portals/xx/) die Datei Favicon.ico anlegt, dann wird diese Datei automatisch als Favicon für das aktuelle Portal verwendet.  

DotNetNuke 5.0 RC1

Die schon lange erwartete neue Version von DotNetNuke mit dem Codenamen "Cambrian" hat einen weiteren Meilenstein erreicht. Die Version RC1 wird bei der OpenForce Europe vorgestellt und an Gruppe von Personen verteilt. Sehr cool ist der Support von jQuery und XHTML, WCAG and ADA compliance. Benutzerrechte können jetzt nicht nur gewährt sondern auch entzogen werden, was in manchen Situationen das Leben verinfachen dürfte. Einige von den neuen Features wurden in die Version 4.9 übernommen und sind dort schon verfügbar. Eine Übersicht der neuen Features von DotNetNuke 5.0 gibt es z.B. hier. Wann es eine öffentliche Version gibt, ist bis jetzt aber noch nicht bekannt...

Debug DotNetNuke Scheduler

Das Debuggen von DotNetnuke Schedulern ist nicht so ganz einfach. Mit einem Break-Point und F5 ist es leider nicht getan an dieser Stelle, da die einzelnen Scheduler in einen separaten Thread laufen.Auch der Trink um Windows Services zu debuggen - das anhängen des Debuggers an den Prozess - funktioniert in diesem Fall einfach nicht. Es gibt aber einen Weg, den Debugger per SourceCode-Aufruf zu starten. Das geht ganz einfach und ist mit einer Zeile erledigt: System.Diagnostics.Debugger.Launch(); Dieser Aufruf bewirkt, dass man eine neue oder eine existierende Instanz von Visual Studio auswählen kann, um anschließend durch den Code zu steppen. Ein paar weitere Infos gibt es bei Mircosoft-MSDN hier 

ASP.NET ajax GenerateScriptType und eigene Komplexe Typen

Ich beschäftige mich gerade mal etwas intensiver mit dem AJAX-Framework - eigentlich ja schon ein alter Hut. Dabei habe ich ein DotNetNuke-Modul, dass zu einem ASMX-WebService Daten versendet und ein Ergebnis zurück bekommt. namespace G.Modules.LicCalc{  [WebService(Namespace = http://tempuri.org/)]    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]  [ScriptService]  public class CalculatorService : System.Web.Services.WebService  {    [WebMethod()]    public string HelloWorld(LicCalcInfo info)    {       return "Hello World" + info.LinuxLicense.ToString();    }  }  } Passend dazu gibt es eine Klasse "LicCalcInfo" - die wie DotNetNuke-typische Info-Class aufgebaut ist using System;namespace GMS.Modules.LicCalc.Business{public class LicCalcInfo{private int _windowsLicense;private int _linuxLicense;public int LinuxLicense{get { return _linuxLicense; }set { _linuxLicense = value; }}public int WindowsLicense{get { return _windowsLicense; }set { _windowsLicense = value; }}}} Wenn ich jetzt über JavaScript versuche die Methode "HelloWorld" aufzurufen und den Parameter LicCalcInfo übergeben möchte, wird bei der Erstellung der Klasse immer eine JavaScript-Exception ausgelöst. Das JavaScript sah so aus: function HelloWorld(){var info = new LicCalcInfo(); info.LinuxLicense = 10;DocuSnap.Modules.LicCalc.CalculatorService.HelloWorld(info, SucceededCallback);}function SucceededCallback(result, eventArgs){    alert(result);} Das ganze funktioniert aber nur, wenn die Klasse "LicCalc" direkt in der ASMX Datei definiert wurde und sich außerhalb des Namespaces befindet. Als extern definierte Klasse habe ich die Einbindung nie geschafft. Die Lösung dabei ist aber mal wieder relativ einfach: Bei der Erzeugung des Objektes in JavaScript muss das Objekt mit dem kompletten Namespace angesprochen werden.. das hat mir dann ein Blick in die automatisch gernierte JavaScript-Datei veraten. Der Aufruf zur Erzeugung muss dann so geschrieben werden: var info = new DocuSnap.Modules.LicCalc.Business.LicCalcInfo(); Dann kann die Klasse auch in JavaScript erzeugt werden und die Verarbeitung wird erfolgreich durchgeführt.

DotnetNuke Game / Battleship Module

Eigentlich habe ich ja ein paar Module (News, FAQ) für DotNetNuke gesucht - dabei bin ich dann über ein Game gestolpert, dass jeder von uns kennt und auch gerne spielt: Schiffe versenken :) Auf der Seite http://www.donein.net/Default.aspx?tabid=58 gibt es sowohl einen Downloadlink als auch die Möglichkeit, das Spiel direkt mal zu testen! Viel Spaß :)

IE und die Option "Anmeldedaten merken"

Wer sich wundert das die Funktion "Anmeldedaten merken" im IE nicht funktioniert und sich ebenfalls darüber ärgert, für den habe ich nun eine Lösung (vielmehr habe ich im Web eine gefunden). Im Blog auf www.dotnetnuke.com habe ich einen Beitrag gefunden der erklärt, wieso, weshalb, warum und was man dagegen tun kann.Hier ist der Beitrag...Prinzipell müssen zwei Einträge in der web.config angepasst werden, damit die Funktion das macht, was sie soll:<forms name=".DOTNETNUKE" protection="All" timeout="120" cookieless="UseCookies" /> <add key="PersistentCookieTimeout" value="20160" />Der "Fehler" liegt auch weniger an DNN sonder viel mehr an der Behandlung von Cookies unter ASP.NET 2.0.

ASP.NET Ajax das Updatepanel und der FCKEditor

Heute habe ich versucht, den FCKEditor innerhalb eines ASP.NET Ajax Updatepanel dazu zu bewegen mir auch den eingegebenen Text auszuhändigen. Normalerweise ist ja die Einbindung und Nutzung vom FCKEditor innerhalb von DotNetNuke denkbar einfach. Also wie gewohnt die Arbeitsschritte ausgeführt und mal mutig F5 gedrückt. Leider mit dem Resultat, dass die Eigenschaft Text vom FCKEditor nach einem partial PostBack immer leer war und der Text zunächst mysteriös verschwand. Die Suchmaschine meines Vertrauen hat mir auch prompt ein paar Hinweise zu dem Thema ausgespuckt - gut, ich war wohl nicht alleine auf dieser Welt. Auf der Seite http://jlcoady.net/archive/2007/03/30/fckeditor-work-inside-updatepanel wurde ein Lösungsansatz vorgestellt, der aber leider so nicht ganz funktioniert - zumindest im meinem Fall nicht. private void Page_Load(object sender, EventArgs args){   Page.ClientScript.RegisterOnSubmitStatement(   editor.GetType(),   "editor",   "FCKeditorAPI.GetInstance('" + editor.ClientID + "').UpdateLinkedField();");} Dieser Code-Snippet bracht mich nicht weiter, denn der Text wurde immer noch nicht zurück geliefert, nach einem Postback innerhalb vom UpdatePanel. Auch der folgende Code sollte angeblich funktionieren, konnte aber meine FCKEditor auch nicht wirklich übereden, mal endlich seine Arbeit aufzunehmen. this.Page.ClientScript.RegisterOnSubmitStatement( this.GetType(), "AjaxHack", "for ( var i = 0; i < parent.frames.length; ++i ) if ( parent.frames[i].FCK ) parent.frames[i].FCK.UpdateLinkedField();" ); Wie sich nun herausstellt, sind die Scripte vollkommen in Ordnung und funktionieren auch. Nur ist es empfehlenswert die Methode "RegisterOnSubmitStatement" nicht als Methode der Page aufzurufen sondern als Methode vom ScriptManager. Das sieht dann so aus: ScriptManager sm = ScriptManager.GetCurrent(Page);if (sm != null){ScriptManager.RegisterOnSubmitStatement(this.Page,this.GetType(),"FCKAjaxHack","for ( var i = 0; i < parent.frames.length; ++i ) if ( parent.frames[i].FCK ) parent.frames[i].FCK.UpdateLinkedField();");} Oh Wunder, jetzt funktioniert auch der FCKEditor in der Zusammenstellung von DotNetNuke, ASP.Net Ajax und dem Updatepanel!

HTML DOCTYPE bei DNN anpassen

Wer sich mit tabellenlosen Designs beschäftigt - und sind wir mal ehrlich, ergibt es anders einen Sinn - der wird sich auch immer wieder mal mit dem DOCTYPE rumschlagen müssen. Zum Glück haben die Entwickler von DotNetNuke da auch mitgedacht und den DOCTYPE pro DNN-Portal, sogar pro DNN Skin konfigurierbar gestaltet. Dafür muss lediglich eine XML-Datei angelegt werden, die den Namen des Skins trägt und dann die Endung ".doctype.xml" hat  also von Aufbau her so aussieht [SKINNAME].doctype.xml. Die XML Datei hat folgenden Aufbau: <SkinDocType><![CDATA[<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">]]></SkinDocType> Fertig ist der angepasste DOCTYPE für ein DotNetNuke-Skin. Das war doch mal wieder einfach :)  

Eine brauchbare DotNetNuke Sitemap

Ein Kunde wollte in seinem aktuellen DNN-Projekt eine Sitemap für sein Portal erstellen - eigentlich ja nichts ungewöhnliches aber in den letzten DotNetNuke Projekten wurde es bei uns so gut wie nie gebraucht. Habe mir heute die Mühe gemacht und noch mal ein wenig gesucht, welche DNN Module es denn derzeit so auf dem Markt gibt, welche die Anforderungen einer Sitemap erfüllen. Bei all den vielen Treffern habe ich dann die Seite houseofnuke.com bzw. dort das Modul HouseIndex entdeckt und finde die Darstellung dieser Sitemap wirklich klasse. Neben dem Seitenname kann man auch die Keywords und die Beschreibung der Seite ausgeben lassen - echt sinnvoll! Und so kann die Sitemap aussehen: