.NET-Software-Entwicklung - DotNetNuke - Business-Develoment
# 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
# Monday, February 20, 2006

Exportieren / Umwandeln von DataTable in CSV

Bevor ich aber mit .NET 2.0 so richtig loslege hier noch ein kleiner Codebeitrag. Man hat ja immer wieder die Anforderung Daten in CSV zu exportieren (im Zeitalter von XML für mich unverständlich aber gut ;-) ). Dafür veröffentliche ich jetzt das fünftausenste Code-Beispiel.

Zunächst habe ich eine allgemeine Basisklasse geschrieben, die auch für weiter Exportformate genutzt werden kann:

using System;
using System.Data;
using System.Web;
using System.Text;
using System.IO;



namespace GaliNeo.Framework
{
    /// <summary>
    /// Zusammenfassung für BaseConverter.
    /// </summary>
    public abstract class BaseConverter
    {
        public BaseConverter()
        {
        }

        /// <summary>
        /// Export DataTable to http stream
        /// </summary>
        /// <param name="oDataTable"></param>
        /// <param name="response"></param>
        /// <param name="sFileName"></param>
        public void ExportToResponseStream(DataTable oDataTable, System.Web.HttpResponse response, string sFileName)
        {
            response.Clear() ;
            response.ClearHeaders();
            response.ClearContent();
            response.Buffer = true;
            
            //Very importent because "ü", "ä", usw....

            response.ContentEncoding = System.Text.Encoding.Default ;
            
            response.ContentType = GetHTTPContentType() ;
            response.AppendHeader("content-disposition", "attachment; filename=" + HttpUtility.UrlEncode(sFileName, System.Text.Encoding.UTF8)) ;

            response.Write( ConvertDataTable(oDataTable).ToString() ) ;
            
            //close http response
            response.End();


        }

        /// <summary>
        /// Export datatable to file
        /// </summary>
        /// <param name="oDataTable"></param>
        /// <param name="sFileName"></param>
        /// <returns></returns>
        public bool ExportToFile(DataTable oDataTable, string sFileName )
        {
            try
            {
                string fullpath = System.IO.Path.GetFullPath( sFileName ) ;
                if (System.IO.Directory.Exists ( fullpath ))
                {
                    System.IO.Directory.CreateDirectory( fullpath ) ;
                }

                StreamWriter SW;
            
                SW=File.CreateText(sFileName);
                SW.WriteLine(ConvertDataTable(oDataTable).ToString());
            
                SW.Close();
                return true ;
            }
            catch
            {
                return false ;
            }

        }

        protected abstract StringBuilder ConvertDataTable(DataTable oDataTable) ;
        protected abstract string GetHTTPContentType() ;

    }
}

 

Die Klasse ermöglicht es eine Stream entweder auf Festplatte zu schreiben oder aber in den HTTP Responsestream.

Die passende CSV-Klasse ist relativ simple und kein wirkliches Geheimnis:

using System;
using System.Data;
using System.IO;
using System.Text;

namespace GaliNeo.Framework
{
    /// <summary>
    /// Summary description for CSVConvertor.
    /// </summary>
    public class CSVConverter : BaseConverter
    {

        
        protected override string GetHTTPContentType()
        {
            return "text/csv";
        }

        /// <summary>
        /// To generate CSV file.
        /// </summary>
        /// <param name="oDataTable"></param>
        /// <param name="directoryPath"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        protected override StringBuilder ConvertDataTable(DataTable oDataTable)
        {

            
            StringBuilder oStringBuilder = new StringBuilder();

            
            
             // Start, Creating column header

            foreach(DataColumn oDataColumn in oDataTable.Columns)    
            {
                oStringBuilder.Append(oDataColumn.ColumnName + ",");
                oStringBuilder.Append( System.Environment.NewLine ) ;
            }

             //End, Creating column header
             //Start, Creating rows

            foreach(DataRow oDataRow in oDataTable.Rows)    
            {
                
                
                foreach(DataColumn oDataColumn in oDataTable.Columns)    
                {
                    oStringBuilder.Append(oDataRow[oDataColumn.ColumnName] + ",");
                }

                oStringBuilder.Append( System.Environment.NewLine ) ;
            }
            

             //End, Creating rows

            return oStringBuilder;

        }
    }
}

 

Fertig!

 


Monday, February 20, 2006 9:55:09 AM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET | ASP.NET

Neue Themen .NET 2.0, Winform und Google-API

Ab Heute wird die Thematik dieses Blogs ein wenig erweitert. Nun ist es endlich so weit und di Entwicklung mit .NET 2.0 geht bei mir endlich los. In der nächsten Zeit wird der Schwerpunkt mehr auf .NET Winforms und der Google-API liegen.

Aber keine Angst ich werde DotNetNuke nicht wirklich vernachlässigen.


Monday, February 20, 2006 9:44:07 AM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
Allgemein | Winform | .NET 2.0 | google-adwords-api
# Wednesday, February 01, 2006

Die erste sinnvolle Spammail

Auch wenn ich es nie gedachte hätte, habe ich heute eine Spammail bekommen die ich doch recht interesannt oder viel mehr sinvoll fand.

Inhalt war eigentlich die Seite http://www.rekruter.de/ eine Seite mit Stellenangebote der Arbeitsargentur. Ob der Staat jetzt auch schon Spammails gegen die Arbeitslosigkeit einsetzt ;-)


Wednesday, February 01, 2006 12:17:20 AM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
Allgemein
# Tuesday, January 31, 2006

Das Core Team von DotNetNuke bringt ein Shopmodul

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. 


Tuesday, January 31, 2006 5:01:51 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET | DotNetNuke | Opensource
# Monday, January 30, 2006

Microsoft stellt IIS Diagnostics Toolkit zur Verfügung

Microsoft stellt im Downloadbereich das IIS Diagnostic Toolkit zur Verfügung. Das ist eine Sammlung von Werkzeugen, die bei der Fehlersuche rund um den IIS (Internet Information Sevices) helfen sollen. Das Toolkit enthält folgende sieben Werkzeuge: Authentication and Access Control Diagnostics 1.0, SSL Diagnostics 1.1, SMTP Diagnostics 1.0, Log Parser 2.2, Trace Diagnostics 1.0, WFetch 1.4 und Debug Diagnostics 1.0.

Hier geht es zum Download


Monday, January 30, 2006 11:14:28 AM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
Software | Server
# Saturday, January 28, 2006

Server Hosting / DotNetNuke Hosting

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

 


Saturday, January 28, 2006 3:59:15 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET | Allgemein | DotNetNuke