.NET-Software-Entwicklung - DotNetNuke - Business-Develoment
# Thursday, August 17, 2006

In eine SQL Select Statement eine zufaellige Menge an Zeilen zurueckliefern

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 :)


Thursday, August 17, 2006 7:46:11 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
Allgemein | Datenbank
# Monday, July 31, 2006

Mal wieder eine coole Komponente: Outlook 2003 Style Sidebar

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).


Monday, July 31, 2006 7:57:00 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET 2.0 | Allgemein | Opensource | Winform | Controls

NRW06 Summit am 27.08.2006 .... ich war dabei

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 :)

 

 


Monday, July 31, 2006 12:13:37 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET | Allgemein
# Friday, July 21, 2006

DotNetNuke 3.3.3 Final Release

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.


Friday, July 21, 2006 11:52:50 AM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET | ASP.NET | DotNetNuke | Opensource
# Thursday, July 13, 2006

Ein paar Dinge rund um Icons

Habe gerade bei der Suche nach Software um Icons aus einem Programm zu extrahieren folgendes gefunden:

Batch-Icon-extractor ist eine Tool für die Kommandozeile und extrahiert aus einem Verzeichnis inkl. Unterverzeichnisse alle Icons:
http://www.rw-designer.com/batch-icon-extractor

IconsExtract  ist ein weiters Tool um Icons zu extrahieren:http://www.nirsoft.net/utils/iconsext.html

Ein Editor um Icons zu modifizieren: http://www.soft32.com/download_123696.html

Hier gibt es noch eine nette Sammlung von Software zu diesem Thema: http://www.surfpack.com/software/icons/


Thursday, July 13, 2006 10:53:57 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
Allgemein | Software
# Thursday, June 22, 2006

Windows Form Textbox und Strg-A bzw. Ctrl-A

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!


Thursday, June 22, 2006 9:32:18 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET 2.0 | Winform
# Monday, June 19, 2006

Nur eine Instanz einer Anwendung starten / zulassen

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....

 


Monday, June 19, 2006 2:47:10 AM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET 2.0
# Sunday, June 18, 2006

In einem BackgroundWorker einen Treeview aufbauen / populate

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....


Sunday, June 18, 2006 11:35:42 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET 2.0 | Winform
# Wednesday, June 14, 2006

Es ist so weit DNN 3.3.0 steht zum Download bereit

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.


Wednesday, June 14, 2006 4:14:28 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET | ASP.NET | DotNetNuke | Opensource
# Monday, June 12, 2006

Christian Weyer erklärt WCF

Eine wirklich sehr coole Vorstellung der WCF (Windows Communication Foundation) gibt es derzeit als Folge von dotnetPro-TV. Zusammen mit Ralf Westphal gibt Christian Weyer einen super Überblick für Einsteiger und Neulinge in diesem Bereich.

Derzeit gibt es das Video sogar für die Öffentlichkeit zugänglich auf der Seite von DotNetPro, der Link zum Video ist in der orangefarbenen Kästchen.

Viel Spaß :)


Monday, June 12, 2006 4:31:02 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET 2.0 | Allgemein
# Thursday, May 25, 2006

www.iis.net Communitysite ist online

Nachdem es für ASP.NET, Windowsforms und Windows Communication Foundation Community und Informatonsseiten im Netz existieren ist seit kurzem auch eine Seite für den IIS (Internet Information Server) online. Wie bei all den anderen Communityseiten gibt es auch hier ein Forum, einen Downloadbereich mit Tools und jede Menge Tips & Tricks.

www.iis.net


Thursday, May 25, 2006 8:31:40 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
Allgemein | Server

DotMSN - Zugriff auf den MSN Messanger Service

Habe gerade eine OpenSource Library/Komponente entdeckt, die den Zugrif auf die Messanagerplattform von MSN ermöglicht. In manchen Anwendungsszenarien macht es durchaus Sinn, einen Messanger als Kommunikationsweg einzusetzen z.B. bei kritischen Fehlermeldungen, Meldungen das ein asyncroner langer Prozess beendet ist, usw.

Wer dafür den MSN Messanger nutzen möchte aber die Anbindung nicht selber programmieren mag, sollte sich folgende Library anschauen: http://www.xihsolutions.net/dotmsn/index.html 

 


Thursday, May 25, 2006 8:19:28 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET | Opensource
# Wednesday, May 10, 2006

Try/Catch Block in SQL Server 2005

Der SQL Server 2005 unterstützt nun eine deutlich bessere Fehlerbehandlung unter T-SQL - ein Try/catch Block erlaubt ein Errorhandling. Die Handhabung ist eigentlich wie bei allen Try/catch-Blöchen die man z.B. aus C#, VB.NET oder Delphi kennt.

Hier ein klassisches Beispeil - divison durch 0:

BEGIN TRY
   DECLARE @X INT
   -- Divide by zero to generate Error
   SET @X = 1/0
END TRY
BEGIN CATCH

   SELECT ERROR_NUMBER() ERNumber,
   ERROR_SEVERITY() Error_Severity,
   ERROR_STATE() Error_State,
   ERROR_PROCEDURE() Error_Procedure,
   ERROR_LINE() Error_Line,
   ERROR_MESSAGE() Error_Message
END CATCH

Als Ergebnis bekommt man:

Error Detected
Err_Num Err_Sev Err_State Err_Proc Err_Line Err_Msg
------- ------- --------- -------------------- --------- --------------------------------
8134 16 1 NULL 4 Divide by zero error encountered.

Ziemlich cool und bei complexen SQL-Statements kann ddas sehr hilfreich sein!


Wednesday, May 10, 2006 3:54:45 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
Datenbank
# Monday, May 08, 2006

Dockpanel fuer WinForms

Gerade habe ich eine doch sehr cooles .NET Opensource Projekt auf sourcefroge.net gefunden. Dabei handelt es sich um eine in C# geschriebene Komponenten die eine Dockingfunktionalität bietet. Vorlage war dabei wohl das Visual Studio.net 2005.

Für so manche .NET Windows Anwendung dürfte das eine wirkliche Bereichung sein. Hier geht es zu der Komponente: Link


Monday, May 08, 2006 5:35:30 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET | Opensource | Winform
# Friday, April 21, 2006

testing regular expressions online

Wer mal "eben" ein Regex-Pattern erstellen möchte und dieses auch direkt testen will, kann ein kleines Online-Tool dafür nutzen. Hier der Link


Friday, April 21, 2006 5:39:16 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET | .NET 2.0 | Allgemein | Software
# Friday, April 07, 2006

Timezones in DotNet: GMT in PST (Pacific Standard Time) konvertieren

Ich kann es ja kaum glauben aber bei dem mächtigen Framework von .Net wird es echt kompliziert eine DateTime Wert von GMT in PST zu konvertieren. Habe gerade ein paar lustige Stunden damit verbraucht eine dieses einigermaßen sauber zu implementieren und hier meine Lösung:

Basis für meine Lösung ist eine Klasse von Clemens Vasters und seiner Blogengine dasblog.net. Dort gibt es im Projekt "newtelligence.DasBlog.Util.csproj" die Klasse "TimeZones.cs". Die nötigen Informationen für eine Konvertierung wird hier allerdings in einer XML Datei gespeichert. Da ich derzeit allerdings nur eine konvertierung nach PST brauch habe ich die XML Datei ignoriert und setze die Daten manuell in einer Klasse.

    /// <summary>
    /// Liefert verschiedne Zeiten auf der Welt zurücl
    /// </summary>
    public class TimeZoneConverter
    {

        /// <summary>
        /// (GMT-08:00) Pacific Time (US &amp; Canada); Tijuana
        /// Pacific Daylight Time
        /// </summary>
        /// <returns>DateTime of Pacific Daylight Time</returns>
        public static DateTime GetCurrentPST()
        {
            return DateTime2PST(DateTime.Now) ;
        }


        /// <summary>
        /// (GMT-08:00) Pacific Time (US &amp; Canada); Tijuana
        /// Pacific Daylight Time
        /// </summary>
        /// <returns>DateTime of Pacific Daylight Time</returns>
        public static DateTime DateTime2PST(DateTime dtDate)
        {


            WindowsTZI pstTZI = new WindowsTZI();
            pstTZI.bias = 480;
            pstTZI.daylightBias = -60;
            pstTZI.standardBias = 0;
            
            WindowsSystemTime standardDate = new WindowsSystemTime();
            standardDate.year = 0;
            standardDate.month = 10;
            standardDate.day = 5;
            standardDate.dayOfWeek = 0;
            standardDate.hour = 2;
            standardDate.minute = 0;
            standardDate.second = 0;
            standardDate.milliseconds = 0;


            WindowsSystemTime daylightDate = new WindowsSystemTime();
            daylightDate.year = 0;
            daylightDate.month = 4;
            daylightDate.day = 1;
            daylightDate.dayOfWeek = 0;
            daylightDate.hour = 2;
            daylightDate.minute = 0;
            daylightDate.second = 0;
            daylightDate.milliseconds = 0;


            pstTZI.standardDate = standardDate;
            pstTZI.daylightDate = daylightDate;
            

            
            WindowsTimeZone tz = new WindowsTimeZone();
            tz.WinTZI = pstTZI;
            
            return tz.ToLocalTime ( dtDate.ToUniversalTime() ) ;

        }


    
    }

Wer das ganze etwas dynamischer haben möchte schaut sich am beste die Klasse vom Clemens an ...

Ich brauchte diese Funktion für die Google-Adwords-API, diese erwatet nämlich das Datum im PST Format.


Friday, April 07, 2006 7:37:20 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET | .NET 2.0
# Tuesday, April 04, 2006

Parameter aus einem Querystring entfernen.

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


Tuesday, April 04, 2006 12:58:22 AM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET | .NET 2.0 | ASP.NET | DotNetNuke
# Monday, April 03, 2006

DNN (DotNetNuke) und Transaktionen

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();
                }

 


Monday, April 03, 2006 10:38:19 PM (W. Europe Daylight Time, UTC+02:00)  #    - Trackback
.NET | .NET 2.0 | ASP.NET | DotNetNuke
# Tuesday, February 28, 2006

Architects Connection

Seit einigen Tagen existiert ein eigenes Informations-Portal für IT-Architekten (www.architectsconnection.de). Dort stehen sehr viele  architekturrelevanten Ressourcen – Fachartikel, Kommentare, Web- und PodCasts, Vorträge, Event-Termine u.v.m  zur Verfügung und soll bei den täglichen Aufgaben helfen und unterstützen.

Der Gedanke des Portals ist "Service von Architekten für Architekten". Schauen wir mal wie sich dieses Microsoft Portal entwickelt. 


Tuesday, February 28, 2006 4:29:30 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET | .NET 2.0 | Allgemein | ASP.NET
# Monday, February 27, 2006

Einstellungen einer Windows Anwendung speichern unter .NET 2.0

Die ersten Erfahrungen mit dem .NET Framework 2.0 waren sehr erfreulich. Als eines der ersten Features habe ich mir die "Anwendungseinstellungen" vorgenommen und war total begeistert. Endlich wird einem diese lästige Aufgabe komplett abgenommen auch das Binden von Einstellunge auf Eigenschaften eines Controls finde ich super! Nur noch ein Load() und Save() in den Code einbauen und fertig. So dachte ich zumindest aber der Frust kam relativ schnell:

Das Speichern von benutzerabhängigen Einstellungen wird unter c:\Dokumente und Einstellungen\benutzername\.... vorgenommen. So weit kein Problem nur das die Versionsnummer mit im Pfad stehen muss finde ich richtig übel. So bald sich die Versionnummer ändert ist es mit den alten Einstellungen essig ... es gibt zwar eine Upgrade() Methode aber bei der Verwendung von SettingKey funktioniert das nicht mehr :(

Also habe ich versucht den Pfad anzupassen und habe gegoogelt .. siehe da: Es geht nicht .... super gemacht, toll durchdacht aber dann trotzdem leider auf den letzten Metern versaut. Immerhin hat man die Möglichkeit einen eigenenen Provider zu schreiben, um die Einstellungen abzuspeichern. Das wiederum ist klasse gelöst und mehr als sinnvoll!

Nun hier ist eine Provider, der die Einstellungen im XML-Format unter dem Anwendungsverzeichnis speichert:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Windows.Forms;
using System.Xml;
using System.Collections.Specialized;
using Microsoft.Win32;


namespace GaliNeo.Framework.GaliNeoSettings
{
class GaliNeoSettingsProvider : SettingsProvider
{
XmlDocument doc = null;
XmlNode root = null;
XmlNode userSettings = null;
XmlNode appSettings = null;

public GaliNeoSettingsProvider()
{
doc = new XmlDocument();
LoadSettings();
}

public override string ApplicationName
{
get { return Application.ProductName; }
set { }
}

public override void Initialize(string name, NameValueCollection col)
{
base.Initialize(this.ApplicationName, col);
}


public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{

foreach (SettingsPropertyValue propval in propvals)
{

SettingsProperty prop = propval.Property;

setValue(prop, propval, context);

}

this.WriteSettings();
}

public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection props)
{

// Create new collection of values
SettingsPropertyValueCollection values = new SettingsPropertyValueCollection();
string sectionName = this.GetSectionName(context);
string settingKey = (string)context["SettingsKey"];


// Iterate through the settings to be retrieved
foreach (SettingsProperty setting in props)
{
SettingsPropertyValue value = new SettingsPropertyValue(setting);
value.IsDirty = false;
value.SerializedValue = getValue(setting, context );

values.Add(value);
}
return values;

}


private XmlNode SerializeToXmlElement(SettingsProperty setting, SettingsPropertyValue value)
{

XmlElement element = doc.CreateElement("value");
string text1 = value.SerializedValue as string;
if ((text1 == null) && (setting.SerializeAs == SettingsSerializeAs.Binary))
{
byte[] buffer1 = value.SerializedValue as byte[];
if (buffer1 != null)
{
text1 = Convert.ToBase64String(buffer1);
}
}
if (text1 == null)
{
text1 = string.Empty;
}
if (setting.SerializeAs == SettingsSerializeAs.String)
{
//text1 = this.Escaper.Escape(text1);
}

element.InnerXml = text1;
XmlNode node1 = null;
foreach (XmlNode node2 in element.ChildNodes)
{
if (node2.NodeType == XmlNodeType.XmlDeclaration)
{
node1 = node2;
break;
}
}
if (node1 != null)
{
element.RemoveChild(node1);
}
return element;
}

private string GetSectionName(SettingsContext context)
{
string groupName = (string)context["GroupName"];
string settingKey = (string)context["SettingsKey"];
string section = groupName;
if (!string.IsNullOrEmpty(settingKey))
{
object[] arrName = new object[] { section, settingKey };
section = string.Format("{0}.{1}", arrName);
}
return XmlConvert.EncodeLocalName(section);
}


#region DAN


private string getXPathQueryProperty(SettingsProperty setting, SettingsContext context)
{
string xPathQuery = getXPathQuerySection(setting, context);

if (setting.Name != "")
{
xPathQuery += "/" + setting.Name;
} //if (propName != "")

return xPathQuery;
}

private string getXPathQuerySection(SettingsProperty setting, SettingsContext context)
{
string xPathQueryGroup = doc.DocumentElement.LocalName ;

if (this.IsUserScoped(setting))
{
xPathQueryGroup += "/userSettings";
}
else
{
xPathQueryGroup += "/appSettings";
}
xPathQueryGroup += "/" + GetSectionName(context);


return xPathQueryGroup;

}



private void CreatePropNode(SettingsProperty setting, SettingsPropertyValue value, SettingsContext context)
{
string xPathQuery = getXPathQuerySection(setting, context);

XmlNode groupNode = doc.SelectSingleNode(xPathQuery);

if (groupNode == null)
{
groupNode = doc.CreateElement(GetSectionName(context));

if (this.IsUserScoped(setting))
{
userSettings.AppendChild(groupNode);
}
else
{
appSettings.AppendChild(groupNode);
}

} //if (node == null)


XmlNode nodeProp = doc.CreateElement(setting.Name);

nodeProp.AppendChild (this.SerializeToXmlElement(setting,value) );

groupNode.AppendChild(nodeProp);

}

private void setValue(SettingsProperty setting, SettingsPropertyValue value, SettingsContext context) //string propName, string groupName, object value, object defaultvalue)
{

string xPathQuery = getXPathQueryProperty(setting,context);

XmlNode node = doc.SelectSingleNode(xPathQuery);
if (node != null)
{
XmlNode valueNode = SerializeToXmlElement(setting, value);
node.RemoveAll();
node.AppendChild(valueNode);
}
else
{

CreatePropNode(setting, value, context);

} //if (node != null)

}

private object getValue(SettingsProperty setting, SettingsContext context)
{
string xPathQuery = getXPathQueryProperty(setting, context);

XmlNode node = doc.SelectSingleNode(xPathQuery + "/value");

if (node != null)
{
return node.InnerXml;
}
else if (setting.DefaultValue != null)
{
return setting.DefaultValue;
}
else
{
return null;
}

}

// Helper method: walks the "attribute bag" for a given property
// to determine if it is user-scoped or not.
// Note that this provider does not enforce other rules, such as
// - unknown attributes
// - improper attribute combinations (e.g. both user and app - this implementation
// would say true for user-scoped regardless of existence of app-scoped)
private bool IsUserScoped(SettingsProperty prop)
{
foreach (DictionaryEntry d in prop.Attributes)
{
Attribute a = (Attribute)d.Value;
if (a.GetType() == typeof(UserScopedSettingAttribute))
return true;
}
return false;
}

#endregion

private void LoadSettings()
{
string configFile = getPath() + "user.config";

if (System.IO.File.Exists(configFile) )
{
doc.Load(configFile);
root = doc.DocumentElement;
userSettings = doc.DocumentElement.SelectSingleNode("./userSettings");
appSettings = doc.DocumentElement.SelectSingleNode("./appSettings"); ;

}
else
{

try
{
root = doc.CreateElement("configuration");

userSettings = doc.CreateElement("userSettings");
root.AppendChild(userSettings);
appSettings = doc.CreateElement("appSettings");
root.AppendChild(appSettings);

doc.AppendChild(root);
}
catch
{

}
}

}

private string getPath()
{
return Application.StartupPath + @"\App_Data\" ;
}


private void WriteSettings()
{
if (!( System.IO.Directory.Exists(getPath())))
{
System.IO.Directory.CreateDirectory(getPath());
}
string configFile = getPath() + "user.config";


doc.Save(configFile);


}

}
}

Nun das ist noch nicht 100% best practice Entwicklung (musste schnell gehen) aber es funktioniert ....:)

 

 


Monday, February 27, 2006 12:09:43 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET 2.0 | Winform