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.
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
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
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)
Bei einem Ur-Alt Portal (DotNetNuke 3.2.2) das noch hobbymäßig betreut habe, steht nun der Wechsel zu einer anderen Plattform an. Da der Benutzer aber kein neues Passwort bekommen sollten, müssen die existierenden Passwörter aus DNN exportiert werden. Die Passwörter wurden über das ASP.NET Membership Model verwaltet und die Passwörter sind nicht als Klartext sondern verschlüsselt in der Datenbank vorhanden. Ein simpler Export der Daten nutzt also an dieser Stelle nichts. Daher habe ich mich heute Abend hingesetzt und eine Quick and Dirty-Lösung entickelt, die es erlaubt einen Webservice aufzurufen, der dann wiederum eine CSV-Datei auf dem Server erstellt. Warum dann einen Webservice? Nun, zunächst hatte ich mir das etwas anderes gedacht - bin dann aber aus lauter Faulheit dazu übergegangen die Daten direkt lokal zu speichen. Von Quellcode her nicht wirklich optimal und wohl alles andere als CCD-konform .. aber es funktionierte für meinen einmaligen Zweck. Sollte das noch öferts anstehen, muss man über eine allgemeingültigere Lösung nachdenken und auch die Export-Funktion anpassen. Obwohl der Code nicht gerade ne Refernz ist, möchte ich diesen veröffentlichen und vielleicht hilft es ja dem einen odere anderen ebefalls die Passwörter seiner DotNetNuke User zu entschlüsseln. An alle Kritiker des Datenschutzes: Ja das habe ich auch anbemängelt, allerdings wollte das mein Gegenüber so habe. Bitteschön UserWebService.zip (7,65 KB)
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=" > " UseTitle="True" />
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 Tasks
- Current Page
- Admin
- Host
Der 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.
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 = 1 Die Wert von 1 einfach erhöhren z.B. 10000 und anschliesend wird das Kontext-Menü von den DotNetNuke Modulen auch wieder im Firefox angezeigt.
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.
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; }
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 :)
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!
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...
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.
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.
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=566 http://www.mydomain.com/dotnetnuke/installation-service/tabId/566/default.aspx http://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!
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.
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...
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
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.
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ß :)
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.
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!
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 :)
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:
Eigentlich finde ich den FCKEditor mal richtig klasse und im Vergleich zum FreeTextBox-Editor deutlich besser zu gebrauchen. Auch die Integration in DNN ist gut gelungen - besonders toll finde ich das Feature unterschiedlichen Benutzergruppen unterschiedliche Toolbar-Sets zur Verfügung zu stellen. Immer wieder haben ich das Problem das Kunden mit Redakteuren arbeiten, die nicht alles mit dem Editor machen sollen.
Die Einrichtung ist ja auch eigentlich ganz simple:
- in der web.config im Abschnitt "FckHtmlEditorProvider" den Parameter "AvailableToolBarSets" modifizieren und die benötigten Toolbarsets per Namen dort bekannt geben.
- dann im Order "Providers\HtmlEditorProviders\Fck\Custom" die entsprechende Datei fckconfig.js abändern und dort einfach die Toolbars definieren.
- Glücklich sein!
Leider bin ich in den Anläufen heute nicht über den zweiten Punkt hinaus gekommen. Immer wieder habe ich die Meldung - in einer JavaScript Alert-Message- bekommen:
"Toolbar set 'basic' doesn't exits"
Egal was ich auch gemacht habe (Browsercache gelöscht, Webserver angehalten, die Konfigurationsdateien web.config und fckconfig.js angepasst) hatte keinen Einfluss darauf. Immer wieder wurde mir diese Meldung ausgegeben. Allerdings nur, wenn ich mich mit den Rechten einer ganz speziellen Gruppe angemeldet habe, die nur auf einem Modul Editierrechte hatte... hm, dabei sollten die eigentlich nicht mit dem Toolbar-Set Basic sonder mit Redaktion-xyz arbeiten.
Nach langen hin und her, analysieren vom Quellcode des DNN FCK-Providers, etc. habe ich dann folgendes probiert:
Den Dialog "Individuelle Editoreinstellungen" aufrufen:

Dann habe ich unten aus der Auswahlliste Instanz, Modul, Portal ausgewählt (natürlich hintereinander) und habe auf "löschen" geklickt. Dazu muss man nun wissen das im engl. dort "clear" steht und "löschen" finde ich ein wenig unschön übersetzt.

Nachdem ich mir nun allen Mut zusammen gekommen habe .. hab ich einfach darauf geklickt und damit dann die kompletten Einstellungen zurück gesetzt. Anschließend konnte ich für das Portal die Berechtigungen neu setzen und jetzt: BIN ICH GLÜCKLICH und der Editor arbeitet wie gewünscht mit DotNetNuke zusammen ... :)
Folgendes habe ich gerade auf der DotNetNuke Seite gelesen und mich sehr darüber gefreut. Im wesentlichen geht es dabei um eine Neustrukturierung des Administrationkonzeptes. Zukünftig soll es möglich sein auch selber Administrationsmodule zu entwicklen und diese dann einfach in das Admin-Menü mit aufnehmen (ohne Eingriffe in die Datenbank). Ganz spannend finde ich auch, dass man die Berechtigung für die einzelnen Admin-Seiten auch endlich über die ganz normalen Seitenberechtigung steuern kann. Damit ist es dann super easy einzelnen Leuten (Gruppen) die Berechtigung für div. Adminseiten zu erteilen.
Ich bin gespannt was die Zukunft hier bringt - hört sich auf jeden Fall gut an.
Den Artikel (Blogeintrag) gibt es hier...
Auch während Weihnachten war das DNN-Core-Team wohl nicht ganz untätig und hat am 27.12.2007 den Download der DotNetNuke Version 4.8.0 frei gegeben. Es wurden viele Fehler korrigiert und neu ist der Support von DNN für den IIS (Internet-Information-Server) 7.0. Wer sich einen genauen Überblick von den Änderungen der aktuellen DNN Version machen möchte - Bitteschön, wie immer geht das im Bugtracking System support.DotNetNuke.com
Also zunächst mal: Ich lebe noch Auch wenn mein Blog in den letzten Wochen eigentlich etwas anderes vermuten läßt. In den letzten Woche stecke ich in einem größeren Projekt wo ich DotNetNuke und die WCF (Windows Communication Foundation) mit einander kombiniert habe, um ein Videoportal (so in Richtung youtube, myvideo, etc.) zu entwicken. Doch dazu später hoffentlich mehr....
Seit heut steht DotNetNuke 4.7.0 zur Verfügung und wurde für die Öffentlichkeit als Download bereit gestellt. Dieses wurde pünktlich zur US-Konferenz OpenForce'07 bekannt gegeben. Dabei finde die neuen benutzerfreundlichen URLs sehr spannend. Leider komme ich im Augenblick noch nicht dazu, diese zu testen. :(
In der kommenden Version von DotNetNuke (DNN 4.6.0) ist ein sehr interessantes Feature die Möglichkeit der Implementierung von neuen Authentifizierungssystemen jenseits von DNN. Nun ist es nicht nur mehr möglich sich gegen DotNetNuke oder einer ADS (Active Directory Service) zu authentifizieren, sondern eine Anmeldung kann nun durch:
Dafür wurde ein "neues" Providermodell für die Authentifizierung implementiert. In den letzten Tagen habe ich für einen Kunden bereits einen eigenen Provider für eine Anmeldung bei der zentralen Golf-Online-Seite erstellt und erste positive Erfahrungen damit gesammelt. Dafür muss man lediglich drei UI-Komponenten entwickeln: Login, Settings and LogOff – jeweils von Basisklassen abgeleitet (AuthenticationLoginBase, AuthenticationSettingsBase and AuthenticationLogOffBase). Die Konfiguration der einzelnen verfügbaren Provider wird über die Tabelle Authentication vorgenommen. Dort wird ganz einfach ein Prefix und die drei UI-Komponenten angegeben.
Es ist auch möglich dem Benutzer die Auswahl selber zu überlassen, mit welchem Dienst er sich Authentifizieren möchte – das find ich insgesamt schon ziemlich sexy.
Wenn sich der Benutzer über z.B. LiveID angemeldet hat, dann wird nach erfolgreicher Authentifizierung ein Benutzerkonto angelegt oder aber man kann diesen Login mit einem existierenden DNN-Benutzerkonto verknüpfen. In der Datenbank gibt es dafür die Tabelle: UserAuthentication
Das Core-Team von DotNetNuke hat in den letzten Versionen schon einiges an der Usability verbessert. Darunter gehört z.B. die Vererbung von Seiten-Rechten innerhalb der Seitenstruktur.
In vielen Projekten höre ich aber immer wieder, dass das ControlPanel (dort wo z.B. die Module ausgewählt werden) nicht flexibel genug ist und es Vorteilhaft wäre, wenn man anhand der DotNetNuke spez. Rollen die Funktionen ganz gezielt freischalten kann. Somit könnte man bestimmten Rollen ganz gezielt lediglich ein paar Module zur Verfügung stellen, die diese für ihre tägliche Arbeit benötigen. Der Vorteil liegt ganz klar auf der Hand: Die Komplexität für die Redaktuere wird reduziert. In vielen Fällen werden ja wirklich nur ganz wenige Module für die normale Arbeite benötigt (z.B.Text/HTML, Links, Images).
Seit ein paar Monaten verfolge ich eine Projekt, dass das DotNetNuke ControlPanel ersetzt (oder viel mehr eine Alternative bereit stellt). Mit diesem ControlPanel ist es nun endlich möglich die Berechtigungen innerhalb des Controlpanels sehr gezielt zu vergeben.
Hier kann man das Modul downloaden
Leider gibt es keine SourceCode Version von diesem Modul.
Im Augenblick beschäftige ich mich mit dem DNN NavigationProvider. um für einen Kunden ein CSS basiertes Menu zur Verfügung zu stellen. Ursprünglich dachte ich eigentlich, dass man auf das Rendern des Menüs Einfluß hat und bestimmen kann, wie das Menu auszusehen hat.
Nachdem ich den Sourcecode der mitgelieferten Provider analysiert habe .. kam zunächst recht schnell die Ernüchterung. Da wird in der class DNNMenuNavigationProvider auf eine Objekt vom Typ DNNMenu zugegriffen. Doch der Sourcecode scheint davon nicht mit im Standarddownload enthalten zu sein.
Mein erster Schreck - das ich das Rendern gar nicht beeinflussen kann - ging schnell vorbei. Zum einem ist natürlich die Klasse DNNMenu in dem Downloadpaket DotNetNuke WebControls enthalten und zum anderen ist die Nutzung dieses Objektes ja gar nicht notwendig.
Jetzt werde ich mal versuchen meinen eigenen Menuprovider zu entwicklen und bin gespannt wie das klappt!
Nachdem ich eigentlich schon wieder viel zu lange nichts mehr über DNN veröffentlicht hab, möchte ich damit nun endlich wieder beginnen.
Am 29.05 (also gestern) wurde die Version 4.5.2 veröffentlicht und steht wie gewohnt unter www.dotnetnuke.com zum Download bereit.
Mittlerweile ist eine ganze Menge an neuen Features implementiert wurden und eine einzelne Aufzählung wäre mit Sicherheit zu lang(weilig). Einen sehr genauen Einblick über die Veränderungen innerhalb von DotNetNuke bekommt man wie immer in der Bug Tracker.
Nachdem ich nun mein neues Notebook habe und mir ein komplett neues System aufsetzen musste - bekam ich plötzlich einen ganz seltsamen Fehler bei DotNetNuke und der Verwendung des PopUp Kalenders. Hier wurde das Datum wahlweise mal im richtigen und dann mal wieder im falschen Format zurück gegeben. Nur zur Erklärung: Das richtige Datumsformat ist für mich das deutsche (weil deutsche Anwendung) also dd.MM.yyyy aber ich bekam immer wieder folgendes m/d/yyyy.
Zunächst dachte ich daran, das die es ein Konfigurationsfehler sei bzw. ich mir irgendein englisches Servicepack installiert habe (ja, ich geben zu: Ich hab ein deutsches Betriebssystem - sorry). Aber auch nach erneuter Installation des DotNet Frameworks, war keine Besserung in sicht :(
Dann hab ich ein wenig im Forum von DNN gesucht in bin da auch recht schnell auf eine Lösung gekommen:
Wer ein ähnliches Problem hat sollte ganz einfach in der Javascript-Datei "~/js/PopupCalendar.js" folgende Zeile verändern:
anchorVal = "<A HREF=\"javascript:window.opener.calPopupSetDate(window.opener.popCalDstFld,'" + (thisMonth+1) + "/" + monthDate + "/" + thisYear + "');window.opener.closeCalPopup()\">";
zu
anchorVal = "<A HREF=\" window.opener.calPopupSetDate(window.opener.popCalDstFld,'" + constructDate(monthDate,thisMonth+1,thisYear) + "');window.opener.closeCalPopup()\">";
Durch die Verwendung von "constructDate" wird sichergestellt, dass auch auf jeden Fall das richtige Format zurück geliefert wird, wenn ein Anwender im DotNetNuke Popup Kalender darauf klickt!
In der Version 4.4.0 ist dieser Fehler laut Gemini-Report behoben ... für alle anderen installierten Version sollten diese Fix manuell vornehmen!
Wer schon immer mal eine Datenbankmodell-Digramm der DNN-Datenbank haben wollte, kann diese nun einfach downloaden. Die Datenbankstruktur der DNN-Version 4.4.0 wurde dabei dokumentiert. Es stehen drei verschiednen Formate zur Verfügung:
- PDF
- VISO
- HTML Windows-Hilfe
Hier gib es den Download des ERD Modells
Das DotNetNuke mittlerweile einen sehr großen und brauchbaren Funktionsumfang hat muss an dieser Stelle nicht weiter erwähnt werden. Bei der Implementierung alle dieser Features stand aber leider der Punkt Geschwindigkeit (Performance) nie im Mittelpunkt. Das soll nun endlich mit der kommenden Version 4.4.0 verändert werden!
Durch folgende Maßnahmen soll die Geschwindigkeit verbessert werden:
(1) Code Refactoring
(2) Optimierung und verbesserte Einsatz des Caching
(3) Assembly Management
(4) Database
(5) Compression
(6) Page State
Wer genauer wissen möchte was sich hinter den einzelnen Punkten versteckt kann das im Blogeintrag von Charles Nurse hier nachlesen.
Die Ergebnisse der ersten Tests kann man hier nachlesen!
Auf die Version 4.4.0 dürfen wir also alle sehr gespannt sein :)
Gestern ist es mir doch wirklich entgangen :( die Seite www.dnnportal.de wurde gestern zwei Jahre alt und geht nun in die dritte Runde. In dem Forum dieser Seite findet man mittlerweile jede Menge Tips&Tricks rund um DotNetNuke und immer wieder Hilfe von Experten aus dem deutschen Raum :d
Für einen Bekannten habe ich eine DotNetNukeinstallation (4.3.6) aufgesetzt und ihn ein wenig damit spielen lassen. Dabei hat er sich auch ein wenig mit den Profileigenschaften eines Users beschäftigt und diese Modifiziert. Das finde ich doch schon sehr gut und hätte ich mir eigentlich von Anfang an gewünscht ..
Da sein Portal lediglich den deutschsprachigen Raum anspricht hat er einfach die Eigenschaft TimeZone gelöscht. Leider findet das DotNetNuke gar nicht witzig und normale Anwender konnten sich ab diesem Zeitpunkt nicht mehr anmelden. Einige Komponenten benötigen diese Profileigenschaft und es kracht ganz schön böse, falls diese nicht im Profil enthalten ist.
Also: Vorsicht beim Löschen von Profileigenschaften - lieber ausblenden:)
Seit gestern gibt es die aktuelle Version von DotNetNuke auf der offiziellen Downloadseite zur Verfügung. Neben einigen Fehlern, Sicherheitslücken und Peformanceoptimierung wurde auch mal die Datensyncronisation verbessert. Genaue Informationen gibt es wie immer hier.
Die Deutsche Übersetzung findet man bei http://www.deutschnetnuke.de/
"Konflikt der Sortierung für die equal to-Operation kann nicht aufgeloest werden."
Was will der von mir???? Nach dem Umzug einer DotNetNuke - Site auf eine anderen Server bekam ich plötzlich im Log Viewer die Fehlermedlung
DotNetNuke.Services.Exceptions.ModuleLoadException: Konflikt der Sortierung für die equal to-Operation kann nicht aufgelöst werden. ---> System.Data.SqlClient.SqlException: Konflikt der Sortierung für die equal to-Operation kann nicht aufgelöst werden. at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) at Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteReader(SqlConnection connection, SqlTransaction transaction, CommandType commandType, String commandText, SqlParameter[] commandParameters, SqlConnectionOwnership connectionOwnership) at Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteReader(String connectionString, CommandType commandType, String commandText, SqlParameter[] commandParameters) at Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteReader(String connectionString, String spName, Object[] parameterValues) at DotNetNuke.Services.Log.EventLog.DBLoggingProvider.Data.SqlDataProvider.GetLog(Int32 PageSize, Int32 PageIndex) at DotNetNuke.Services.Log.EventLog.DBLoggingProvider.DBLoggingProvider.GetLog(Int32 PageSize, Int32 PageIndex, Int32& TotalRecords) at DotNetNuke.Services.Log.EventLog.LogController.GetLog(Int32 PageSize, Int32 PageIndex, Int32& TotalRecords) at DotNetNuke.Modules.Admin.Log.LogViewer.BindData() at DotNetNuke.Modules.Admin.Log.LogViewer.Page_Load(Object sender, EventArgs e) --- Ende der internen Ausnahmestapelüberwachung ---
Nach ein wenig Forschung war die Lösung schnell gefunden. Die SP muss ein wenig verändert werden, damit der Fehler nicht mehr auftritt.
Die Stored Procedure "GetEventLog" muss von
CREATE TABLE #PageIndex ( IndexID int IDENTITY (1, 1) NOT NULL, LogGUID varchar(36) )
auf CREATE TABLE #PageIndex ( IndexID int IDENTITY (1, 1) NOT NULL, LogGUID varchar(36) COLLATE database_default )
geändert werden. Dann ist wieder alles im Lot!
Ich möchte jetzt hier gar keine Diskussion lostretten die über das Solpart-Menu herzieht. Fakt ist auf jeden Fall:
- Das Anpassen des Menü via CSS kann einem wirklich graue Haare bereiten
- Die Größe des Menü (bezogen auf die HTML Datei) ist sehr groß
- Die Suchmaschinenfreundlichkeit ist fast nicht gegeben
Aus diesen Gründen habe ich ein kleines niedliches CSS-Menu gebaut das mit HTML Aufzählungen, CSS und wirklichen Links (!) arbeitet.
Es ist noch kein perfektes Menu aber für meine derzeitigen Einsatzbereich wirklich ausreichend. Ein paar Erweiterungen und Optimierungen müssen da in Zukunft noch implementiert werden. Aber wie bei jedem Projekt gibt es auch hier mal eine Version 1.0.
Da ich sehr gerne und eigentlich fast alle DotNetNuke Module in C# entwickel ist auch dieses Modul ist c# geschrieben.
Die Einbindung in ein Skin ist relativ simple! Einfach folgendes in das Skin aufnehmen:
<%@ Register TagPrefix="gwc" Namespace="GaliNeo.Modules.Framework" Assembly="GaliNeoMenu" %>
und dann an der Stelle wo das Menü erscheinen soll:
<gwc:GaliNeoMenu runat="server" id="TestMenu"></gwc:GaliNeoMenu>
Natürlich läst sich damit so ziemlich jede Menü darstellen das sich mit den HTML Tags UL und CSS formatieren läßt. Hier ist es zunächst ein klassisches Drop-Down Menü....
Hier der Download des Source-Codes:GaliNeo.DotNetNukeMenu (1.0.0.0).zip (7,96 KB)
Ja ja ... i know. Wochenlang habe ich mein Blog vernachläßigt und jetzt jagt ein Beitrag den anderen Aber irgendwie habe ich mir heute ein wenig Zeit genommen um durch das www zu surfen.
Hier ist noch eine Seite, die man keinen DNN Skin Designe vorenthalten sollte:
http://www.xhtmlskins.com/
Auf dieser Seite geht es um die Erstellung von DotNetNuke Skins ohne Tabellen. Total sexy :)
Letztes Jahr habe ich folgenden Blog-Eintrag verfasst. Darum ging es, wie man ein HTML-Form innerhalb von .NET simulieren kann.
Jetzt ist mir gerade aufgefallen, dass der Sourcecode der ausführenden Klasse dafür fehlt. Natürlich ist das der spannende und entscheidene Part für das Post der HTML-Form. Das möchte ich natürlich nicht so stehen lassen und hier kommt der fehlende Part!
using System; using System.Net; using System.Web; using System.IO; using System.Text ;
namespace GaliNeo.Framework { public class RemotePost { #region Private Members private System.Collections.Specialized.NameValueCollection Inputs = null ; private string _sUrl = "" ;
#endregion public RemotePost() { // // TODO: Fügen Sie hier die Konstruktorlogik hinzu // Inputs = new System.Collections.Specialized.NameValueCollection() ; }
#region Public Methods
public void Add(string sName, double dValue) { this.Add(sName, dValue.ToString()) ; }
public void Add(string sName,int iValue) { this.Add(sName, iValue.ToString() ) ; } public void Add(string sName,string sValue) { Inputs.Add(sName,sValue) ; }
public string Url { get { return _sUrl ; } set { _sUrl = value ; } } public string Send() { string sPostData = "" ;
Uri sUri = new Uri(this.Url) ; //Wird für evtl. SSL - Verbindungen benötigt System.Net.ServicePointManager.CertificatePolicy = new trustedCertificatePolicy();
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(sUri);
//User-Agent request.UserAgent = "GaliNeo OnlineStore" ;
request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; //Zusammensetzen der Daten für die Übermittlung sPostData = GetContentToPost() ; request.ContentLength = sPostData.Length ;
Stream writeStream = request.GetRequestStream(); //Encoding im UTF-8 Format um kompatible zu sein //UTF8Encoding encoding = new UTF8Encoding(); //UFT-8 funktioniert unter ASP.NET nicht :( System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding() ; byte[] bytes = encoding.GetBytes(sPostData); writeStream.Write(bytes, 0, bytes.Length); writeStream.Close();
HttpWebResponse response = (HttpWebResponse) request.GetResponse(); //Überprüft den HTTP-Statuscode if (response.StatusCode != HttpStatusCode.OK) { return "N,-1, HTTPStatuscode:" +response.StatusCode.ToString() ; }
Stream responseStream = response.GetResponseStream(); StreamReader readStream = new StreamReader (responseStream, Encoding.UTF8); return readStream.ReadToEnd(); }
public string GetContentToPost() { string sReturn = "" ;
for(int i=0; i< Inputs.Keys.Count;i++) { if (sReturn.Length == 0) { sReturn = Inputs.Keys[i] + "=" + Inputs[Inputs.Keys[i]] ; } else { sReturn += "&" + Inputs.Keys[i] + "=" + Inputs[Inputs.Keys[i]] ; }// if (sPostData.Length == 0)
}//for(int i=0; i< Inputs.Keys.Count;i++)
return sReturn ;
}
#endregion
} }
Die letzten Monate war es um DotNetNuke ja doch recht ruhig geworden. Mittlerweile kommt aber wieder Leben in den Releasezyklus :) Vor wenigen Tagen wurde die Version 3.3.3 veröffentlich, die als Final Release bezeichnet wird.
Hier ist ein Auszug aus den Änderungen (die Orginalfassung findet man unter dotnenuke.com):
Membership Management CAPTCHA - eine bekannte Technologie, die mehr Sicherheit bei der Anmeldung verspricht. In einem Bild werden Zahlen und oder Buchstaben angezeigt, die der Benutzer bei der Anmeldung eingegben muss. Durch die Darstellung als Bild es es dann nicht mehr so ohne weiteres möglich eine brute force Attacke durchzuführen. Login Redirect - Nach der Anmeldung kann man die User zu einer definierten Seite weiterleiten Password Generation - Als Administrator kann man nun automatisier ein Passwort für einen Anwender verwegeben. Public Registration - Beim diesem Anmeldetyp wird nun auch eine E-Mail an den Benutzer geschickt - damit kann man den Mißbrauch von Daten vorbeugen. Profile Change Notification - Anwender werde über Änderungen in Ihrem Profil per E-Mail informiert. User Account Creation Notification - Wenn ein Administrator ein Benutzerkonto anlegt, dann können nun die Daten an den entsprechenden Benutzer verschickt werden. Force Profile Update - Der Benutzer kann dazu "gezwungen" werden, nach einem Login sein Profil u verändern. Force Password Change - Bietet die Möglichkeit das der Anwender sein Passwort erneuern muss. Password Complexity - Der Aufbau und die Komplexität der Passwörter lassen sich definieren. Preserve Login Parameters - Wenn ein Benutzer zur Anmeldung geleitet wird, dann wird nun die Herkunftsurl ausgelesen und gespeichert, damit anschließend dahin zurück geleitet werden kann. Automated Verified Registration URL - Der Benutzer bekommt per E-Mail eine URL und sobald er diese aufruft wird das Konto freigeschaltet. User Lockout Notification - Wen ein Benutzerkonto gesperrt wird (durch die falsche Eingabe vom Passwort), bekommt der Administrator darüber eine E-Mail.
Role Management Effective Date - Ab wann soll eine Rolle gültig sein. Role Groups - Rollen können nun zu Gruppen zusammengefasst werden.
Usability Rich Text Editor - Nun können Verlinkungen zu Seiten im Poral direkt angelegt werden. Newsletter - Die Abenderadresse kann definiert werden.
Framework AccessDeniedURL - Hierfür kan nu eine Seite definiert werden.
Performance Module Settings - Seiten und Moduleinstellungen werden nun gecached :).
Module Definitions/Installer Module Definitions - Die Moduledefinition kann nun direkt durch eine *.dnn Datei angelegt werden, ohne eine Zip-Datei hochzuladen.
Other SMTP Settings - Die Portnumber kann angepasst werden New Modules - Store, Forums, Blogs, Gallery sind nun Bestandteil der aktuellen Version.
In der Mittagspause noch mit einem Bekannte über DNN diskutiert und das es in der letzten Zeit doch recht still geworden ist .... musste ich gerade feststellen das das Core-Team von DotNetNuke heute das neue Release 3.3.0 zum Download frei gegeben hat.
Leider komme ich in den nächsten nicht dazu diese Version zu testen aber in den Foren gibt es dazu bestimmt jede Menge zu lesen - oder auch nicht, wenn alles ohne Probleme verläuft. Es bleibt aber dabei: Zuerst die Installationsanweisung von DotNetNuke lesen und auf jeden Fall eine komplette Datensicherung von Datenbank und Dateisystem durchführen.
Die deutsche Übersetzung gibt es wie immer unter Sebastian Leupold.
Gerade habe ich einen interessanten Artikel gefunden der zeigt, wie man einen Parameter aus der Querystringauflistung entfernen kann.
Public Sub RemoveQueryString(ByVal Req As HttpRequest, ByVal strKeyToDel As String, ByVal http_Context As HttpContext) Dim nvc As System.Collections.Specialized.NameValueCollection = New System.Collections.Specialized.NameValueCollection(Req.QueryString) Dim sPage As String = Req.ServerVariables("SERVER_NAME") & Req.ServerVariables("SCRIPT_NAME") nvc.Remove(strKeyToDel)
Dim strNewURL As String = Req.Path Dim sSeparator As String = "?" Dim sKey As String For Each sKey In nvc If sKey <> Nothing Then Dim sValues As String() = nvc.GetValues(sKey) Dim sValue As String For Each sValue In sValues If sValue <> Nothing Then strNewURL &= sSeparator strNewURL &= sKey & "=" & sValue sSeparator = "&" End If Next End If Next If nvc.Keys.Count < 1 Then strNewURL &= "?" End If http_Context.Current.RewritePath(strNewURL) End Sub
Gefunden habe ich den Code unter http://www.codeproject.com
Eines meiner größten Probleme - oder sagen wir lieber Sorgen - war bisher, dass DNN keine Transaktionen unterstützt. Es gibt doch immer wieder mal Business-Cases wo man transaktionsicher Daten verarbeiten möchte. Ein typischens Beispiel wäre z.B. eine Online-Shop, wenn es um die Bestellung und gleichzeitige Zahlungsabwicklung geht.
Da DotNetNuke in vermutlich in vielen Fällen auf einem Windows 2003 Server betrieben wird, ist die komplette Umgebung schon vorhanden um die Abläufe transaktionssicher zu gestalten. Das Stichwort ist hier "Services without Components". Der Begriff "Services without Components" steht für die Nutzung von COM+-Dienste in .NET-Anwendung ohne Registrierung als Serviced Component (COM+-Anwendung).
Klassen: .ServiceConfig and System.EnterpriseServices.ServiceDomain
Das folgende Beispiel zeigt eine ganz einfache Implementierung innerhalb einer Methode:
//Hier wird mit einem Transaktionskontext gearbeitet, //damit das Handling einfacher wird ServiceConfig sc = new ServiceConfig(); sc.Transaction = TransactionOption.RequiresNew ; ServiceDomain.Enter ( sc ) ;
try { //mach was .... ContextUtil.SetComplete() ;
} catch (Exception exc) { ContextUtil.SetAbort() ; throw exc ; } finally { ServiceDomain.Leave(); }
Heute hat das Coreteam von DotNetNuke ein weiters Modul frei gegeben. Diesmal handelt es sich um ein Modul das eine Shopfunktionalität abbildet. Bei der Installation sollte man darauf achten das man nicht das Module "Categories" von efficionconsulting installiert hat, denn sonst kommt es zu Konflikten bei der Namensgebung. Diese Hürde einmal genommen ist die weiter Installation kein Problem.
Die Funktionalität ist ziemlich Low-Level und an einige Stellen gibt es noch Fehlermeldungen (z.B. bei den Einstellungen). Es gibt aber ein paar ganz gute Ansätze und ich denke das im Laufe der Zeit dieses Modul noch an Funktionsumfang zunimmt. In den nächsten Tagen werde ich wohl auch noch mal in den Source reinschauen ... so einfach aus neugier.
Für mich selber ist dieses Modul eher uninteressant, da mein Shop so langsam die Version 1.0 ereicht hat; auch wenn er laut Zeitplanung schon längst fertig sein sollte .. na ja es kommt halt immer anders als man denkt. Mittlerweile ist die Featureliste schon sehr lang - erspare mir diese aber jetzt. Eines der wichtigsten Merkmale ist aber wohl, dass alle öffentlichen Bereiche über Templates pro Portal dynamisch anpassbar sind. Ebenso ist der Bestellprozess über eine XML Workflowbeschreibung komplett frei definierbar. Anpassbarkeit und Konfigurierbakeit ist bei der Implementierung sehr wichtig gewesen. Das erste Projekt wird vermutlich nächste Woche live gehen aber dann nur für eine bestimme Gruppe von Personen. Wer trotzdem mal mehr darüber wissen möchte, kann sich ja bei mir melden. Was mit dem Shop passiert ist noch nicht ganz klar.
Eines der doch besten Argumente für die Linux- bzw. PHP-Welt im Webumfeld waren bis vor einiger Zeit immer noch die doch sehr teuren Hostingpakete von Windowsbetriebssystemen. Mittlerweile fallen die Preise ständig und sind auf einem Niveau, wie es auch im Linuxumfeld anzutreffen ist.
Das ist besonders für Freunde und Fans von DotNetNuke interessant! Es gibt zwar auch einige Anbieter die ein DotNetNuke Hosting für z.B. 10€ anbiete aber wer gerne Kontrolle über seine System hat sollte sich überlegen einen eigenen Server zu mieten.
Nicht nur das man dort der eigene Administrator ist .. man ist bei vielen Punkten nicht auf den Support seinen Providers angewiesen.
Ganz davon abgesehen, dass man auch weiter Anwendungen auf seinem Server unterbringen kann.
Ich habe nun schon seit über einem Jahr einen Server bei Strato stehen und bin mit dem Service sehr zufrieden. Wer also ein paar Euro mehr ausgibt bekommt dafür auch deutlich mehr geboten. Ich persönlich möchte das nicht mehr missen. Immerhin läuft auch mein Block darüber und ein paar weitere Anwendungen.
Weil ich das Angebot sehr gut finde habe ich oben mal einen Banner eingebaut - wer also einen Buchen will .. einfach klicken :)
Am 15 Januar hat Locopon einen neuen alternativen DotNetNuke Provider für den WYSIWYG Editor FCKEditor zum download bereitgestellt. Zu finden under diesem Link....
Dieser Provider ist ein VB.NET OpenSource Projekt (und damit kostenlos) und stellt eine echte Alternative zur FreeTextBox dar - wenn nicht sogar eine besser Lösung. Die einzelnen Features werden auf der Website näher erklärt.....
Wer eine deutsche Übersetzung sucht ist auf DeutschnetNuke gut aufgehoben.
Der Titel ist mit Sicherheit etwas provokativ gestellt; aus folgendem Grund:
In den frühen Morgenstunden des 24.12 kam der zweite Newsletter - finde die Newsletter übrigens super - von DotNetNuke.com. Hauptthema des Newsletter war das "DotNetNuke® Benefactor Program", dabei handelt es sich um en Mehrwert-Programm rund um DotNetNuke. Insgesamt gibt es vier Programmstufen von 99$ - 799$ mit unterschiedlichen Inhalten bzw. Möglichkeiten (Details hier).
Ist das der erste Schritt aus DotNetNuke ein komerzielles Produkt zu machen? Ich denke nein und es ist eine gute Möglichkeit das Projekt auf Dauer zu sichern. Ob es das Coreteam allerdings hinbekommt ihre Progamm auch so umzusetzen bleibt abzuwarten.
Hans-Peter Schelian (dnnportal.de) hat dazu auch einen Blogeintrag geschrieben und er als offizieller Team Leiter eines DotNetNuke Unterprojekts hat noch mehr Einblick ....
Warten wir ab .....
Bei mein Besuch der Seite www.dotnetnuke.com hab ich bemerkt, dass die Seite schon unter der Version 3.2.2 läuft. Vielleicht können wir ja auf eine baldige Veröffentlichung dieser Version hoffen und damit auf Behebung von Fehlern 
Mehr Infos über Veränderungen gibt es wie immer unter support.dotnetnuke.com ....
Eine kleine Änderung habe ich in der Templateengine vorgenommen: Das Control skin aus der der Methode LoadSkin() habe ich nicht nur für diese Methode zur Verfügung gestellt sondern daraus eine protected Variable innerhalb der Klasse gemacht. Somit kann nun die abgeleitete Klasse immer darauf zugreifen und der "Umweg" über sender (siehe Part 2) kann geändert werden.
Ich brauchte das gerade für eine Hilfsmethode die ich nicht nur innerhalb der Methode InitializeSkin aufrufen möchte.
Keine Ahnung warum ich das nicht direkt so gemacht habe!
In meinem ersten Eintrag habe ich beschrieben, wie man eine Grundlage für templategesteuerte DotNetNuke Module erstellen kann.
Heute möchte ich kurz darauf eingehen, wie man innerhalb eines Eventhandler auf Steuerelemente des Templates zugreifen kann. Als Beispiel nehme ich hier einen LinkButton..
protected virtual void btnLogIn_Click(object sender, EventArgs e) {
txtBox = (TextBox) ((Control)sender).FindControl ( "txtUserName" ); if (txtBox != null) { userName = txtBox.Text ; }
}
Der Zugriff erfolgt genau wie bei der InitializeSkin Methode über FindControl. Hier muss man nun lediglich den Parameter sender nehmen und die Methode FindControl darauf anwenden.
Was mir bei DotNetNuke schon lange nicht schmeckt ist der ganze Login und Registrierungsbereich.
Zum einen habe ich andere Anforderungen - okay dafür kann das Core-Team nichts - zum anderen ist aber die Anpassung des Layout nur für alle Portal gleichzeitig möglich.
Deswegen habe ich mich hingesetzt und ein ein weiters Modul dafür geschrieben. Ja, es gibt zwar schon ein paar aber die unterstützen halt alle nicht ein Templatesystem.
Das Konzept dafür ist relativ einfach: Zur Laufzeit wird die ASCX Datei dynamisch geladen. Entweder wird dabei ein Standardlayout geladen oder aber wenn vorhanden aus dem jeweiligen Portalverzeichnis. Dafür habe ich eine Klasse SkinnedWebControl geschrieben, die von PortalModuleBase abgeleitet wird.
Die Methode InitSkin() lädt das entsprechende Skin und sorgt dafür das es initialisiert wird.
protected Control LoadSkin() { Control skin; skinpath = this.PortalSettings.HomeDirectory + "GaliNeo/UserAccount/" ;
// Do we have a skin? if (SkinFilename == null) throw new Exception("You must specify a skin.");
try { skin = this.LoadControl(skinpath + this.skinFilename) ; } catch (FileNotFoundException) {
try {
skinpath = this.ModulePath + "UITemplates/" ; skin = this.LoadControl(skinpath + this.skinFilename); } catch (FileNotFoundException) { throw new Exception("Critical error: The skinfile '" + skinpath + "' could not be found. The skin must exist for this control to render."); } } // Initialize the skin InitializeSkin(skin); Controls.Add(skin) ;
return skin; }
Die Mehtode InitializeSkin() wird dann in der entsprechenden Klasse überschrieben um z.B die Steuerelemente mit entsprechenden Werten zu versehen oder aber auch Events an die Steuerelemente zu binden.
protected abstract void InitializeSkin(Control skin);
Das entsprechende DotNetNuke Modul UserControl wird dann von der Klasse SkinnedWebControl abgeleiet.
Eine Besonderheit ist der Zugriff auf Steuerelemente. Diese sind nicht direkt ansprechbar sonder müssen zunächst über die Methode FindControl gesucht werden. So könnte das dann aussehen:
protected override void InitializeSkin(Control skin) {
LabelControl dnnlbl = null ; LinkButton lnkbtn = null ;
dnnlbl = (LabelControl) skin.FindControl("lblUserName") ; if (dnnlbl != null) { dnnlbl.Text = GetLocalization("lblUserName") ; }
lnkbtn = (LinkButton) skin.FindControl("lnkBtnLogIn") ; if (lnkbtn != null) { lnkbtn.Text = GetLocalization("lnkBtnLogIn") ; lnkbtn.Click += new System.EventHandler(btnLogIn_Click) ; }
}
Die ASCX Datei des Modules sieht ganz normal aus, nur sind dort die Controls nicht definiert. Dafür gibt es die Templatedatei wobei es sich auch um ene ASCX Datei handelt, die aber nicht die Attribute CodeBehind und Namespace benötigt. Die beiden Controls Label und LinkButton werden in der Template-ASCX wie gewohnt definiert.
Soeben bekam ich einen Newsletter vom DotNetNuke-Core Team - eigentlich den ersten überhaupt. Nun ja darin stand das es nun die Version 3.2 von DotNetNuke gibt. Ebenso ist die Version 4.0 also die ASP.NET 2 Version für VS.NET 2005 als Download verfügbar.
Sonst soll es aber zwischen den beiden Versionen keinen Unterschied geben und die nächste Zeit werden wohl beide Versionen weiter gepflegt.
Hier gibt es den kompletten Pressebericht
Dann schau ich jetzt mal, ob die Downloadserver schon überlastet sind :)
Nachdem ich ein paar sehr witzige Stunden mit den Installationsroutinen (für Module) von DotNetNuke hatte und schon fast verzweifelt habe, kam eine gute Fee und holte mich da raus ... aber alles hübsch der Reihe nach!
Ich habe ein eigenes Module geschrieben und dieses DNN Module hatte eine wahnsinnige Enterprise Funktionlität - nämlich folgende:
SET newOrderno = ((SELECT MAX(OderNo) FROM TABLE) + 1)
Dieses funktionierte auch einwandfrei, allerdings als ich dann das Modul zusammen packte und es auf einem Server installieren wollte, spuckte die Installation immer einen SQL Fehler aus ... "Fehler in der Nähe von 1" Ist auch logisch, denn was da ankam sah so aus:
SET newOrderno = ((SELECT MAX(OderNo) FROM TABLE) 1)
Das "+" fehlte also ... um das jetzt hier mal abzukürzen: Es lag an dem Dateiformat .. die Textdatei mit den SQL-Befehlen war als ANSI Datei abgespeichert. Nachdem ich diese Datei im UTF-8 Format abgespeicher hatte war das Problem behoben und das "+" stand im SQL-Befehl...
Zum Glück gibt es das www.dnnportal.de und Hans-Peter, der auch Nachts noch gute Tipps hat :)
Nur mal so nebenbei: Wenn man eine Textdatei z.B. als Templatevorlage ausließt und es fehlen die Umlaute .. ja dann würde ich diese auch mal im UTF-8 Format speichern....dann beim Auslesen der Datei noch das richtige Format angeben und schon ist mal alle Sorgen los!
Ein Blick in den Downloadbereich hat mir gerade gezeigt, dass es endlich die Dokumentationen zur aktuellen Version von DNN 3.1.1 gibt.
Hier ist der Link in den Downloadbereich: http://www.dotnetnuke.com/tabid/125/default.aspx
Viel Spaß beim Lesen ....
Für alle die keine Lizenz von CodeSmith kaufen möchten, aber auf den Luxus der Codegeneriung nicht verzichten möchten, gibt es eine Alternative.
Diese Alternative nennt sich MyGeneration und ist zu finden unter: http://www.mygenerationsoftware.com
Dieses Tool ist lizenzkostenfrei und biedet alles was man benötigt. Zumindest ist es in meinem Bereich noch nicht an seine Grenzen gekommen. Was mir lediglich fehlt ist eine Art Batch-Job, da es schon manchmal lästig ist die einzelne Gerneriung von Hand anzustoßen.
Es gibt auch schon für jede Menge Zwecke / Anwendungsfälle Templates - natürlich auch für DotNetNuke (!). Das Erstellen von MyGeneration-Templates finde ich etwas besser und intuitiver gelößt - kann aber auch nur Einbildung sein 
Mit dem Usercontrol URLControl von DNN kann man auf die interne Dateiverwaltung von DNN zugreifen.
Die Einbindung habe ich in einem anderen Artikel bereits erläutert. Hier nur noch kurz der benötigte Code für die ASCX-Datei:
<%@ Register TagPrefix="Portal" TagName="URL" Src="~/controls/URLControl.ascx" %>
<portal:url id="ctlURL" runat="server" width="300" showtabs="false" showfiles="true" showUrls="false" urltype="F" showlog="false" shownewwindow="false" showtrack="false"/>
Die Eigenschaft URL dieses Controls liefert allerdings bei der Auswahl von Dateien lediglich so etwas wie "FileId=7". Um aber Bilder darstellen zu können muss dieses in einer URL umgewandelt werden. Die folgenden Funktion sind genau dafür da.
public string FileNameToImgSrc(string FileName) { string sSrc = GetRelativeFilePath(FileName) ; return this.PortalSettings.HomeDirectory + sSrc; }
public string GetRelativeFilePath(string FileName) { if (FileName.StartsWith("FileID=")) { int fileId = int.Parse(FileName.Substring(7)); FileController objFileController = new FileController(); DotNetNuke.Services.FileSystem.FileInfo objFileInfo = objFileController.GetFileById(fileId, this.PortalId); if (!(objFileInfo == null)) { return objFileInfo.Folder + objFileInfo.FileName; } else { return ""; } } else { return FileName; } }
Heute ist die neuste Version der Open Source Portalengine DotNetNuke ® zum Download bereitgestellt wurden. Zunächst gibt es nur die Version inkl. Source.
Es ist aber davon auszugehen, dass es auch bald wieder einer Version nur mit den benötigten Dateien für eine Installation gibt.
Änderungen in dieser DotNetNuke ® Version können unter support.dotnetnuke.com nachgelesen werden.
Das Downloadfile enthält keine Dokumentation von DNN, dieser werden derzeit an das neue Branding angepasst und zukünftig einzeln verfügbar sein.
Bei der Installation UNBEDINGT die Readme Datei beachten!
Also ich bin richtig froh, dass DotNetNuke Opensource ist. Da wir mittlerweile mehrere große Projekte mit DotNetNuke realisiert haben oder gerade noch dabei sind, kann die Abhängigkeit von einem Anbieter für unsere Kunden und deren Geschäftsmodelle im Internet katastrophale Konsequenzen haben. Selbst wenn DotNEtNuke plötzlich nicht mehr frei und opensource wäre, könnten wir mit dem bisherigen STand 3.1 problemlos weiterentwickeln. Interessanterweise liefern die besten Argumente für DotNetNuke und Opensource-Software häufig genug die Fürsprecher anderer Programme ... wie auch hier
http://blog.gandke.de/CommentView,guid,6f0815c7-ff41-4b2a-a657-7512bb94c58e.aspx
Heute Abend habe ich mich mal mit der Scheduler-Technologie von DotNetNuke auseinandergesetzt. Ich habe zwar auch einen eigenen DotNetNuke unabhängigen Scheduler laufen, da ich mich aber mit dieser Seite von DNN noch nicht auseinandergesetzt habe und der Anwendungsfall nicht so zeitkritisch ist viel mein Entschluß auf diese Art der Implementierung.
Zunächst einmal habe ich mir die Dokumentation von DotNetNuke Scheduler Service durchgelesen - allerdings war dort nur sehr wenig über die Implementierung zu lesen.
Die Erstellung ist aber auch eigentlich super simple und somit ist eine Anleitung gar nicht wirklich erforderlich. Hier das Grundgerüst für einen DotNetNuke Scheduler Service:
using System; using DotNetNuke.Services.Exceptions ;
namespace GaliNeo.Modules.Events { public class NotifyScheduler : DotNetNuke.Services.Scheduling.SchedulerClient {
public NotifyScheduler(DotNetNuke.Services.Scheduling.ScheduleHistoryItem objScheduleHistoryItem) { this.ScheduleHistoryItem = objScheduleHistoryItem; }
public override void DoWork() { try { this.Progressing() ; this.ScheduleHistoryItem.Succeeded = true ; this.ScheduleHistoryItem.AddLogNote("GaliNeo Events - Notify User was successfully") ;
} catch(Exception exc) { this.ScheduleHistoryItem.Succeeded = false ; this.ScheduleHistoryItem.AddLogNote("EXCEPTION: " + exc.ToString()) ; this.Errored( ref exc) ; Exceptions.LogException(exc) ; } }
} }
Das Geheimnis ist eigentlich ganz einfach.
- Man erstellt eine Klasse und leitet diese von DotNetNuke.Services.Scheduling.SchedulerClient ab
- Es muss eine Methode (DoWork()) definiert werden, die von der DotNetNuke Engine aufgerufen wird
- Ganz wichtig ist, den Konstruktur nicht zu vergessen. Das ist mir zunächst passiert und ich wunderte mich, warum der Tast nicht ausgeführt wurde.
Innerhalb der Methode DoWork() kann man nun auf die Business-Logik eines Modules zugreifen, um z.B. Daten zu lesen, zu verändern und wieder zu speichern.
Es gibt wohl eine Einschränkung: Auf die MemberRole - Implementierung kann von einem Scheduler aus nicht zugegriffen werden, da der dafür erforderliche Kontext fehlt!
Wir suchen zur Entwicklung von Skins für DotNetNuke einen Webdesigner mit guten HTML / CSS-Kenntnissen auf freiberuflicher Basis. Schwerpunkt liegt auf der grafischen Gestaltung.
Bei Interesse bitte Kontakt per eMail aufnehmen mit Michael Gandke (kontakt2005 @ gandke.de). Bitte zwei oder drei bisherige Projekte / Websites (inkl. URL) mit angeben.
Mal in eigener Sache: Wir suchen zur Entwicklung von Webanwendungen unter Microsoft .NET einen Kollegen mit guten ASP.NET-Kenntnissen zur Festanstellung (Großraum Mönchengladbach). Die Zusammenarbeit kann auch freiberuflich auf Projektbasis erfolgen. SQL-Kenntnisse sollten ebenfalls vorhanden sein sowie Erfahrungen mit eCommerce / Online-Shops.
Entwickelt werden hauptsächlich Module für DotNetNuke unter C# und/oder VB.NET. Bei Interesse bitte Kontakt per eMail aufnehmen mit Michael Gandke (kontakt2005 @ gandke.de). Eine kurze Beschreibung der bisherigen Projekte reicht aus.
Es gibt in DotNetNuke keine Möglichkeit eine neu angelegt Gruppe (Rolle) allen oder nur einem bestimmten Teil von Usern zu zuordnen.
Da es heute bei mir schnell gehen mußte, habe ich das über SQL-Statements gelöst aber vielleicht bau ich ja auch mal ein Modul für DNN....
DotNetNuke verwaltet die Zuordnng von Usern und Rollen in zwei Systemen
- Ein eigenes System von DNN, besteht aus ein paar Tabellen
- Die Microsoft Implementierung von MemberRole
Ich erspare mich jetzt zu schildern, warum das so ist ....
Es ist darauf zu achten, dass alle beiden Bereiche von DNN aktuallisiert werden!
Hier die SQL-Befehle:
Declare @ApplicationId nvarchar(255) Declare @RoleGUI nvarchar(255) Declare @RoleId int
--Die interne GUI für das Portal SET @ApplicationId = '{59DFEA62-67E2-450E-A039-91ECA87FCDF4}' --Die eindeutige Kennzeichung einer Rolle in der ASPNET Implementierung SET @RoleGUI = '{D8N05067-B4BD-4ER9-9773-F1BAC67FF47G}' --Die eigene DNN Verwaltung SET @RoleId = 1
INSERT INTO aspnet_UsersInRoles ( UserId, RoleId ) SELECT U.UserID, @RoleGUI As RoleId FROM ASPNET_USERS U WHERE (ApplicationId = @ApplicationId) and (U.UserId not in (SELECT UR.UserId FROM aspnet_UsersInRoles UR WHERE UR.RoleId = @RoleGUI));
--SELECT Count(*) FROM ASPNET_USERSINROLES WHERE RoleId = @RoleGUI;--
INSERT INTO UserRoles ( UserId, RoleId, ExpiryDate ) SELECT U.UserId, @RoleId as RoleId, '03.08.2005' AS ExpiryDate FROM Users U WHERE U.UserId not in (SELECT UserId FROM UserRoles WHERE RoleId = @RoleId)
--SElECT Count(*) FROM UserRoles WHERE (RoleId = @RoleId)---
In der letzten Zeit gab es immer wieder Probleme mit den Passwörtern von Host / Admin Accounts in DotNetNuke.
Mit der Version DNN 3.0.13 hat das Core-Team von DotNetNuke, die Schlüssel für die Passwort Verschlüsselung in die Web.config ausgelagert. Durch ein Update werden die Schlüssel jedes Mal überschrieben bzw. neu erzeugt.
Sollte man nun keine Datensicherung haben (was eigentlich eine Totsünde ist!), gibt es zumindest einen Trick, wie man Host und Admin Passwörter manuell zurücksetzen kann.
- Einfach als neuen User registrieren und das dort vergeben Passwort sich merken.
- Dann in die Datenbank gehen und das Passwort / PasswordSalt (bzw. den Wert der Felder) mit den Werten beim Host und/oder Admin austauschen. Diese Informationen liegen in der Tabelle "aspnet_Membership"....
Somit hat man zumindest den Zugang zu diesen Accounts wieder hergestellt.
Natürlich hilft das einem auch nicht, wenn man keine öffentlichen Registrierungen zulässt und man muss Zugriff auf die Datenbank der DotNetNuke - Installation haben.
Vor einiger Zeit habe ich bei DotNetNuke einen Fehler in der automatischen Anmeldung festgestellt.
Die User können über den Schalter "Anmeldedaten merken" ein automatisches Login durchführen lassen. Sollte ein Benutzerkonto nun gespert sein (z.B. durch falsche Eingabe von Benutzername / Passwort), dann wird beim LogIn dieses ignoriert und der User kann sich weiterhin automatisch anmelden.
Um das zu umgehen habe ich den Core-Code ein wenig modifiziert (ja ja .. nicht schön und gefällt mir auch selber nicht, war jetzt aber erst mal eine quick-and-dirty Lösung).
In der Klasse "compontens\Users\UserController.vb" die Funktion "GetCurrentUserInfo" modifizieren:
Dim objUser As UserInfo = CType(HttpContext.Current.Items("UserInfo"), UserInfo) If Not ObjUser Is Nothing Then Return objUser Else Return New UserInfo End If
Ersetzen durch:
Dim objUser As UserInfo = CType(HttpContext.Current.Items("UserInfo"), UserInfo) If Not ObjUser Is Nothing Then If objUser.Membership.LockedOut Then Dim _portalSettings As PortalSettings = PortalController.GetCurrentPortalSettings
FormsAuthentication.SignOut()
HttpContext.Current.Response.Cookies("portalaliasid").Value = Nothing HttpContext.Current.Response.Cookies("portalaliasid").Path = "/" HttpContext.Current.Response.Cookies("portalaliasid").Expires = DateTime.Now.AddYears(-30)
HttpContext.Current.Response.Cookies("portalroles").Value = Nothing HttpContext.Current.Response.Cookies("portalroles").Path = "/" HttpContext.Current.Response.Cookies("portalroles").Expires = DateTime.Now.AddYears(-30)
' Redirect browser back to portal Dim strURL As String = "" If _portalSettings.HomeTabId <> -1 Then strURL = NavigateURL(_portalSettings.HomeTabId) Else strURL = GetPortalDomainName(_portalSettings.PortalAlias.HTTPAlias, HttpContext.Current.Request) End If HttpContext.Current.Response.Redirect(strURL, True) Else Return objUser End If
Else Return New UserInfo End If
Dieser Weg ist noch keine wirklich sauber Lösung aber zumindest erst mal ein brauchbarer Bugfix. Wenn ich etwas mehr Luft haben, versuche ich eine andere Lösung zu finden.
Für große Seiten kann es hilfreich sein die zu übertragenden Bytes zu komprimieren. Dadurch können die Ladezeit optimiert werden.
Eine HTTPModule für .NET (DotNetNuke) gibt es unter http://www.blowery.org/code/HttpCompressionModule.html.
Die Installation ist sehr einfach und ist innerhalb von wenigen Minuten erledigt.
Zuerst die Dateien in das "\bin" Verzeichnis der Webanwendung kopieren.
blowery.Web.HttpCompress.dll
blowery.Web.HttpCompress.dll.xml
ICSharpCode.SharpZipLib.dll
ICSharpCode.SharpZipLib.dll.xml
Dann muss die Web.config angepasst werden:
Im Abschnitt configSection folgendes hinzufügen:
<sectionGroup name="blowery.web"> <section name="httpCompress" type="blowery.Web.HttpCompress.SectionHandler, blowery.Web.HttpCompress"/> </sectionGroup>
Das httpModul hinzufügen
<system.web> <httpModules> <add name="CompressionModule" type="blowery.Web.HttpCompress.HttpModule, blowery.web.HttpCompress"/> </ httpModules> </system.web>
In die Web.config aber nicht innerhalb der system.web folgende Zeilen einfügen
<blowery.web> <httpCompress preferredAlgorithm="deflate" compressionLevel="high"> <excludedMimeTypes> <add type="image/jpeg"/> <add type="image/gif"/> </excludedMimeTypes> <excludedPaths></excludedPaths> </httpCompress> </blowery.web>
Schon ist die Konfiguration abgeschlossen!
Aber VORSICHT! Bevor ein Update von DotNetNuke eingespielt wird, muss dass httpModul deaktiviert werden.
Eine Microsoft Veranstalltung hat gestern acht Personen zusammengeführt, die sich alle mit dem Thema DotNetNuke beschäftigen.
Viele kannte man nur aus dem Forum und es war eine sehr gute Gelegenheit mal endlich die Gesichter hinter den Namen zu sehen.
Kurzentschlossen ist dann nach ein paar Bierchen dieses Bild hier entstanden:

Es war ein sehr netter Abend und schnell waren wir uns einig, dieses in der Zukunft fortzusetzen. Immerhin gibt es eine ganze Menge Stuff rund um DotNetNuke.
Weiter Kommentare gibt es im unter http://blog.gandke.de und im Forum http://www.dnnportal.de
Jeder der mit dem eingebauten WYSIWYG Editor (FreeTextBox) bei DotNetNuke unglücklich ist .. für den gibt es gute Nachrichten. Mittlerweile hat sich einer aus der Community hingesetzt und einen Provider für den OpenSource Editor FCKEditor entwickelt.
Diesen findet man unter http://dnn.tiendaboliviana.com/web als Download.
Eine Anleitung für den Einbau des Editors in DotNetNuke findet man unter http://www.dotnetnuke.de/Default.aspx?tabid=163
Da die DotNetNuke Version 3.1.0 einige Schwierigkeiten und negative Überraschung mit sich bringt, hat sich Hans-Peter von deutschen dnn-portal hingesetzt und eine fehlerbereinigte Version inkl. der deutschen Lokalisierung erstellt.
Den Download gibt es unter:
http://www.dnnportal.de/Downloads/tabid/176/Default.aspx
Das Core-Team von DotNetNuke hat die Strategie bei den mitgelieferten Modulen geändert. Diese werden jetzt nicht automatish mit DotNetNuke installiert sonden müssen / können einzeln installiert werden. Dabei müssen diese Module nicht mit der Hand installiert werden sonden einfach in den Ordner Install/Module abgelegt werden.
Bei der Originalauslieferung liegen die bisherigen Module schon (als ZIP - Datei mit einem dnn-File) in diesem Ordner vor. Auf den ersten Blick sieht man den Source Code nicht mehr. Keine Panik, das Core-Team hat den Source nur in die Datei Projekt.resources versteckt. Einfach in ZIP umbennen, auspacken und glücklich sein!
Nachdem jetzt schon seit ein paar Tagen die DotNetNuke Seite auf der Version 3.1 läuft, gibt es diese Version nun auch endlich als Download.
Unter www.dotnetnuke.com gibt es die Version DNN 3.1 vom 09.06.2005.
Da bin ich jetzt aber mal gespannt!
In der aktuellen Version von DotNetNuke (DNN 3.0.13) hatte ich vermehrt mit der Fehlermeldung
"Die Internetseite ... kann nicht angezeigt werde. Vorgange abgebrochen" zu kämpfen!
Dies Meldung kamm immer in einer JavaScript alert MessageBox und sah so aus:

Leider kann man diesen Fehler nicht provozieren und erst recht nicht reproduzieren.
Mittlerweile habe ich eine Lösung für das Problem:
Die SolPart-Komponente scheint hier diesen Fehler zu erzeugen und das auch nur im Internet Explorer. In der JavaScript-Datei "spmenu.js" muss einfach eine Zeile verändert werden:
this.delaySubmenuLoad=(spm_getAttr(o, 'delaySubmenuLoad', '0') != '0' && spm_needsSubMenuDelay());
ändern in:
this.delaySubmenuLoad=spm_needsSubMenuDelay();
Danach war der Fehler bei mir behoben.
Hoffentlich übernimmt das CoreTeam von DotNetNuke auch diese Änderung in der nächsten Version.
Es lohnt sich doch immer erst mal zu forschen, ob jemand eine Problemstellung schon mal gelöst hat, bevor man etwas selber programmiert. :)
Heute musste ich zum ersten Mal (in einem DotNetNuke Modul) eine Auswahl von Dateien aus dem Portal vornehmen. Hatte bisher aber mir noch nie angeschaut, wie das so geht. Das Core-Team von DotNetNuke rocks .. die haben natürlich ein sehr coole Komponten geschrieben, um das Problem zu lösen.
<%@ Register TagPrefix="Portal" TagName="URL" Src="~/controls/URLControl.ascx" %>
<portal:url id="ctlURL" runat="server" width="300" showtabs="false" showfiles="true" showUrls="false" urltype="F" showlog="false" shownewwindow="false" showtrack="false"/>
Mit diesen beiden Zeilen kann man folgende Funktionalität in DotNetNuke abbilden:
- "showfiles" -> Auswahl einer Datei aus dem Portal
- "showtabs" -> Auswahl einer Seite (Tab) aus dem Portal
- "showUrls" -> Eingabe einer URL
- "showlog", "shownewwindow", "shownewwindow" ;-> Die bekanten Einstellungen
So macht das Entwickln echt Spaß :)
Heute Abend habe ich mal mit ein interessantes Thema beschäftigt - Scheduler-Jobs unter DotNetNuke.
DotNetNuke im Core einen eigene Implementierung für Scheduler, allerdings laufen diese Jobs im Prozess er Webanwendung. Dieses bedeutet, dass die einzelnen Jobs nur dann ausgeführt werden können, wenn der Hauptprozess der Webanwendung auch läuft. Darauf kann man sich allerdings nicht wirklich verlassen ...
Aus diesem Grund habe ich eine eigene Architektur entwickelt, bei der man vom Hauptprozess unabhängig ist.
Folgendes Szenario: Ich möchte jeden Abend um Punkt 21 Uhr eine E-Mail an ganz bestimmt User verschicken.
In einem Windows NT-Service habe ich einen Scheduler integriert, der je nach Konfiguration zu einem beliebige Zeitpunkt verschiedene Assemblies ausführen kann. Natürlich hätte man auch den Windows internen Scheduler nehmen können aber so habe bin ich etwas flexibler, was die Konfiguration betrifft.
Wie kommt jetzt dieser Service an Daten von DotNetNuke ran? Nun der Scheduler ruft zu einem ganz bestimmten Zeitpunkt ein Programm auf, dass für den Versand der E-Mail zuständig ist - oder viel mehr das die E-Mails aufbereitet und dann in eine MSMQ schiebt. Die benötigten E-Mailadressen bekommt dieses Programm über einen Web Service der innerhalb der DotNetNuke Webanwendung läuft. Bei diesem Web Service handelt es sich lediglich um Schnittstelle, die dann wiederum auf eine typische DotNetNuke Assembly zugreift. Damit ist die Grundarchitektur von DotNetNuke nicht verändert wurden.
Der Source Code für den Web Service ist wirklich sehr simple:
using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Web; using System.Web.Services; using System.Xml ; using System.Xml.Serialization ; using Lowfett.Goldmember.WeightProcess.MailNotification.Business ;
namespace Lowfett.Goldmember.WeightProcess.Webservive.MailNotification { /// <summary> /// Zusammenfassung für Service1. /// </summary> public class WSMailNotification : System.Web.Services.WebService { public WSMailNotification() { //CODEGEN: Dieser Aufruf ist für den ASP.NET-Webdienst-Designer erforderlich. InitializeComponent(); }
#region Vom Komponenten-Designer generierter Code
//.... #endregion
[WebMethod] [System.Xml.Serialization.XmlInclude(typeof(MailNotificationInfo))] public ArrayList GetUserToNotify() { return new MailNotificationController().GetUserToNotify() ; }
} }
Wichtig ist das die Assembly des Web Service im "bin" Verzeichnis von DotNetNuke liegt - die asmx Datei kann in einem beliebigen Unterverzeichnis liegen.
Den Source Code für den NT-Service und den Client des Web Services erspare ich mir an dieser Stelle!
Die Seite www.dotnetnuke.com läuft jetzt mit der noch nicht verfügbaren Version 3.1 von DotNetNuke.
Das läßt vermuten, dass diese Version von DotNetNuke wohl auch bald zum Download bereit gestellt wird.
Hauptsächlich wurden in diesem Release Bugfixes eingepflegt. Eine genau Übersicht gibt es unter http://support.dotnetnuke.com....
Hans-Peter von deutschen DNN-Portal hat dort einen recht interessanten Hinweis gepostest:
http://www.dnnportal.de/Weblog/tabid/177/EntryID/112/Default.aspx
Ein Tip an alle DotNetNukler: Überpürft mal ob man wirklich alle Einträge braucht die DotNetNuke dort reinschreibt und vor allem ob und wie lange die Einträge dort gespeichert werden.
Immerhin hat DotNetNuke die Tabelle SiteLog bei mir auf 10.000.000 (da ist keine Null zu viel) anwachsen lassen. Wie man sich vorstellen kann, kommen da einige MB zusammen.
Da ist wohl morgen erst mal "Putztag" angesagt und das nicht nur in meiner Wohnung :)
DotNetRocks ist eine Radiosendung die sich mit allem rund um das Thema .NET befasst. In einer der letzten Sendungen war ein paar der Köpfe von DotNetNuke als Gäste eingeladen. Dabei handelte es sich um "Jim Duffy" und "Shaun Walker"!
Wer sich diese Sendung anhören möchte ... hier ist der direkte Link:
http://www.dotnetrocks.com/default.aspx?showID=113
Echt cool
Die Inhalte sind:
- Wichtige Änderungen zwischen der Version 2 und der aktuellen Version 3
- Der Gedanke von Open Source
- Die Zukunft von DotNetNuke
Hier ist ein cooler Artikel der kurz und knapp eine Anleitung zum Erstellen eines Windows Service unter DotNet gibt:
http://www.developer.com/net/csharp/article.php/10918_2173801_1
Habe ihn gerade entdeckt, da ich auf der Suche war den Scheduler Service von DotNetNuke zu umgehen. Der hat nämlich so einige negative Eigenschaften, die ich für meinen Anwendungsfall nicht gebrauchen kann.
So ist der Scheduler von DotNetNuke nur verfügbar, wenn auch die Webanwendung aktiv ist. Sollte es also vorkommen, das niemand im Portal online ist und die Webanwendung ist heruntergefahren ... blöde Sache!
Nun ja, deswegen versuche ich das jetzt mit Hilfe eines (DotNet) Windows Service zu implementieren.
Habe soeben ein Fehler in der Benutzerverwaltung von DotNetNuke gefunden. Wenn sich ein Benutzer mit Hilfe eines Cookies immer anmelden möchte wird bei einer späteren Anmeldung per Cookie wohl keine Validierung der Daten durchgeführt. Ein Sperren des Benutzerkontos und auch die Änderung des Passworts haben keinerlei Einfluß... der Benutzer kommt weiter fleißig ins Portal :(
Derzeit setze ich auf dem Live-Server die DotNetNuke Version 3.0.12 ein - werde mal testen ob das in der Version 3.0.13 auch noch so ist.
Bei einem Portal mit DotNetNuke besteht das Problem, dass ne ganze Menge E-Mailtraffic entsteht. Es gibt eine ganze Menge an Funktionen und Modulen, die E-Mail-Benachrichtigungen durch die Gegend schicken. Besonders beim Thema Newsletter versagt DotNetNuke ein wenig - immerhin sprechen wir von mittlerweile ca. 20.000 Usern (oder E-Mailadressen).
Da ich schon seit langem die MSMQ etwas stärker involvieren wollte, war hier die beste Möglichkeit dieses endlich zu realisieren. Eine E-Mail ist ja so wieso ein asynchroner Prozess und was hindert einen also daran die E-Mails in eine gemeinsame "Message Queuing Services" zu schieben, um diese von einer Stelle aus zu verschicken.
MSMQ steht für "Microsoft Message Queuing Services" und ist ein wenig, um asynchrone Prozesse oder man kann diese auch Workflows nennen, abzubilden.
Ein Windows Service sorgt für das Prozessmodell, denn irgendwie muss das Programm zum Abrufen der MSMQ und zum Versenden der E-Mails ja "leben". Die Erstellung eines Windows Service ist nicht spektakulär, deswegen erspare ich mir Details. Wie man einen Versand von E-Mail realisiert ist nun auch ein alter Hut .. damit will ich nun wirklich keinen langweilen.
Okay, ich gebe zu das ist nicht so die super Erfindung aber eine ganz nette Sache um Anwendung DotNetNuke etwas zu entlasten - das "Reinschieben" einer Nachricht in die MSMQ geht nun mal schneller als das direkte Versenden.
Vorteile sind z.B. auch, dass man Transaktionen nutzen kann um so sicherzustellen, dass die E-Mail an den SMTP-Server auch sicher übergeben wurde.
Teilweise werden die Nachrichten direkt von DotNetNuke in die MSMQ geschoben oder aber wenn noch viel "Vorarbeit" geleistet werden muss kommen hier der DotNetNuke Scheduler Mechanismus zum Einsatz.
Warum ich diesen nicht benutze um die E-Mails aus DotNetNuke zu versenden? .. ganz einfach: Ich wollte eine allgemein gültige Schnittstelle haben!
Wer einen seltsamen JavaScript-Fehler bei DotNetNuke bekommt und einfach keine Lösung findet - vielleicht ist da ja eine:
Also der Fehler ist folgender: Beim Laden einer Seite kommt die eine JavaScript-Meldung..
Zeile: 2 Zeichen: 1 Fehler: Syntaxfehler Code: 0
Habe mir einen Wolf danach gesucht. Habe dann den HTTP-Header mitgeschrieben und gesehen das zwischendurch auf die 404 Seite weitergeleitet wurde.
Die Datei: aspnet_client/system_web/1_1_4322/WebUIValidation.js sollte geladen werde, konnte aber nicht gefunden wurden.
Da klingelte es - es fehlten das benötigte aspnet_client - Verzeichnis im Stammverzeich der DotNetNuke Installation.
Ich denkde das dieser Fehler nicht nur für DotNetNuke Anwendungen sonder auch für jede andere ASP.NET Anwendung zutrifft....
Wer schon mal über den lästigen Fehler Javascript error "ScrollTop' is null or not an object. bei DotNetNuke stößt, dem sei hier Abhilfe geschaffen.
Das trat immer auf, wenn ich ein eigenes Modul auf eine Seite platziert habe. Man muss sagen, dass man sich diesen Fehler selber einhandelt. Habe ein paar Module - oder viel mehr den HTML Code dafür - aus einem alten Projekt kopiert. So weit auch kein Problem nur darf natürlich kein weiteresmal ein <form> - Tag im HTML-Code auftauchen!
Also einfach mal mit <strg>-f nach dem Wort "form" suchen und schauen ob das der Grund ist 
Nach ein sehr anstregenden 14 Tagen ist es endlich so weit und mein erstes DotNetNuke-Portal ist online. Also mein erstes Web-Portal auf Basis von DotNetNuke.
Bis auf ein paar Schwierigkeiten ging auch eigentlich alles ganz gut. Jetzt läuft es auf jeden Fall :)
Wer mal schauen will: http://www.lowfett.de
Das wird alles noch wachsen und muss ausgebaut werden .. aber jeder fängt mal klein an :)
Gerade schalte ich mein erstes Portal mit DotNetNuke 3.0.12 online. Bisher hatte existierte immer noch ein Problem, dass bei der E-Mailbenachrichtigung für einen neuen User, der Username und das Passwort fehlten.
Der Grund ist ganz einfach, denn in den Vorlagen steht:
[User:Password] bzw. [User:Password]
richtig ist aber:
[Membership:Password] bzw. [Membership:Password]
Wer neugierig ist und ein weiteres DotNetNuke Portal sehen will: www.lowfat.de oder sehr bald www.lowfett.de Es befindet sich noch in den Anfängen aber aller Anfang ist schwer 
Wie fleißige Leser dieses Weblog wissen, entwickel ich eine (ganze) Menge Module um eine Community auf Basis von DotNetNuke zu realisieren.
Darunter fällt so etwas wie:
- Private Nachrichten (Instant Messaging)
- Erweiterte Benutzerprofile. Mit Angaben wie Alter, Foto, Geschlecht und einen dynamischen Fragekatalog
- Such nach den Benutzernprofilen - das war ein ein wenig Denksport

Was bei einer guten Community nicht fehlen darf ist eine Buddyliste. Nach ein paar Nachforschungen und der No. 1 Anlaufstelle www.dnnportal.de habe ich zwar eine Buddyliste gefunden aber leider ist diese zu einfach gestrickt. Was ist daran kompliziert? Folgendes:
Gerade entsteht eine Buddyliste die:
- anzeigt, welche seiner Buddies online sind
- man hat die Möglichkeit, das Hinzufügen eines Eintrages zu unterbinden - das Hinzufügen meines Buddies muss also durch ihn genehmigt werden
- gleichzeitig kann man die Liste auch nutzen um andere User zu sperren bzw. die Kontaktaufnahme zu unterbinden.
- ein Rechtesystem, dass bestimmt, wer welche Aktion durchführen kann.
Den Grundstein habe ich heute Nacht dafür gelegt. Hoffe das ich morgen damit so weit fertig werde und das dann in das Puzzel Community einbauen kann.
Nachdem jetzt das Modul der Usersuche für DotNetNuke fertig ist, war noch die Anforderung, dass man für unterschiedliche Benutzergruppen differente Rechte vergeben kann. Normale User sollten z.B. kein Bild sehen können.... usw.
Da ich alle meine Module mittlerweile in C# entwickel, habe ich ein Konvertierung des Mechanismus von DNN vorgenommen. Zja, viel Arbeit und eigentlich wollte ich gerade schlafen gehen, immerhin haben wir ja schon vier Uhr ...(nachts). Im Badezimmer ist mir eingefallen, dass es in der Tabelle Permission eine Spalte ModuleDefID existiert ... und das wohl mit gutem Grund. Hmmmm....
Okay, die letzten dreieinhalb Stunden hätte ich mir sparen können :(
Also, wenn jemand von euch die Rechte bei DotNetNuke erweitern will, dann einfach diese in der Tabelle Permissions eintragen und bei ModuleDefID die entsprechende Referenz aus der Tabelle ModulDefinition.
Na, man lernt halt nie aus .... gute Nacht!
Heute habe ich mich noch mal um die Suche in Benutzerprofilen bzw. in der Tabelle ASPNET_PROFILE gekümmert. Um wirklich eine gute Performance zu erreichen. wird man nicht eine redundanten Datenhaltung nicht vermeiden können.
Um nicht den DotNetNuke - Core, Tabellen oder aber die Stored Proceduren von DNN zu verändern, habe ich mich dann für Trigger direkt im MS SQL Server entschieden.
Die Erstellung des Triggers war zunächst etwas problematisch, da man innerhalb eines Trigger nicht auf ein Feld vom Typ "nText" zugreifen kann. Änder der Datentypen wollte ich ja vermeiden und so habe ich einfach die Daten aus der Orginaltabelle gelesen.
Klappt perfekt und die redundante Datenhaltung tut jetzt auch schon fast gar nicht mehr weh :)
Wichtig ist nur das man mit einem Trigger arbeitet, der ausgelöst wird nachdem die Aktion insert ode update durchgeführt wurde.
Beispielhaft sieht das dann so aus:
CREATE TRIGGER GaliNeo_ASPPROFILE_Update ON [dbo].[aspnet_Profile] FOR INSERT, UPDATE AS
DECLAR @sPostalCode varchar(5)
DECLARE @sUserId char(100) DECLARE @iUserId int DECLARE @sUserName nvarchar(50)
/*die aktuelle UserId ermittlen, die vom update betroffen ist */ select @sUserId=Userid from inserted
/*Benutzername aus der Tabelle ermittlen, damit die DNN-UserId ermittelt werden kann*/ SELECT @sUserName = [UserName] FROM ASPNET_USERS WHERE [UserId] = @sUserId
/*Die DNN-UserId wird ermittlet */ SELECT @iUserId = [UserId] FROM Users WHERE [UserName] = @sUserName
/*Ermitteln der geänderten Daten direkt aus der Orginaltabelle */ SELECT @sPostalCode=dbo.fn_GetProfileElement('PostalCode',PropertyNames,PropertyValuesString) FROM ASPNET_PROFILE WHERE [USERID] = @sUserId
IF ((SELECT count(*) FROM GaliNeo_User_Profile WHERE [UserId] = @iUserId)= 0) begin INSERT INTO GaliNeo_User_Profile ( [UserId], [PostalCode], ) VALUES ( @iUserId, @sPostalCode, ) end else begin
UPDATE GaliNeo_User_Profile SET
[PostalCode] = @sPostalCode WHERE [UserId] = @iUserId
end
Mal wieder das alte Problem der Suche in einem Benutzerprofil in DotNetNuke..... zuerst sah die ganze Geschichte noch recht brauchbar aus, allerdings wird das unter "Druck" ziemlich langsam. Eine Suchanfrage dauert da schon mal 8 Sekunden und das um gerade mal 10 - 15 Datensätze zu ermittlen. Ich finde das ist nicht akzeptable, zumal ich jetzt noch mit keiner großen Datenmengen > 30.000 arbeite.
Also hat sich mein Verdacht bestätigt, dass die Lösung einfach nicht performant genug ist. Das ermittlen der benötigten PLZ geht recht schnell, nur leider dann das zerpflücken der Daten aus der Tabelle ASPNET_PROFILE dauert und dauert. Nun hier kann man aber dem guten SQL-Server keine Schuld geben, für das was dort passiert ist er immer noch verdammt gut 
Na jetzt muss aber eine andere Lösung her damit DotNetNuke bzw. meine Lösung hier etwas mehr Spaß macht!
Meine Idee ist jetzt einfach mit einer redundanten Tabelle zu arbeiten, in denen ich die Daten aus der Tabelle ASPNET_PROFILE speichere. Um aber dafür nichts im Core-Bereich zu modifzieren, werde ich versuchen die Daten via Trigger in die neue Tabelle zu schreiben.
Ob mir das geklingt und wie das wird .. na klar, gibt es hier auf dieser Welle!
So, nachdem ich das erste Modul zur Sortierung von den wie ich sie getauft habe "permanten Modulen" fertig hatte, habe ich mich an das nächste gemacht. Schon mal versucht ein solches Modul wieder aus dem Portal bzw. aus einzelenen Seiten zu entfernen? Herzlichen Glückwunsch, so billig können Aushilfskräfte gar nicht sein 
Also musste ein Admin-Modul her, womit ich ein solches Modul schnell entfernen kann.
Der Ablauf ist recht simpel, man wählt das Modul aus, bekommt eine Liste mit allen Seiten und wählt dann aus ob auf allen oder nur auf bestimmten Seiten, das Modul gelöscht werden soll.
Mein nächstes Vorhaben ist etwas kniffliger, denn ich möchte das nach dem Erstellen / Hinzufügen einer Seite, diese direkt alle permanten Module so konfiguriert, wie auf einer "Schablone" definiert. Ja natürlich kopiert DNN die Module auf die neue Seite, aber leider ist die Sortierreihenfolge immer falsch bzw. wird auf -1 gesetzt und das eine oder andere Mal hatte ich auch trouble mit den Skins.
Die Kunst ist hierbei natürlich nicht in den Core einzugreifen... mal schauen wie das wird....
So, nach ein wenig google etwas Arbeit habe ich jetzt ein Lösung gefunden, die sogar recht performant aussieht.
Zunächst noch ein paar Basics:
Die Tabelle ASPNET_PROFILE beinhaltet folgende Felder:
- UserId
- PropertyNames
- PropertyValuesString
- PropertyValuesBinary
- LastUpdatedDate
Das Feld PropertyNames beinhaltet eine mit ":" separierte Zeichenfolge, die definiert welche Benutzereigenschaften / -properties gespeichert werden. Zusätzlich wird die Position dort angegeben. Ein Beispiel:
FirstName:S:39:7
Dieser (Teil-)Eintrage besagt das die Property den Namen "FirstName" hat, vom Typ String "S" ist, an der Postion 39 anfängt und 7 Zeichen lang ist.
Um nun einzelene Daten zur extrahieren, habe ich mir eine die Funktionalität der UDF (User Defined Functions) vom Microsoft SQL Server bzw. der MSDE zu nutze gemacht. Diese Funktionen können direkt aus SQL-Statements aufgerufen werden.
CREATE FUNCTION dbo.GaliNeo_UDF_GetElement ( @ord AS INT, @strToParse AS VARCHAR(8000), @seperator AS VARCHAR(1) ) RETURNS INT AS BEGIN
-- Wenn die Eingabeparatemer null sind, wird auch null zurück gegeben IF @strToParse IS NULL OR LEN(@strToParse) = 0 OR @ord IS NULL OR @ord < 1 OR @ord > LEN(@strToParse) - LEN(REPLACE(@strToParse, @seperator, '')) + 1 RETURN NULL
DECLARE @ipos AS INT, @curord AS INT
SELECT @ipos = 1, @curord = 1
-- nächsts Element suchen WHILE @curord < @ord SELECT @ipos = CHARINDEX(@seperator, @strToParse, @ipos) + 1, @curord = @curord + 1 RETURN CAST(SUBSTRING(@strToParse, @ipos, CHARINDEX(@seperator, @strToParse + @seperator, @ipos) - @ipos) AS INT) END
Die GaliNeo_UDF_GetElement ist eine sehr allgemein Funktion um mit separierte Strings in SQL-Queries zu arbeiten. Sehr hilfreich war dabei ein Artikel auf der Seite WindowsItPro.
Diese Funktion können wir nun in der eigentlichen UDF "GaliNeo_UDF_GetProfileElement" nutzen:
CREATE FUNCTION dbo.GaliNeo_UDF_GetProfileElement ( @fieldName AS NVARCHAR(100), @fields AS NVARCHAR(4000), @values AS NVARCHAR(4000) ) RETURNS NVARCHAR(4000) AS BEGIN
IF @fieldName IS NULL OR LEN(@fieldName) = 0 OR @fields IS NULL OR LEN(@fields) = 0 OR @values IS NULL OR LEN(@values) = 0 RETURN NULL
DECLARE @fieldNameToken AS NVARCHAR(20) DECLARE @fieldNameStart AS INTEGER, @valueStart AS INTEGER, @valueLength AS INTEGER
SET @fieldNameStart = CHARINDEX(@fieldName + ':S',@Fields,0)
IF @fieldNameStart = 0 RETURN NULL SET @fieldNameStart = @fieldNameStart + LEN(@fieldName) + 3
SET @fieldNameToken = SUBSTRING(@Fields,@fieldNameStart,LEN(@Fields)-@fieldNameStart)
SET @valueStart = dbo.GaliNeo_UDF_GetElement(1,@fieldNameToken,':') SET @valueLength = dbo.GaliNeo_UDF_GetElement(2,@fieldNameToken,':')
IF @valueLength = 0 RETURN ''
RETURN SUBSTRING(@values, @valueStart+1, @valueLength) END
Aus einer SQL Query kann jetzt diese Funktion wie folgt genutzt werden: SELECT dbo.GaliNeo_UDF_GetProfileElement('PostalCode',PropertyNames,PropertyValuesString) FROM aspnet_Profile
So, das tat doch mal wieder fast nicht weh und bei 10.000 Profilen ist es von der Performance noch in Ordnung. Mal schauen wie es sich verhält, wenn man etwas mehr Daten in er DB hat.
Ich habe ein Modul geschrieben, dass es einem Portalbenutzer erlaubt mehr über sich zu verraten. Dabei nutze ich zum einen die von DNN Core-Team eingesetzt Whidby Implementierung um verschiedene Daten abzuspeichern.
Jetzt wollte ich noch eine Suche programmieren mit der Möglichkeit sich alle Benutzer im Umkreis von x-KM anzeigen zu lassen (also eine klassische Umkreissuche). Nach einer langen Nacht, ziemlich viel Mathe (oh man studiere ich etwa wieder -)) und google ist die Umkreissuche aus kein Thema. Aber wie komme ich nun an die PLZ der einzelnen Benutzer ran. Diese sind mit allen anderen Informationen wie Stadt, Telefon, usw. in einem Text-Feld gespeichert.
Ich hoffe nicht, dass ich jetzt jedes Textfeld zerlegen muss um an die PLZ zu kommen. Das macht bei mehrere zehntausend Profilen keinen Spaß :( Eine weiter Idee ist mir gekommen, dass ich beim speichern der Profile einen Trigger anwerfe der die PLZ in eine neue Tabelle schreibt.
Frage: Wer hat sich so eine Form der Datenspeicherung einfallen lassen?????
Weiter Infos und die Lösung dieses Problems gibt es hier im Block....
So, jetzt ist das Admin-Modul online und wird beim Kunden getestet. Bei der Entwicklung sind mir noch ne ganze Menge mehr Szenarien eingefallen, die man bei der Verwaltung von DNN - Modulen einstetzen kann z.B.: Schon mal versucht ein permanantes Module zu löschen? Okay, bei 10 Seiten geht das noch aber bei größeren Portalen macht das wirklich keinen Spaß!
Werde mich damit in den nächsten Wochen nach und nach befassen und hoffe somit das DotNetNuke noch besser zu administrieren sein wird. Nicht das DNN schlecht wäre aber es handelt sich halt um ein universelles System.
Die Basis von DotNetNuke ist einfach klasse und das Potential sehr groß!
Na da habe ich doch wieder etwas entdeckt, was an DotNetNuke nicht so super toll funktioniert bzw. schwer zu handel ist. Bei einem Projekt habe ich eine zweite Navigation aufgebaut, die ich mit dem Link-Modul realisiert habe. Diese Module bzw. die Container sollen jetzt auf allen Seiten erscheinen - gut das ist kein Problem, denn DotNetNuke bietet mir ja die Möglichkeit in den Moduleoptionen dieses zu definieren "Show on all Tabs". Das macht DotNetNuke auch ganz brav, nur leider wird die Reihenfolge der einzelnen Module, immer etwas nach dem Zufallsprinzip ermittelt.
Aus diesem Grund habe ich mich heute Abend hingesetzt um für solche Anwendungsfälle ein Modul zu entwicklen, dass die Reihenfolge eines Modul auf allen Seiten neu setzt.
Zunächst wählt man ein Modul und bekommt anschließend eine Liste mit allen Tabs auf denen das Modul angezeigt wird. Nun hat man die Möglichkeit entweder für jedes Tab einzeln eine neue Platzierung anzugeben oder aber für alle Tabs auf einmal.
Natürlich ist das nicht ganz ungefährlich, da es ja auch durch aus sein, dass hier Konflikte auftreten können, wenn ein einzelnes Modul zwischen den permanten Modulen exisitert. Allerdings wird dieser Anwendungsfall im ersten Schritt bewußt auser Acht gelassen. Derzeit (also im aktuellen Projekt) kommt es halt nicht vor.
In diesem Modul steckt mit Sicherheit noch einiges an Potential, um die Usability von DNN zu verbessern ...
Hoffe das ich morgen die ersten Ergebnisse und die Reaktion von DotNetNuke berichten kann...
Nach langem warten ist es endlich so weit, die Portalsoftware DotNetNuke wurde in der Version 3.0.12 freigegeben und diesmal ohne ein lästiges "Beta" dahinter!
Zudem hat das Core-Team eine Erweiterung der Modul-Palette angekündigt. Darauf darf man sehr gespannt sein!
Derzeit arbeite ich daran eine Communtiy auf Basis von DNN zu erstellen. Es handelt sich dabei (wie schon mal weiter unten geschrieben) um eine Community rund um das Thema Ernährung, Fitness, usw. (www.lowfett.de). Was ich für DNN nicht gefunden habe ware so etwas wie erweiterte Benutzerprofile, also die Anforderung z.B. auch ein Bild von sich online zu stellen.
Jetzt habe ich ein einges Modul dafür entwickel. Dabei habe ich zunächst das Profil um folgende Angaben erweitert
- Geburtstag
- Geschlecht
- Größe
- Gewicht
- Sternzeichen
- Haarfarbe
- Augenfarbe
- Bild
Diese Informationen werde über die "Whidbey" Implementierung gespeichert. Da dieses allerdings sehr statisch ist und nicht ohne zu programmieren erweitert geändert werden kann, musste noch dynamischer aufgebaut werden.
Nun habe ich mich hingesetzt und eine Verwaltung geschrieben, die es einem Benutzer - oder viel mehr Admin - erlaubt ein komplett eigenes Profil zu erstellen. Dabei stehen als Antwortmöglichkeiten folgendes zur Verfügung:
- Checkboxen (also Mehrfachauswahl)
- Radiobutton (Einfachauswahl)
- Comboboxen
- Freies Textfeld
Wenn ich es schaffe, werde ich in den nächsten Tagen davon ein paar Screenshots machen.
Durch diesen Mechanismus kann man jetzt weitere Eigenschaften dem Profil hinzufügen (z.B. Hobbies, Interessen, usw.).
Für die DotNetNuke Plattform gibt es nur eine limitierte Anzahl von ECommererce-Lösungen.
Folgende sind derzeit erhältlich:
Nun wird eine weitere Lösung hinzukommen. Da mich keine der Lösungen total überzeugt hat (obwohl CataLook schon fast ein Knaller ist) werde ich nun eine eigenen Implementieren. Eine Schwachstelle soll von Beginn an nicht auftretten: schlechte Usability.
Es wird mit Sicherheit noch einige Zeit dauern bis die Lösung fertig ist aber wer noch Zeit zu warten hat .. soll warten :)
Ach, es wird ein 100% DNN Modul(e) und komplett in C# entwickelt. Will hier keine Glaubenskrieg oder wilde Diskussionen lostretten, aber ich mag C# lieber ... auch wenn es nur wenige Punkte Vorsprung hat zu VB.Net 
Seitdem 6. Dezember ist die deutschesprachige Seite dnnportal.de online. Mittlerweile verzeichnet diese Seite täglich 10.000 Zugriffe und die Benutzeranzahl wächst von Tag zu Tag ...
Fragen / Antworten / Diskussionen / News .. all das findet man auf dieser Seite.
Das ist ein gute Beweis dafür, dass sich DotNetNuke immer mehr durchsetzt und als Portallösung ernst genommen wird.
Bei der Imagegallery der FreeTextBox innerhalb von DNN trat immer das Problem auf, dass Ordner ab der zweiten Ebene nicht mehr angezeigt wurden. Egal welche DNN - Berechtigungen gesetzt wurden, lediglich der Host konnte immer alle Ordner sehen.
Das Problem bzw. die Lösung ist ganz einfach:
In der Datenbank werden die Ordner so abgelegt "MeinOrdner/SubOrdner", bei der Überprüfung der Rechte wird aber "MeinOrdner\SubOrdner" übergeben. Dadurch wird natürlich keine Berechtigung gefunden und die Ordner werden nicht angezeigt.
Eine Zeile Code im Projekt "Provider.Ftb3HtmlEditorProvider" ist nötig und schon läuft es wieder. Öffnen der Datei "ftb.imagegallery.aspx.vb" und die Funktion "Page_PreRender" eine Zeile Code einfügen:
strDirectory = strDirectory.Replace("\", "/")
Die komplette Funktion sieht dann so aus:
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.PreRender
' Obtain PortalSettings from Current Context Dim _portalSettings As PortalSettings = CType(Context.Items("PortalSettings"), PortalSettings)
'Get the list of sub-directories Dim strDirectories As String() = System.IO.Directory.GetDirectories(Server.MapPath(imgGallery.CurrentImagesFolder), "*") Dim alDirectories As ArrayList = New ArrayList Dim strDirectory As String Dim roles As String Dim i As Integer Dim s As String
'Parse directories (only adding those we have permission for For i = 0 To strDirectories.Length - 1
If PortalSettings.ActiveTab.ParentId = PortalSettings.SuperTabId Then strDirectory = strDirectories(i).Substring(Common.Globals.HostMapPath.Length) Else strDirectory = strDirectories(i).Substring(PortalSettings.HomeDirectoryMapPath.Length) End If
'DANFIX strDirectory = strDirectory.Replace("\", "/")
roles = FileSystemUtils.GetRoles(strDirectory, _portalSettings.PortalId, "READ")
If PortalSecurity.IsInRoles(roles) Then alDirectories.Add(strDirectory) End If
Next
imgGallery.CurrentDirectories = CType(alDirectories.ToArray(GetType(System.String)), String())
End Sub
Das DotNetNuke - Team hat einen neue Betaversion (BETA 3.0.11) lanciert. Diese findet man wie immer unter http://www.dotnetnuke.com. Die Installation verläuft wie immer ohne Probleme, selbst ein Update von der 3.0.10 war möglich.
Dieses ist laut Ankündigung die letzte Beta (!) die nächst Version soll eine die 3.0 Final sein.
DotNetNuke ist ein sehr mächtiges und auch ausgereiftes CMS (Content Management System), allerdings hat ein solch mächtiges System immer den üblen Beigeschmack, dass mal als Anwender zunächt hoffungslos überforder ist. Auch wenn die Entwickler von DNN schon eine ganz gut Usability erreicht haben und auch die Installation meist ohne große Probleme verläuft, bleibt die Frage "Wie arbeite ich richtig mit DotNetNuke?".
Eine Standardantwort gibt es zunächst nicht, wer jedoch bei diesem Thema individuelle Hilfe braucht, kann sich bei mir melden. (mail at dotnetnukeblog punkt de)
Wer sich schon immer fragte, wie man bei einem DotNetNuke Modul (bzw. einem ASCX-Control unter DNN) eine eigene JavaScript Datei einbinden kann .. hier die Antwort:
- Die entsprechende JavaScript Datei in das Visual Studio Projekt aufnehmen
- Im Page_Load Event folgendes einfügen:
Dim jsFilePath As String = ResolveUrl("MeinSkript.js") Me.Page.RegisterClientScriptBlock("MeinSkript.js", "
")
Danach sind die Funktionen des Skripts auf dem Client verfügbar.
Unter http://www.microsoft.com/germany/msdn/library/net/ aspnet/EinfuegenVonClientseitigemSkriptAusEinemASPNETServersteuerelement.mspx findet man auch noch einen interessanten Artikel von Microsoft zu diesem Thema (generell Client-Skripte einfügen).
Die Portallösung DotNetNuke ist mittlerweile sehr mächtig. Obwohl die Bedienung in den meisten Fällen sehr Benutzerfreundlich ist, kann man durchaus verschiedenen Dinge optimieren. Diese Erkenntnis km mir gestern, als ich eine „Einführung“ von DotNetNuke gegeben habe.
So war der Entschluss recht schnell gefasst, dass ein paar extra Admin-Module den Komfort und vor allem die Schnelligkeit durchaus erhöhen. Diese sollen dann mehr wie eine Schnellerfassung arbeiten …
Mehr zu diesem Thema .. wie immer ... in diesem Blog.
Wer neugierig ist was DotNetNuke ist, was es kann, wo man es herbekommt und so ein richtig schönes KickOff haben will .. es gibt auf der MSDN-Online Seite von Microsoft einen WebCast zum Thema DotNetNuke.
Das Schöne ist dabei, man muss nichts installieren und bekommt trotzdem schon mal einen sehr guten Überblick!
Hier ist der Link: http://www.microsoft.com/germany/msdn/webcasts/detail.aspx?id=100341
Da es für Dotnetnuke mittlerweile nur noch einen Datenbankprovider gibt, wäre es doch sehr schön weiter kostenlose Alternativen zu schaffen. Aus diesem Grund hat sich in den letzten Tagen eine Gruppe zusammengefunden, die sich nun mit der Erstellung allternativer Datenbankprovider beschäftigt. Derzeit besteht das Team aus drei Leuten - Tom www.dbresource.de, Hans-Peter www.dnnportal.de und meiner Person.
Bin sehr gespannt wie sich das weiterentwickelt. Die ersten Schritte sind auf jeden Fall gemacht.
Wäre doch schön, wenn DotNetnuke nicht nur mit dem MS SQL-Server sondern auch mit Firebirdsql oder MySQL zusammenarbeiten würde ....
Mehr in den nächsten Tagen!
Nachdem ich mich heute den ganzen Abend über mein Notebook geärgert habe und ich es nun neu Aufsetzen muss, brauchte ich auf jeden Fall noch ein Erfolgserlebnis, bevor ich schlafen gehe!
In den letzten Tagen ist ein Projekt ins Leben gerufen wurden, dass sich mit DotNetNuke und der OpenSource Datenbank Firebird beschäftigt. Es gibt für DNN 3 leider keine weitern Datenbankprovider. So haben wir beschlossen, eine Unterstützung von Firebird für DNN 3 zu implementieren. Später wollen wir dann auch MySQL mit ins Boot nehmen - Firebird ist quasi zum warm werden.
Also; weil mein Notebook so schön arbeitet und nur von Zeit zu Zeit eine CD verlangt, habe ich angefangen meine anderen Rechner mit Firebird auszustatten. Die Installation und Einrichtung verlief ohne Probleme :) und ein paar Minuten später konnte ich auch schon die ersten Daten auslesen. Na das sieht alles ganz gut aus .... mal schauen wie es weitergeht.
Alles weiter werde ich hier berichten. Leider ist meine Zeit im Augenblick sehr knapp, da ich gerade versuche mit Hilfe von DotNetNuke die www.lowfett.de neu aufzubauen.
Naja, jetzt kann ich später die Augen getrost zu machen gehen. :)
I'm rocking the world, yeah 
Dieses liegt an der Einstellung in der Web.Config.
Nach der Installation steht dort folgendes:
<globalization culture="en-US" uiCulture="en" requestEncoding="UTF-8" responseEncoding="UTF-8" fileEncoding="UTF-8" />
Ändert man dieses ab in:
<globalization requestEncoding="iso-8859-15" responseEncoding="iso-8859-15" culture="de-DE" uiCulture="de-DE" fileEncoding="iso-8859-15" />
oder
<globalization requestEncoding="UTF-8" responseEncoding="UTF-8" culture="de-DE" uiCulture="de-DE" fileEncoding="UTF-8" />
Werden auch Umlaute wieder richtig angezeigt.
Nachdem ich mich jetzt schon einige Zeit mit dem ständig cooler werdenden freien Portalframework DotNetNuke (DNN) beschäftige, nimmt die Begeisterung keine Abbruch.
Neben diesem Weblog kann ich noch die sehr gute deutsche Portalseite empfehlen: DNNPortal. Dort findet man News und Support in deutsch.
|