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 :)
So, endlich habe ich heute mal etwas Zeit gefunden um mein Blog auf die aktuellste Version von dasBlog.net zu aktualisieren.
Die Anpassung an ein anderes Design hat zwar noch nicht so ganz funktioniert aber ich werde die Tage noch mal daran arbeiten. Bis jetzt läuft die Version 1.9.6264.0 sehr zufriedenstellend und auch das eigentliche Update der Blogsoftware stelle kein Problem dar.
Sollte es doch irgendwelche Probleme geben, dann sagt mir doch bitte bescheid 
Hier ein paar Blogbeträge zum Thema Barcodes und wie man diese unter DotNet erzeugen kann ohne 3rd-party Komponenten:
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
} }
Wer schon mal HTML-E-Mails verschickt hat kommt wohl kaum um das Problem herum, dass man auch Bilder dieser E-Mail hinzufügen möchte. Der erste und einfachste Weg ist, diese einfach auf einem Server abzulegen und dann auf diesen zu verweisen. Was ist aber wenn der Anwender keine Internetverbindung hat, der Server bzw. das Bild nicht mehr erreichbar ist? Dann sehen diese E-Mails meist sehr unschön aus.
Gerade habe ich einen netten Artikel gefunden, der Beschreibt, wie man ein Bild als E-Mailanhang mitschickt und wie man die Verbindung zwischen Bild und Anhang herstellen kann.
Hier einmal die Kurzfassung:
<IMG height=68 src="cid:015024716@24012006-255A" width=140 align=top border=0>
Die Sourceanweisung mit dem Wert "cid:015024716@24012006-255A" ist hier das interessante. Die RFC-Spezi. besagt das jeder E-Mailanhang eine eindeutige Id bekommt.
Der benötigte Sourcecode zum Versand der E-Mail:
'Zu erst mal die Imports die benötigt werden Imports System.Net.Mail Imports System.Net.Mime
Public Sub SendMail()
Dim objMail As New MailMessage Dim objSender As New MailAddress("absender@server.de") Dim objSmtpClient As New SmtpClient("smtp.server.de:8881") Dim objEmpfaenger As New MailAddress("empfaenger@server.de")
objMail.To.Add(objEmpfaenger) objMail.From = objSender objMail.Subject = "Betreff der Mail"
'Damit das ganze auch funktioniert muss man angeben, 'das man die Mail im HTML-Format verschicken möchte objMail.IsBodyHtml = True
'So jetzt zum spannenden Teil, das Bild als Attachment anfügen Dim objFootImage As New Attachment(Server.MapPath("LOGO.gif"), _ MediaTypeNames.Image.Gif) objFootImage.ContentId = "01" objFootImage.ContentDisposition.Inline = True objFootImage.TransferEncoding = TransferEncoding.Base64 objMail.Attachments.Add(objFootImage)
'Und so wird es anschließend verwendet objMail.Body = "<img src=""cid:01"" border=0 height=68 width=140>"
'Jetzt nurnoch die Mail verschicken und fertig objSmtpClient.Send(objMail) End Sub
Eine ausführliche Erklärung des ganzen gibt es auf dieser Seite
Soeben habe ich eine sehr coole Komponente entdeckt, die es einem relativ einfach ermöglicht bei einer ASP.NET WebForm einen "Bitte warte Sie"-Dialog / BusyBox einzubelnden. Dieses ASP.NET Komponenten ist sehr anpassbar und scheint auf dem ersten Blick sogar schon in der Version 0.2.1 sehr brauchen zu sein.
Das Opensource Projekt heißt "BusyBoxDotNet" und ist hier zu finden.
Mal schauen wie sich die Komponente unter DotNetNuke verhält und ob man diese für eine Modulentwicklung einsetzen kann.
Die Komponente ist nur für ASP.NET 2.0 verfügbar ...
Gestern abend war ich mal wieder auf einem Techtalk zum Thema:
"Teile und herrsche: Verteilte Lösungen mit der Windows Communication Foundation"
Hier bot Christian Weyer eine echt klasse "Show" und vermittelte eine sehr gute Einführung in das Thema SO (ohne "a") und WCF. Dabei wurden den Zuhöreren aber keine Slides um die Köpfe geschmießen, sondern Christian arbeitet mit Flipcharts und vielen Code-Beispielen. Man konnte das erzählte meist direkt in der Praxis sehen und somit vielfach deutlich schneller verstehen.
Ende des Jahres gibt es eine weiter Beispielanwendung TecTv, das viele Bereiche des neuen .NET Frameworks 3.0 zeig... also WCF, WPF, WWF. Darauf darf man gespannt sein.
Mittlerweile gibt es viele XML-Editoren jetzt gibt es einen XML-Notepad :)
Das XML Team von Microsoft hat eine .NET 2.0 Anwendung released mit der man XML Documents bearbeiten kann, XSL supported, XML Schema Validierung und sogar ein XML Diff Tool... zu guter letzt gibt es sogar intellisense. Auch bei großen Dokumente ist die Performance der Anwendung gut und im Vergleich zu vielen anderen Editoren wirklich mal zu gebrauchen.
Den Download gibt es hier. Voraussetzung für das 2XML-Notepad" ist das .NET Framework 2.0.
Der erste Eindruck sieht echt gut aus, werde das jetzt mal in der Praxis vermehrt einsetzen.
Ich habe gerade eine coole Seite über Threading in .NET 2.0 gefunden, die auch viele Beispiele in C# bietet.
http://www.albahari.com/threading/
Zudem gibt es (derzeit links unten) einen PDF, das nun auf meinem "muss ich unbedingt mal komplett Lesen" Stappel liegt 
Auf CodePlex wird von Microsoft ein Projekt mit dem Namen Phalanger gehostet. Phalager soll einen PHP-Compiler anzubieten, der es ermöglicht, PHP-Skripts ohne Modifikation auf .NET zu kompilieren. Dabei erzeugt der Compilier aus PHP-Skipts MSIL (Microsoft Intermediate Language). Ausprobiert habe ich es selber noch nicht, allerdings finde ich den Ansatz sehr interessant!
Hier der direkte Link zum Projekt auf CodePlex
Wenn man aus einem Pool von x Zeilen, die ein Select-Statement zurückliefert, eine zufällige Auswahl an Zeilen habe möchte geht das ganz einfach so: SELECT TOP 5 NEWID() AS randomNumber, * FROM [MyTable] ORDER BY 1
In diesem SQL-Statement wird einfach eine Guid erzeugt und das Resultset nach dieser zusätzlichen Spalte sortiert. Durch die Anweisung TOP 5 werden dann auch nur die ersten fünf Zeilen im Resultset aufgeführt.
Schon ist es vollbracht!
Alternativ - und wie ich auch gerade festgestellt habe der von Microsoft vorgeschlagene Weg - kann man auch folgenden Befehl nutzen
SELECT TOP 5 * FROM [MyTable] ORDER BY NEWID()
Vorteil: Die zusätzliche Spalte randomNumber wird nicht mit in das Resultset aufgenommen und ich persönlich finde es auch etwas eleganter :)
Gerade habe ich auf GotDotNet mal wieder eine wirklich coole Komponente gefunden, mit der man die Sidebar von Outlook 2003 abbilden kann.
Zu finden gibt es dieses .NET Komponenten - die übrigens in C# implementiert wurde - inkl. dem kompletten Sourcecode und einer Beispielanwendung, wie man die Komponente einsetzt, genau hier (klickst Du).
Letzte Woche Donnerstag war ich auf dem diesjährigen NRW Sumit veranstaltet von JustCommunity e.V.. Es war eine wirklich klasse Veranstaltung, auf der man eine ganze Menge geboten bekommen hat. Es gab sehr viele interessante Vorträge und die eine besser Auswahl an Dozenten kann man wohl kaum treffen. Nur schade war das Christian Weyer absagen musste und damit der Vortrag über die WCF ausgefallen ist. Es war eine gute Gelegenheit sich mit Kollegen auszutauschen und ein paar Anregungen mitzunehmen.
Es wurden aber nicht nur Vorträge zum Thema "Mircosoft" angeboten auch die PHP- und Linuxwelt waren mit Referenten vertreten. Also für jeden Geschmack gab es das passende Angebot.
Besonders gespant war ich auf den letzten Vortrag über "Indigo & SOA in the real World", in dem Daniel Fisher und Michael "Security" Willers aus einem Projekt für das BSI berichteten. Ziel war es wohl Indigo (WCF) auf Sicherheitsmerkmale zu überprüfen. Nun und auf der ersten Folie stand dann plötzlich Proseware :) ... die Anwendung lebt also doch noch. Ich bin leider nicht dazu gekommen nachzufragen ob die Anwendung komplett neugeschrieben wurde oder aber ob es die Basis von Clemens ist. Leider hat Proseware ja nie eine Freigabe von Microsoft erhalten :( aber diese Version wird wohl zum Ende des Jahres erhältlich sein ... ich denke auf diese Anwendung darf man sich sehr freuen!
Leider konnte ich nicht alle Vorträge besuchen da immer vier Tracks parallel liefen und das von 10:00Uhr Uhr bis Abends 20:30Uhr (!). Aufgrund der Länge und des doch sehr warmen Wetters waren wohl alle am Abend ziemlich platt und müde, was bei der anschließende Party mit 50 Liter Freibier aber keinen größeren Schaden anrichtete.
Ein großes Dankeschön geht an dieser Stelle an die beiden Hauptorganisatoren Daniel Fisher und Stephan Oetzel ... ich freue mich sehr auf den NRW Summit 07 :)
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.
Eigentlich bin ich von den Controls des .NET Frameworks 2.0 sehr zufrieden und der Umfang der enthaltenen Controls ist durchaus brauchbar. Aber gerade bin ich doch ein wenig entäuscht, da es die Jungs wohl nicht geschafft, übersehen bzw. nicht an eine sehr simple doch oft gebraucht Funktionalität zu denken.
Ich habe eine Windowsforms-Anwendung auf der sich ein Multiline-Textfeld befindet. Jeder (oder sagen wir lieber viele) Benutzer sind es gewohnt den gesamte Inhalt eines solchen Textfeldes mit Strg-A zu markieren... doch was ist das? Nichts rührt sich, nichts wird markiert :(
Nach einer recherche im Web musste ich wohl feststellen, dass ich nicht zu blöd bin, sondern dieses Problem wohl auch bei anderen existiert. Also beleibt einem nichts übrig als diese Enterprise-Funktionalität selber zu implementieren... das würde dann so aussehen:
if ( (e.Control) && (e.KeyCode==Keys.A)) { this.myTextbox.SelectAll(); }
Mahlzeit!
Manchmal ist erwünscht, dass der Benutzer nur eine Instanze der Anwendung starten kann. Hier ein Code-Beispiel wie man dieses Verhalten über ein Mutex erreichen kann:
[STAThread] static void Main() { Application.EnableVisualStyles(); Application.DoEvents(); // ensure one instance running if(!MainForm.InstanceExists) { Application.Run(new MainForm()); } } static Mutex mutex; static string AppGuid = "4B3DF7C2-1BD3-7d54-AFF0-A3D4656C5EDH"; static bool InstanceExists { get { bool notExists; mutex = new Mutex( false, "Local\\" + AppGuid, out notExists ); return !notExists; } }
Durch die Verwendung einer Guid wird hier die "Einmaligkeit" gewährleistet. Sollte die Anwendung auf einem Terminalserver laufen dann muss "Local\\" gegen "Global\\" ersetzt werden....
In .NET 2.0 ist das Arbeiten mit Threads dank des Backgroundworkers deutlich einfacher geworden. Heute Abend habe ich mich mal damit beschäftigt in einem Backgroundworker einen Treeview zu füllen. Der Zugriff auf ein Control in der Methode DoWork() ist nämlich nicht möglich, aber es gibt einen Trick, dieses zu lösen.
Zunächst einmal die Basics um einen Backgroundworker bereitzustellen:
this.backgroundworker = new BackgroundWorker(); this.backgroundworker.WorkerReportsProgress = true; this.backgroundworker.DoWork += new DoWorkEventHandler(backgroundworker_DoWork); this.backgroundworker.ProgressChanged += new ProgressChangedEventHandler(backgroundworker_ProgressChanged); this.backgroundworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundworker_RunWorkerCompleted);
Wichtig dabei ist lediglich das Event ProgressChanged zu implementieren und die Property WorkerReportsProgress auf "true" zu setzen. Bis hier noch nicht wirklich aufregend....auch der Auruf mit
this.backgroundworker.RunWorkerAsync();
ist wie gewohnt.
In der Methode DoWork() kommt dann aber der Trick...
void backgroundworker_DoWork(object sender, DoWorkEventArgs e) {
TreeNode treenode= new TreeNode(); treenode.Text = 'name'; this.backgroundworker.ReportProgress(0, treenode); }
Hier jetzt einfach mal so viel Vorstellungskraft aufbringen als würde DoWork() eine Schleife, Datenbankabfrage oder ähnliches durchführen, die viel Zeit in Anspruch nimmt. Die Möglichkeit eine Fortschritt zu Reporten kann man nun nutzen um ein Object an eine Form weiterzugeben. Die Implementierung der Methode/Event ProgessChanged könnte dann so aussehen:
void backgroundworker_ProgressChanged(object sender, ProgressChangedEventArgs e) { this.tvNavigator.BeginUpdate(); this.tvNavigator.Nodes.Clear(); this.tvNavigator.Nodes.Add((TreeNode)e.UserState); this.tvNavigator.EndUpdate(); }
Mit diesem Trick ist es nun möglich einen TreeView asyncron zu füllen....
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.
|