.NET-Software-Entwicklung - DotNetNuke - Business-Develoment
# 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
# Wednesday, January 18, 2006

Neuer Version des FCKEditor provider

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.

 


Wednesday, January 18, 2006 8:38:55 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET | DotNetNuke | Opensource
# Thursday, January 12, 2006

HTML Zeichen aus einem String entfernen

Ich wollte gerade eine Modul etwas benutzerfreundlicher gestalten und bei einem Link im ToolTip einen Kommantar / Vorschau anzeigen. Der Text der im ToolTip angezeigt werden soll liegt im HTML Format vor. Das macht die Ansicht schwer, da im ToolTip keine HTML-Zeichen verarbeitet werden.

Habe mir dann einfach ein paar Regular Expressions geschrieben, die mir helfen sollen den Text vom HTML zu befreien.

string sHTMLToolTip = ..... //HTML Message

sHTMLToolTip = Regex.Replace( sHTMLToolTip, "<(br|p)>", System.Environment.NewLine , RegexOptions.IgnoreCase | RegexOptions.Multiline);

sHTMLToolTip = Regex.Replace( sHTMLToolTip, "<(.|\n)+?>", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);

Ich glaube auf die RegEx muss ich nicht näher eingehen ;-)


Thursday, January 12, 2006 1:04:02 AM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET
# Tuesday, January 10, 2006

Checkliste zur Webseitengestaltung

Nachdem ich mein Weblog die letzten 14 Tage etwas stiefmütterlich behandelt habe möchte ich diesen Zustand nun endlich wieder beenden und damit zumindest einen guten Vorsatz durchsetzen ;-)

Ich habe vor ein paar Tagen eine sehr interessante Seite für die Gestaltung von Website gefunden. Diese Seite ist nicht nur für Webdesigner interessant sondern richtet sich an alle Menschen, die gerne eine Website betreiben möchten.
Es werden nämlich nicht nur Themen wie HTML, CSS, Frames keine Frames, Hyperlings überprüfen, usw. behandelt sonder auch z.B. rechtliche Bereiche Copyrights (Umgang mit Urheberrechten) oder Disclaimer bis hin zu solchen Themen wie Ergonomie.

Die Seite ist eine große Linksammlung und zu erreichen unter: http://dciwam.de/checkliste/


Tuesday, January 10, 2006 12:17:34 AM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
Allgemein
# Saturday, December 24, 2005

Wird DotNetNuke kommerziell?

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


Saturday, December 24, 2005 10:39:23 AM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
DotNetNuke | Opensource
# Wednesday, December 21, 2005

Die Website von DoNetNuke wurde auf die Version 3.2.2 umgestellt

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


Wednesday, December 21, 2005 4:24:18 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
DotNetNuke
# Saturday, December 17, 2005

Cooler ASP.NET Kalender im Outlookstyle

Habe gerade bei The Code Project ein ziemlich cooles ASP.NET Control gefunden. Damit kann man einen Kalender genau wie in Outlook darstellen:

http://www.codeproject.com/useritems/daypilot.asp

Habe das Control selber noch nicht ausprobiert aber die Demo sieht schon mal sehr vielversprechend aus! Das Beste zu Schluß: Es ist ein OpenSource Projekt ;-)

 


Saturday, December 17, 2005 5:43:12 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET | Opensource
# Sunday, December 11, 2005

Templatesystem Part 3

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!


Sunday, December 11, 2005 11:49:41 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET | DotNetNuke
# Wednesday, December 07, 2005

Outlook als RSS Reader verwenden

Soeben habe ich ein verdammt cooles Tool gefunden, womit ich Outlook als RSS Reader verwenden kann. Es ist unter http://www.attensa.com  erhältlich. Sehr gut ist auch, dass man beim Surfen RSS Abo's direkt über das Kontextmenu des IE oder FireFox mit in die Liste aufnehmen kann. 


Wednesday, December 07, 2005 12:07:05 AM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
Allgemein
# Tuesday, December 06, 2005

Geburtstag des deutschen DNNPortal

Vor genau einem Jahr hat Hans-Peter Schelian das Portal www.dnnportal.de online gebracht. Mittlerweile hat es zu der Anlaufestelle im deutschsprachigen Raum entwickelt.

Ein ganz dickes und Lob und Dankeschön an Hans-Peter der sehr viel Arbeit und Zeit in dieses Portal investiert. Zum Glückt gibt es mittlerweile aber einige weiter Leute, die im Forum den HP entlasten ;-)

Ich bin sehr gespannt wie die Zukunft von DNN aber natürlich auch die Zukunft vom dnnportal aussieht!


Tuesday, December 06, 2005 10:54:35 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback

# Tuesday, November 29, 2005

Templatesystem Part 2

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.

 

 


Tuesday, November 29, 2005 4:12:10 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET | DotNetNuke
# Wednesday, November 23, 2005

Mit C# rechnen / dividieren von Integer-Werten als Ergebnis kommt eine Double-Zahlen raus

Ich habe gerade eine Komponente von mir nach C# portiert - voher VB.Net. Übrigens geht das sehr gut mit SharpDevelopment.

Nun ja auf jeden Fall habe ich in VB.Net eine Berechnung gemacht

iPageCount = Convert.ToInt32(System.Math.Ceiling(RecordCount / PagingCount))

Nach C# konveritert sieht das nun so aus:

iPageCount = Convert.ToInt32(System.Math.Ceiling( RecordCount / PagingCount ));

Jetzt muss ich dazusagen, dass die beiden Werte RecordCount und PagingCount von Typ Integer sind. Wenn man nun in C# die Rechnung 6/4 = 1,5 durchführt kommt aber immer 1 raus. Das liegt daran das C# eine typsichere Sprache ist. Wenn man nun ein korrektes Ergebnis haben möchte muss man die beiden Werte zuerst in einen Double Typ umwandeln.

iPageCount = Convert.ToInt32(System.Math.Ceiling( Convert.ToDouble(RecordCount) / Convert.ToDouble(PagingCount) ));

Jetzt kommt bei der Rechnung (RecordCount / PagingCount) auch der gewünschte Wert von 1,5 raus. Durch die Funktion System.Math.Ceiling() wird hier auf den Wert 2 aufgerundet.
(Ergänzung -> siehe Kommentar)


Wednesday, November 23, 2005 10:33:49 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET
# Friday, November 18, 2005

foreach Statement und Hashtable

Durch eine Hashtable kann man nicht direkt via foreach Statement itterieren.

 foreach(ProfileProperty currEntry in objInfo.ExtentedProperty)
 {
    string sUsername = currEntry.Username;
 }

Wenn man so einen Konstrukt abbilden muss dann geht das durch folgenden Umweg:

 ProfileProperty baseProp = null ;
 foreach(System.Collections.DictionaryEntry currEntry in objInfo.ExtentedProperty)
 {
    baseProp = (ProfileProperty)currEntry.Value ;
 }

 

Wichtig ist hierbei das man bei der Typumwandlung currEntry.Value zur Konvertierung nimmt, denn sonst gibt es eine Exception.

 


Friday, November 18, 2005 1:09:22 AM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
.NET
# Sunday, November 13, 2005

Templatebasierte erweiterte Benutzeranmeldung Part 1

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.

 


Sunday, November 13, 2005 11:55:21 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
DotNetNuke
# Thursday, November 10, 2005

Qualified Google Advertising Professional

Wir sind von Google als "Google Advertising Professionals" qualifiziert. Klicken Sie hier für weitere Informationen über Google Advertising Professionals ...

Falls es jemanden Interessiert: Seit einiger Zeit bin ich "Qualified Google Advertising Professional" :)

Und zusammen mit dem ebenfalls "Qualified Google Advertising Professional" Michael Gandke ist das eine weitere Dienstleistung die wir anbieten!

Wer also Bedarf in diesem Bereich hat, einfach einmal melden - hier gibt es weiter Infos dazu... 


Thursday, November 10, 2005 10:20:44 PM (W. Europe Standard Time, UTC+01:00)  #    - Trackback
Allgemein