.
Anmeldung | Registrieren | Hilfe

.NET-Blogs Archiv August 2009

Alle Windows Live Dienste, Programme und Services im Ueberblick

30.08.2009 12:00:03 | Kay Giza

Kennen Sie wirklich alle Windows Live-Dienste (es sind nämlich über 20!), die Microsoft kostenfrei anbietet? Ich war vor drei Tagen hier in München im Biergarten und hatte einen tollen Abend mit Freunden und Bekannten. Dabei erwähnte ein Bekannter von mir, dass er bei seinem jetzigen Freemail-Anbieter nur E-Mails mit max. 500 KB Größe empfangen kann und welchen Dienst ich ihm stattdessen empfehlen könnte? Ich empfahl Windows Live Hotmail (mit unbegrenzt Speicherplatz) sowie Windows Live SkyDrive (25 GB kostenfreie externe Festplatte im Internet). Dabei erwähnte mein Bekannter, dass er dies nicht kennen würde und wo man sich informieren kann? Denn ruft man beispielsweise http://skydrive.live.com/ auf um sich zu informieren, muss man sich erst mit einer Windows Live-ID anmelden. Heute dachte ich mir, ok - wo gibt es denn eine gute Übersicht über alle Windows Live-Dienste mit allen kostenfrei verfügbaren Programmen, Diensten und Services? Gefunden habe ich http://www.windowslive.de, dort findet man eine wirklich gute Übersicht über alle (!) verfügbaren Dienste. Ich habe diese Liste ein wenig vervollständigt in den Beschreibungen und habe noch einige Dienste für beispielsweise Softwareentwickler hinzugefügt... [... die vollständige Liste inkl. Beschreibungen und Download-Links finden Sie in diesem Blogeintrag auf Giza-Blog.de]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
Visit:  MSDN Online | Follow MSDN Online on Twitter | Follow Kay Giza on Twitter
Daily News on MSDN:  MSDN Aktuell
© Copyright 2006-2010 Kay Giza. All rights reserved. Legal

Die kostenlosen Windows Live Dienste unter einer Adresse

29.08.2009 11:18:14 | Oliver Scheer

Unter Windows Live Essentials bzw. Windows Live Services verbirgt sich eine nette Anzahl an von Anwendungen und Diensten, die sowohl auf dem Desktop als auch im Web arbeiten können. So gehört z.B. mein Lieblingsfototool Windows Live Fotogallerie ebenfalls dazu.

Mehr Informationen gibt es unter: www.windowslive.de

image

Für die Silverlight Freunde unter uns … die Seite ist vollständig in Silverlight gebaut worden.

Eine Anwendung soll nur einmal geöffnet werden können

28.08.2009 16:41:28 | Klaus Bock

…war eine Frage auf codekicker.de. Aus der Frage entwickelte sich eine interessante Diskussion rund um die verschiedenen Möglichkeiten dies zu Bewerkstelligen.
Einer der ersten Vorschläge war die Verwendung eines Mutex, gefolgt von der Verwendung einer Datei deren Anwesenheit die Ausführung der Anwendung signalisiert.

Mein persönlicher Favorit ist nach wie vor die Verwendung der systemeigenen Prozessliste, in der jeder ausgeführte Prozess vom System erfasst und aufgeführt wird. GENiALi brachte daraufhin den Einwand:

Nach dem Prozess suchen? Wenn der User mal ein Progi umtauft, von app.exe auf Application.exe? Dann wird nichts mehr daraus.

Damit hat er prinzipiell Recht, wenn man den Namen der Anwendung “hart verdrahtet”. Ich habe nie erwähnt, den Namen der Anwendung irgendwo zu hinterlegen.

Genau dafür bietet die Process-Klasse die statische Methode GetCurrentProcess an. mit dieser Methode wird der aktuelle Prozess der aufrufenden Methode in eine Instanz der Process-Klasse zurückgegeben. In dieser Process-Instanz ist jetzt alles nötige enthalten. Die ID des Prozess genauso wie der Name. Über das Hauptmodul des Prozess, zu erhalten über die Eigenschaft MainModule der Process-Instanz, kann auch der komplette Pfad zu Vergleichen herangezogen werden. Verpackt in ein paar Zeilen Code, lässt sich damit eine sehr effektive Methode erstellen, die sehr zuverlässig die Einmaligkeit der Ausführung einer Anwendung gewährleistet.

/// <summary>
/// Prüft ob die Anwendung bereits ausgeführt wird.
/// </summary>
/// <returns>
/// <c>true</c> wenn die Anwendung bereits läuft,
/// anderenfalls <c>false</c>.
/// </returns>
/// <remarks>n/a</remarks>
private static bool AlreadyRunning()
{
    Process current = Process.GetCurrentProcess();
    Process[] processes = Process.GetProcessesByName(
							current.ProcessName);

    foreach (Process process in processes)
    {
        if (process.Id != current.Id)
        {
            if (Assembly.GetExecutingAssembly().Location
				.Replace("/", "\\") == current.MainModule.FileName)
            {

                return true;
            }
        }
    }

    return false;
}

Somit lässt sich in einem einzigen Statement prüfen ob die Anwendung bereits läuft oder nicht.

/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    if (Program.AlreadyRunning())
    {
        Application.Exit();
        return;
    }

    Application.Run(new Form1());
}

Dabei sollte es keine Rolle spielen ob die Anwendung eine Konsolenanwendung, eine Windows Forms Anwendung oder eine WPF Anwendung ist.

Technorati-Tags: | |

TaskmgrPro, Enhances Windows Task Manager

28.08.2009 16:17:00 | Ozgur Aytekin

TaskmgrPro is a plug-in for Windows Task Manager. It enhances the standard Processes tab and creates three additional tabs. You can batch kill or resurrect processes in the standard Processes tab, batch stop or start services in the additional services tab, view all established TCP connections and all open ports in the additional TCP/IP tab and manage shared folders easy in the additional Shares Tab.

http://www.goldgingko.com/taskmgrpro/index.htm

Auf geht es zur nrw conf 09 Konferenz

27.08.2009 14:30:53 | Lars Keller

Morgen findet die jährliche nrw conf 09 in Wuppertal statt. An Board sind wieder jede Menge bekannte Gesichter und ich freue mich auf die interessanten Vorträge! Besonders gespannt bin ich auf das  Security Shootout von und mit Frank und Marc. Auf der ice:2009 habe ich schon so ein paar Andeutungen davon mitbekommen…

Ich selber werde einen Vortrag zur MS Office (VSTO/OBA) Entwicklung halten.

Die Agenda ist prall gefüllt und ich freue mich auf das Event. Man sieht sich da!

 



This weblog is sponsored by netcreate OHG.

Auf geht es zur nrw conf 09 Konferenz

27.08.2009 13:30:53 | Lars Keller

Morgen findet die jährliche nrw conf 09 in Wuppertal statt. An Board sind wieder jede Menge bekannte Gesichter und ich freue mich auf die interessanten Vorträge! Besonders gespannt bin ich auf das  Security Shootout von und mit Frank und Marc. Auf der ice:2009 habe ich schon so ein paar Andeutungen davon mitbekommen…

Ich selber werde einen Vortrag zur MS Office (VSTO/OBA) Entwicklung halten.

Die Agenda ist prall gefüllt und ich freue mich auf das Event. Man sieht sich da!

 

Auf geht es zur nrw conf 09 Konferenz

27.08.2009 04:30:05 | Lars Keller

Morgen findet die jährliche nrw conf 09 in Wuppertal statt. An Board sind wieder jede Menge bekannte Gesichter und ich freue mich auf die interessanten Vorträge! Besonders gespannt bin ich auf das  Security Shootout von und mit Frank und Marc. Auf der ice:2009 habe ich schon so ein paar Andeutungen davon mitbekommen…

Ich selber werde einen Vortrag zur MS Office (VSTO/OBA) Entwicklung halten.

Die Agenda ist prall gefüllt und ich freue mich auf das Event. Man sieht sich da!

 

PropertyChanged Event ohne Stringliteral aufrufen

26.08.2009 18:43:00 | Stefan Lange

Bei der Implementierung von INotifyPropertyChanged muss der Property-Setter das PropertyChanded Event auslösen, wenn sich der Wert der Property ändert. Das sieht beispielsweise so aus:

public class ViewModel : INotifyPropertyChanged
{
  public string Name
  {
    get { return _name; }
    set
    {
      if (_name != value)
      {
        _name = value;
        OnPropertyChanged("Name");
      }
    }
  }
  string _name;

  public event PropertyChangedEventHandler PropertyChanged;

  protected void OnPropertyChanged(string propertyName)
  {
    if (PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  }
}

Den Namen der geänderten Property als Stringliteral an den Event Handler zu übergeben verhindert, dass er etwa beim Refactoring automatisch mit umbenannt wird. Ein möglicher Lösungsansatz, über den auch schon viel geschrieben wurde, besteht in Verwendung einer Lambda Expression:

OnPropertyChanged(x => x.Name);

Anstatt des Strings wird ein Expression Tree übergeben, aus dem dann der Name der Property ermittelt wird. Eine Implementierung dazu findet sich beispielsweise hier: http://www.lieser-online.de/blog/?p=130

Damit der Compiler den Typ von x herleiten kann, muss allerdings für jede ViewModel Klasse eine eigene Version von OnPropertyChanged implementiert werden. Das finde ich aber noch lästiger als den String direkt hinzuschreiben.

Eine Lösung besteht darin, zusätzlich this als ersten Parameter zu übergeben:

OnPropertyChanged(this, x => x.Name);

Der Compiler kann so den Typ von x über die Signatur der Funktionsdefintion erschließen. OnPropertyChanged kann dadurch in eine Basisklasse verschoben werden und ist wie folgt definiert:

protected void OnPropertyChanged<T, TResult>(T dummy, Expression<Func<T, TResult>> propertyExpression)
{
  OnPropertyChanged(((MemberExpression)propertyExpression.Body).Member.Name);
}

Der Parameter this wird vom Compiler dazu verwendet herzuleiten, dass x vom Typ ViewModel sein muss. So kann OnPropertyChanged vollständig generisch sein. Der Wert von this wird aber gar nicht verwendet.

Das Ganze funktioniert zwar, ist aber insofern etwas seltsam, als dass this nur zur Herleitung des Typs von x verwendet wird. Es ist also noch keine optimale Lösung.

Da wir ja nur den Namen der Property wissen wollen, können wir die Lambda Expression etwas einfacher hinschreiben:

OnPropertyChanged(() => Name);

Das passende OnPropertyChanged sieht dann so aus:

protected void OnPropertyChanged<TResult>(Expression<Func<TResult>> propertyExpression)
{
  OnPropertyChanged(((MemberExpression)propertyExpression.Body).Member.Name);
}

Diese Variante verwende ich selbst in Silverlight und WPF Projekten, da wir stets mit einer ViewModel Basisklasse arbeiten.

Hier der gesamte Quellcode:

public abstract class ViewModelBase : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  protected void OnPropertyChanged(string propertyName)
  {
    if (PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  }

  protected void OnPropertyChanged<TResult>(Expression<Func<TResult>> propertyExpression)
  {
    OnPropertyChanged(((MemberExpression)propertyExpression.Body).Member.Name);
  }
}

public class ViewModel : ViewModelBase
{
  public string Name
  {
    get { return _name; }
    set
    {
      if (_name != value)
      {
        _name = value;
        OnPropertyChanged(() => Name);
      }
    }
  }
  string _name;
}

Extension Method

Wer keine gemeinsame Basisklasse für alle seine ViewModel Klassen verwenden möchte, kann auch eine Funktion Raise als Extension Method für den Typ PropertyChangedEventHandler implementieren. Das sieht dann so aus:

public static class PropertyChangedExtensions
{
  public static void Raise<T, TResult>(this PropertyChangedEventHandler handler, T sender, Expression<Func<T, TResult>> propertyExpression)
  {
    if (handler != null)
      handler(sender, new PropertyChangedEventArgs((((MemberExpression)propertyExpression.Body).Member.Name)));
  }
}

Die Extension Method Raise wird direkt am Event Handler aufgerufen:

PropertyChanged.Raise(this, x => x.Name);
PropertyChanged.Raise(this, x => Name);  // same as above

Auch diese Schreibweise ist möglich:

PropertyChanged.Raise(this, () => Name);

Dazu muss in der Definition von Raise nur der erste Parameter des Delegates Func gelöscht werden.

Performance

Die Auswertung des Expression Trees dauert vermutlich mindestens 100 mal länger als der direkte Funktionsaufruf mit einem Stringliteral. Da es sich aber um UI Code handelt spielt das überhaupt keine Rolle. Andere UI Funktionalitäten, wie das Zuweisen von Styles oder Data Templates, dauert um so vieles länger, dass die Verwendung von Expression Trees insgesamt kaum messbar sein wird.

Beim Recherchieren zu diesem Thema habe ich jedoch einen Blogeintrag gefunden, bei dem der Autor in einer ähnlichen Lösung den übergebenen Expression Tree zunächst zerlegt, dann compiliert und schließlich ausführt, um an das sender Objekt zu gelangen. Das ist nicht nur unnötig, sondern vermutlich dann doch auch messbar inperformant.

Aspektorientierte Lösung

Eine aspektorientierte Lösung beispielsweise mit PostSharp halte ich bei diesem Problem für übertrieben. Der zusätzliche Code bei der hier gezeigten Lösung ist minimal und außerdem gut lesbar. Nur um eine Zeile Code im jedem Property-Setter zu eliminieren und im Gegenzug durch ein zusätzliches Attribut zu ersetzten erscheint mir nicht sinnvoll. Es kann aber sein, dass ich meine Meinung dazu zukünftig ändere.

Fazit

Expression Trees haben auch außerhalb von LINQ viele nützliche Anwendungsgebiete. Allerdings sind sie auch etwas komplizierter, was leicht zu einer suboptimalen Verwendung führen kann. Erst beim Schreiben dieses Blogeintrags ist mir beispielsweise eine Verbesserung aufgefallen, die ich vorher übersehen hatte. Ich hatte ursprünglich OnPropertyChanged nicht als generische Funktion geschrieben, sondern stattdessen Func<object> verwendet. Das geht zwar auch, man muss allerdings aufpassen: Wenn der Typ der Property ein Value Type ist, wird im Expression Tree so etwas ähnliches wie „Boxing“ verwendet. Man muss daher eine zusätzliche Variante von OnPropertyChanged mit Func<ValueType> implementieren, die dies durch ein entsprechendes „Unboxing“ berücksichtigt.

Touch me! Windows 7-Touchscreen-Fähigkeiten nutzen

26.08.2009 13:47:21 | Peter Kirchner

Windows 7 unterstützt moderne Touchscreen-Bildschirme stärker als frühere Tablet PC-Editionen von Windows: Nicht mehr nur das einfache Berühren des Bildschirms ist reaktionswürdig; auch parallele Berührungsabläufe, wie etwas das Skalieren eines Objekts auf dem Bildschirm mit zwei Händen, bewältigt Windows 7 bei entsprechender Hardware. Zweifelsfrei wird Touch zukünftig eine erhebliche Rolle in Benutzerschnittstellen spielen. Entwickler, die heute wegen fehlender eigener Hardware den UI-Trend nicht erkennen, werden absehbar das Nachsehen haben. Umso wichtiger ist es, zumindest Vorsorge zu treffen: Gestalten Sie Ihre Benutzerschnittstellen insgesamt Touch-tauglich. Im ISV Developer Community Blog erfahren Sie, wofür Sie schon heute sorgen können.

Neugierig geworden? Dann hier weiterlesen!

Governance Resource Center for SharePoint Server 2007

26.08.2009 08:17:00 | Ozgur Aytekin

This page contains tools and resources to help business decision makers and IT professionals govern their SharePoint Products and Technologies environment. Governance is the set of roles, responsibilities, and processes that you put in place in an enterprise to guide the development and use of a solution based on SharePoint. By using the governance techniques and best practices available from this page, an enterprise can align its policies for using SharePoint with its culture and goals while still enabling teams and individuals to effectively collaborate and share information.

http://technet.microsoft.com/en-us/office/sharepointserver/bb507202.aspx

VSTS beim .NET-Stammtisch Konstanz-Kreuzlingen

26.08.2009 02:55:05 | Jürgen Gutsch

Etwas verspätet liefere ich hier noch einen kurzer Rückblick auf das sechste Treffen des .NET-Stammtisch Konstanz-Kreuzlingen.

Wie immer bin ich um 18:30Uhr im Raum F023 in der FH-Konstanz angekommen um die Session vorzubereiten. Strom und Beamer zu prüfen und die Videokamera aufzustellen. Diesmal war ich nicht der erste, denn Thomas stand schon drin und richtete den Laptop für seine Präsentation.

Thomas zeigte viele Neuerungen in den VSTS 2010 auch anhand einiger live Demos.

Als beeindrucktesten Neuerungen empfand ich die hierarchischen Workitems, sowie die viel Bessere Unterstützung der Tester unter anderem auch mit dem neuen Workitem-Typ “Testcase”, den Testaufzeichnungen und dem Videomitschnitt während des Testens. Der Entwickler kann so fehlgeschlagenen Tests nachvollziehen und muss unter Umständen nicht lange nach dem Fehler suchen. Auch für die Architekten wurden einige Neuerungen hinzugefügt.

Insgesamt werde ich wohl jedem empfehlen VSTS 2010 einzusetzen, bzw. auf die neue Version updaten, sobald sie Verfügbar ist.

Das Video und die Bilder zum Vortrag werde ich in den nächsten Wochen auf der Website des .NET-Stammtisch veröffentlichen.

Anschließend gingen wir alle in das Brauhaus wo wir in gemütlicher Atmosphäre, bei Frischgebrautem, weiter zum Thema Diskutieren konnten.

Danke nochmal an Thomas, dass er extra wegen uns aus Erlangen, zu uns nach Konstanz runter geheizt ist. :-)

DotNetKicks-DE Image

Ermittlung der größten Datei(en) in einer Ordnerstruktur

25.08.2009 21:30:00 | Martin Hey

Wie kann man ausgehend von einem Ordner von allen Dateien - auch die die in Unterordnern sind - die größte bzw. die größten ermitteln?

Das Ziel ist ganz klar - es wird aus der Ordnerstruktur das FileInfo-Objekt benötigt, dessen Eigenschaft Length am größten ist. Um an diese Objekte zu kommen, gibt es zum einen die Möglichkeit, rekursiv durch alle Unterordner gehen und für alle Dateien ein solches Objekt zu erzeugen und sich die relevanten Objekte zu speichern. Eine andere Möglichkeit ist, per Directory.GetFiles an die Dateipfade und darüber diese FileInfo-Objekte zu instanziieren:
// define the root
const string rootPath = @"C:\Program Files\Microsoft SQL Server";

// check if the directory exists
if (!Directory.Exists(rootPath))
throw new DirectoryNotFoundException();

// get all file names in the directory
// warning: may throw System.UnauthorizedAccessException
string[] fileNames = Directory.GetFiles(rootPath, "*.*", SearchOption.AllDirectories);

// get all FileInfo objects from file names
var files = fileNames.Select(fileName => new FileInfo(fileName));

// query the largest file
FileInfo largestFile = (from file in files
orderby file.Length descending
select file).First();

// query the top 10 largest files
FileInfo[] topTenLargestFiles = (from file in files
orderby file.Length descending
select file).Take(10).ToArray();

Vorteil dieser Methode: Der Code ist kurz und übersichtlich. Aber es gibt auch mindestens einen Nachteil: Besteht nach Code Access Policy kein Zugriff auf eine der abgefragten Dateien oder Ordner, so wirft Directory.GetFiles eine System.UnauthorizedAccessException und bricht ohne Ergebnis ab.

Die Selektion der größten Datei(en) selbst ist dann, wie gezeigt, sehr leicht mit LINQ zu realisieren.

Mastering PowerShell E-Book

25.08.2009 10:30:53 | Constantin Klein

Ein kostenloses E-Book mit dem Titel „Mastering PowerShell“ gibt es auf PowerShell.com In englischer Sprache gibt PowerShell MVP Dr. Tobias Weltner auf 567 Seiten einen guten Überblick und behandelt die Themen: The PowerShell Console Interactive PowerShell Variables Arrays and Hashtables The PowerShell Pipeline Using Objects Conditions Loops Functions Scripts Finding and Avoiding Errors Command Discovery and Scriptblocks Text and Regular Expressions XML The File System The Registry Processes, Services, Event Logs WMI: Windows Management [...]

So Long, Farewell...

24.08.2009 16:01:00 | Lori Grosland

If you haven’t heard already, Channels 8, 10 and Coding4Fun will be consolidated into Channel 9.  For more info about the change, check out this blog post:  http://channel9.msdn.com/posts/C9Team/The-Future-of-Channel-9/

So what does that mean?  Well, sometime in the fall, the content from Channels 8, 10 and Coding4Fun will be migrated over to Channel 9.  That content includes my blog.  The old links should still work but they will redirect to the new location on Channel 9.

Since I’m a bit sentimental, I’m sad to see Channel 10 go.  However, the timing works out well for me.  I’m leaving soon on maternity leave and won’t be back in the office for awhile.  When I get back, I will start a new blog on Channel 9 or MSDN or where ever is most appropriate.  In the meantime, be sure to check out the great content on Channel 9…

http://channel9.msdn.com/

And for those in Germany, check out the German landing page for Channel 9…

http://channel9.msdn.com/germany/

Thanks to everyone for reading my blog and watching the videos!  I hope you have found the content interesting.  :-)

So Long, Farewell...

24.08.2009 16:01:00 | Lori Grosland

If you haven’t heard already, Channels 8, 10 and Coding4Fun will be consolidated into Channel 9.  For more info about the change, check out this blog post:  http://channel9.msdn.com/posts/C9Team/The-Future-of-Channel-9/

So what does that mean?  Well, sometime in the fall, the content from Channels 8, 10 and Coding4Fun will be migrated over to Channel 9.  That content includes my blog.  The old links should still work but they will redirect to the new location on Channel 9.

Since I’m a bit sentimental, I’m sad to see Channel 10 go.  However, the timing works out well for me.  I’m leaving soon on maternity leave and won’t be back in the office for awhile.  When I get back, I will start a new blog on Channel 9 or MSDN or where ever is most appropriate.  In the meantime, be sure to check out the great content on Channel 9…

http://channel9.msdn.com/

And for those in Germany, check out the German landing page for Channel 9…

http://channel9.msdn.com/germany/

Thanks to everyone for reading my blog and watching the videos!  I hope you have found the content interesting.  Smiley

So Long, Farewell...

24.08.2009 16:01:00 | Lori Grosland

If you haven’t heard already, Channels 8, 10 and Coding4Fun will be consolidated into Channel 9.  For more info about the change, check out this blog post:  https://channel9.msdn.com/posts/C9Team/The-Future-of-Channel-9/

So what does that mean?  Well, sometime in the fall, the content from Channels 8, 10 and Coding4Fun will be migrated over to Channel 9.  That content includes my blog.  The old links should still work but they will redirect to the new location on Channel 9.

Since I’m a bit sentimental, I’m sad to see Channel 10 go.  However, the timing works out well for me.  I’m leaving soon on maternity leave and won’t be back in the office for awhile.  When I get back, I will start a new blog on Channel 9 or MSDN or where ever is most appropriate.  In the meantime, be sure to check out the great content on Channel 9…

https://channel9.msdn.com/

And for those in Germany, check out the German landing page for Channel 9…

https://channel9.msdn.com/germany/

Thanks to everyone for reading my blog and watching the videos!  I hope you have found the content interesting.  Smiley

PHP Toolkit für die ADO.NET Data Services veröffentlicht

24.08.2009 09:31:34 | Jan Schenk

digg_url = "http://blogs.msdn.com/jansche/archive/2009/08/24/php-toolkit-f-r-die-ado-net-data-services-ver-ffentlicht.aspx";digg_title = "PHP Toolkit für die ADO.NET Data Services veröffentlicht";digg_bgcolor = "#FFFFFF";digg_skin = "normal";digg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;

Unter http://blogs.msdn.com/interoperability/archive/2009/08/21/a-new-bridge-for-php-developers-to-net-through-rest-php-toolkit-for-ado-net-data-services.aspx findet ihr einen Blog-Eintrag (englisch), der sich eingehend mit der Veröffentlichung und der Verwendung des PHP Toolkits für die ADO.NET Data Services beschäftigt.

Wenn ihr jetzt keine Ahnung habt, was ADO.NET ist und ob euch das in irgendeiner Weise hilft, dann ist das auch kein Problem. Die ADO.NET Data Services sind Webdienste, die an einer Webschnittstelle Daten, zum Beispiel von einer SQL-Datenbank, zur Verfügung stellen. Wem das noch nicht reicht, einfach mal in diesen Webcast meines Kollegen Dariusz Parys reinschauen. Da wird ADO.NET ausführlicher erklärt.

Von Windows XP zu Windows 7 – Eine Referenzanwendung

24.08.2009 06:59:16 | Oliver Scheer

In Windows 7 sind so einige neue coole Features hinzugekommen. Wie z.B. die Touch- und Sensor-Unterstützung.

Wir bei Microsoft wollen es für unsere Kunden so leicht wie möglich machen, ihre Anwendungen von Windows XP oder Windows Vista auf Windows 7 zu heben. Dafür haben wir eine Beispielreferenzanwendung erstellt: PhotoView.

Filmstrip

Diese Anwendung enthält sehr viel Referenzmaterial und den Sourcecode einer voll funktionsfähigen Anwendung. Diese demonstriert die diversen Windows 7 Funktionen:

  • Infrastrukturfeatures, wie z.B. Restart & Recovery, IO Optimization, etc.
  • Benutzerinteraktion: Sprunglisten und lokale Suche
  • Windows 7 Highlights: Touch und Sensor
  • u.v.m.

Mit PhotoView kann man diese Features leicht ausprobieren und dabei auch sehen wie man eine Anwendung von Windows XP nach Windows 7 portieren und aufwerten kann.

image

Viel Spaß damit. Bei Fragen einfach einen Kommentar hier rein schreiben.

Downloadlink: http://code.msdn.microsoft.com/XP2Win7

XQuery-Singleton oder warum ein einzelnes Element nicht unbedingt als solches erkannt wird

23.08.2009 16:52:00 | Wolfgang Kluge

Bei der Arbeit mit dem XML-Datentyp ab SQL Server 2005 kann es zu einer Fehlermeldung kommen, die - zumindest auf den ersten Blick - ein wenig unverständlich erscheint.

Msg 2389, Level 16, State 1, Line #
XQuery [value()]: 'value()' erfordert ein Singleton (oder eine leere Sequenz). Ein Operand vom 'xdt:untypedAtomic *'-Typ wurde gefunden.

bzw.

Msg 2389, Level 16, Status 1, Line #
XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'

Dabei ist nicht die Aussage der Fehlermeldung verwirrend, sondern vielmehr die Tatsache, dass alles korrekt zu sein scheint. Dazu folgendes Beispiel:

DECLARE @test xml

SET @test = '
<test>
    <name>Wolfgang Kluge</name>
    <links>
        <link>http://gehirnwindung.de/</link>
        <link>http://klugesoftware.de/</link>
        <link>http://vbwelt.de/</link>
    </links>
</test>'


SELECT @test.value('/test/links/link[2]/text()', 'varchar(200)')

Die Meldung weißt ja bereits darauf hin. Die value()-Funktion erfordert einen einzelnen Wert oder eine leere Sequenz - also eine Abfrage, die keinen oder genau einen Wert zurückgibt. Eben das macht die Abfrage aber eigentlich bereits - sie gibt einen einzelnen Wert zurück. Deswegen scheint die Fehlermeldung nicht wirklich viel Sinn machen.

Nun, möglicherweise ist ja die text()-Funktion der Auslöser. Kurz entfernt und getestet,

SELECT @test.value('/test/links/link[2]', 'varchar(200)')

wird aber immer noch der gleiche Fehler ausgegeben... Erfolgreich ist man erst, wenn man die gesamte Abfrage in Klammern setzt und von dieser Menge wiederum ein einziges Element auswählt. Folgende Abfragen funktionieren korrekt:

SELECT @test.value('(/test/links/link)[2]', 'varchar(200)')
SELECT @test.value('(/test/links/link[2])[1]', 'varchar(200)')

Schöner (weil meiner Meinung nach auch einfacher lesbar) ist hierbei die erste Zeile. Innerhalb der Klammer werden 3 <link>-Nodes selektiert und außerhalb die zweite aus dieser Menge ausgewählt. In der zweite Zeile bleibt bereits innerhalb der Klammer nur noch eine <link>-Node übrig, wovon dann aber trotzdem noch die erste ausgewählt werden muss...

Das Gleiche kann man auch mit Text-Nodes betreiben, solange kein XML Schema angegeben wird, in dem die <link>-Node als reines Textelement definiert ist (ansonsten kommt es zu einem anderen Fehler, weil es schlicht unnötig wäre).

SELECT @test.value('(/test/links/link/text())[2]', 'varchar(200)')
SELECT @test.value('(/test/links/link[2]/text())[1]', 'varchar(200)')

Die runden Klammern definieren hier noch Mengen von Text-Nodes, von denen (wie oben) eine einzige ausgewählt werden muss.

Wozu aber die Klammern in XPath

Es gibt natürlich auch einen Grund dafür. Angenommen, es existieren in diesem Beispiel mehrere <links>-Nodes, so kann es auch mehrere zweite <link>-Elemente im Dokument geben - und somit ist nicht sichergestellt, dass die Abfrage "/test/links/link[2]" einen einzelnen Wert zurückgibt. Leider ist das sogar auch dann noch so, wenn man per XML SCHEMA COLLECTION definiert, dass es nur eine einzige <links>-Node geben darf.

Auch schade ist, dass die "Erkennung", ob nun eine Node eindeutig ausgewählt wurde, nicht alle Möglichkeiten von XPath abdeckt. Das Predikat innerhalb des letzten Knotentests muss ein Zahlwert sein (und nicht ein Vergleich, der true zurückgibt). Daher funktioniert zwar [last()], das ebenso eindeutige [position()=2] wird dagegen aber nicht als eindeutig erkannt.

Da damit jedoch sichergestellt werden kann, dass nur ein Element ausgewählt ist, funktioniert es auch, in jeder Elementhierarchie ein (mit Zahl-Predikaten) genau spezifiziertes Element auszuwählen. Das gilt allerdings auch für die text()-Funktion, weswegen man auch dort noch einen Knotentest braucht. Die Zeilen

SELECT @test.value('/test[1]/links[1]/link[2]', 'varchar(200)')
SELECT @test.value('/test[1]/links[1]/link[2]/text()[1]', 'varchar(200)')

sind somit auch gültig (ich finde es nur nicht besonders schön). Bei meinen Tests (mit erheblich mehr <link>-Nodes) war die Performancereihenfolge zudem mehr als eindeutig:

Nr. Abfrage Aufwand Faktor
1 (/test/links/link/text())[2] 7,49% 1,00
2 (/test/links/link)[2] 8,82% 1,18
3 /test[1]/links[1]/link[2] 14,02% 1,87
4 /test[1]/links[1]/link[2]/text()[1] 14,74% 1,97
5 (/test/links/link[2])[1] 17,96% 2,40
6 (/test/links/link[2]/text())[1] 36,98% 4,94

Anhand der dazugehörigen Grafik lassen sich die Unterschiede noch leichter erkennenPerformanceunterschiede zwischen den einzelnen XPath-Abfragen

Dass die letzten beiden Möglichkeiten nicht so schnell sind wie die ersten beiden, kann man noch mit den doppelten Knotentests erklären. Für mich ist (und bleibt vorerst) verwunderllich, warum die letzte Abfrage so unglaublich schlecht abschneidet. Grob scheint es aber so zu sein, dass die Abfrage länger zur Ausführung braucht, je mehr Knotentests in der Abfrage enthalten sind.

Fazit

Um ein echtes XQuery-Singleton zu bekommen, muss die eigentliche Abfrage in runde Klammern gesetzt und mit eckigen Klammern ein einzelner Datensatz aus dieser Menge gewählt werden: (xpath)[1].
Dabei sollte man der Performance zu Liebe versuchen, so viel Knotentests [] als irgend möglich aus der Abfrage zu entfernen.

Nachlese der ICE 2009

22.08.2009 16:43:40 | Oliver Scheer

Die ICE (intelligent communities for europe // http://www.ice-lingen.de ) in Lingen ist und bleibt eines meiner Lieblingsevents. Also Begrüßung erwartete jeden Sprecher  auf seinem Bett folgendes (ich habe das jetzt mal nicht genau überprüft, aber ich gehe einfach mal davon aus):

Mein Vortrag dort ging dort natürlich über Silverlight 3. War aber angesichts der Zeit von 45 Minuten eher ein Sprint, als ein Deep Dive.

Folgende verfügbaren Online-Demos habe ich diesmal gezeigt:

  1. Windows4All (was definitiv nicht Windows 8 werden wird :-) )
    http://windows4all.com/
  2. SmoothHD
    http://www.smoothhd.com/ 
  3. IIS7 Smooth Streaming
    http://www.iis.net/media/experiencesmooth
  4. Microsoft World Wide Teleskop
    http://www.worldwidetelescope.org/webclient/
  5. Silverlight 3 Toolkit: http://silverlight.net/samples/sl3/toolkitcontrolsamples/run/default.html
  6. Mein Bubbles-Spielchen mit Out-Of-Browser-Funktionalität
    http://the-oliver.com/projects/games/bubbles/

Die Slides und Demos dazu gibt es hier.

Leider gab es aber auch einen sehr unschönen Fashion-Victim-Incident.

Zu sehen auf dem Bild “Thomas K. aus M. in B.”

codekicker, eine neue Seite in der Community

22.08.2009 13:07:03 | Klaus Bock

codekicker.de Mehr oder weniger durch Zufall bin ich über codekicker gestolpert; und war sehr schnell vom Konzept der Seite begeistert.
Codekicker ist keines der üblichen Foren wie man sie kennt. Die Verantwortlichen Felix Schad und Marvin Steppat, beides Studenten der Uni Karlsruhe, haben sich ein nettes Konzept einfallen lassen. Hier ein Auszug aus der FAQ der Seite.

codekicker ist eine Webseite für Fragen und Antworten rund um das Thema Programmieren. Benutzer können Fragen stellen und Fragen beantworten, genau wie in einem Forum.

codekicker ist aber auch eine Wiki - Fragen und Antworten können von der Community editiert werden, um sie zu verbessern und Fehler zu beseitigen. So steigen Fragen mit der Zeit in ihrer Qualität und verlieren nie an Aktualität.

codekicker wird nicht von uns betrieben - wir machen nur die Technik. codekicker ist die Community aus Programmierern, die von Anderen lernen und ihr Wissen teilen möchten. Daher werden Fragen und Antworten auch nicht von uns moderiert oder zensiert. Dafür ist die Community selbst verantwortlich.

Es gibt keine von den Betreibern ernannten Administratoren oder Moderatoren. Die Aufgaben erledigen die Mitglieder der Seite selbst. Allerdings muss jeder einzelne sich das Recht für entsprechende Privilegien durch das Vertrauen der Mitglieder verdienen.

Das Kernstück des Bewertungssystems bildet die Reputation. Wird eine Frage oder Antwort für gut befunden, kann man eine positive Bewertung abgeben. Der Verfasser der Frage oder Antwort erhält dann 10 Reputationspunkte. Empfindet man eine Antwort als unzureichend oder falsch, kann man diese auch negativ bewerten. Dem Verfasser werden dann 10 Punkte von seiner Reputation abgezogen.
Je mehr Punkte man auf seinem Konto verbuchen kann, desto höher ist natürlich die Reputation und dementsprechend auch die Rechte auf der Seite.
So kann ein Benutzer der über 100 Reputationspunkte verfügt auch negativ bewerten. Um eine Antwort eines anderen Mitglied editieren zu können, bedarf es bereits 500 Reputationspunkte.

Neben der Reputation werden noch sogenannte Abzeichen in den Stufen Bronze, Silber und Gold vergeben. Dies werden einzelnen Mitgliedern für entsprechende Aktivität verliehen.
Silber und Gold erhält man z.B. für Fragen und Antworten die sehr oft positiv bewertet wurden.

Es werden noch viele weitere und sehr interessante Feature geboten wie etwa ein Kopfgeld aussetzen, Fragen und Antworten direkt kommentieren, die Aktivitäten der einzelnen Mitglieder direkt in ihrem Profil sehen udgl.

Im großen und ganzen empfinde ich die Seite als echte Bereicherung der deutschsprachigen Entwicklergemeinde.

Technorati-Tags: | |

Microsoft Small Basic

22.08.2009 04:24:00 | Ozgur Aytekin

A simplified programming language and environment to help teach programming to beginners.

Microsoft Small Basic is a project that is aimed at making computer programming accessible to beginners. The project comprises a simple programming language that gathers inspiration from the original BASIC programming language; a modern and attractive programming environment; and rich, extensible libraries. Together they make programming fun for kids and adults alike.

http://www.microsoft.com/downloads/details.aspx?FamilyID=B006D58D-C2C7-44AD-936B-E7E2D7DE793E&displaylang=en

DateTime.Parse und UTC

21.08.2009 13:57:00 | Martin Hey

Manchmal lässte es sich ganz einfach nicht vermeiden, dass man Datumswerte aus einem Text erzeugen muss. Und aus genau diesem Grund hab ich mich nun auch mal etwas intensiver mit dem Verhalten von DateTime.Parse beschäftigt.

Ausgangspunkt ist folgender Text:
string dateTimeAsText = "2009-08-18T13:36:02.000Z";

Wie man gut erkennen kann, repräsentiert der Text ein Datum mit Zeit in UTC gemäß ISO 8601. Nun kann es ja nicht so schwer sein, diesen Wert als DateTime in UTC zu ermitteln, möchte man meinen - schließlich gibt es ja DateTime.Parse:
string dateTimeAsText = "2009-08-18T13:36:02.000Z";
DateTime dateTimeValue = DateTime.Parse(dateTimeAsText, CultureInfo.InvariantCulture);

Bei der Überprüfung des Wertes fällt auf, dass der erzeugte Wert mitnichten der 18.08.2009 13:36:02 ist, sondern dass direkt eine Umwandlung in die lokale Zeit des ausführenden Systems durchgeführt wird. Erwartet hätte ich, dass der Wert direkt übernommen wird und das DateTimeKind auf DateTimeKind.Utc oder zumindest auf DateTimeKind.Unspecified steht.

Besonders bei Webanwendungen, die nicht in der gleichen Zeitzone laufen in der sich der Client befindet, ist dieses Verhalten eher hinderlich. Hier ist in der Logikschicht und der Datenschicht UTC in meinen Augen die sinnvollste Möglichkeit mit Datumswerten umzugehen und erst in der Präsentationsschicht die Umwandlung in die jeweilige Benutzerzeit durchzuführen.

Erste Möglichkeit ist nun, nach jedem Aufruf der Parse-Methode auf dem entstehenden Wert die Methode ToUniversalTime aufzurufen. Hier könnte man aber erwarten, dass es irgendwie schon eine Out-of-the-box-Lösung gibt, die das gleiche Ergebnis bringt.

Geht nicht? Geht doch. DateTime.Parse hat eine Überladung mit 3 Parametern:
string dateTimeAsText = "2009-08-18T13:36:02.000Z";
DateTime dateTimeValue = DateTime.Parse(dateTimeAsText, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);


Der relevante Wert ist DateTimeStyles.AdjustToUniversal. Dieser legt fest, dass der Ergebniswert ein DateTime vom Typ DateTimeKind.Utc sein soll.

Windows in Silverlight

21.08.2009 12:27:33 | Oliver Scheer

Nein, Windows ist nicht in Silverlight entwickelt worden, auch wenn ich das gerne meinen Kollegen erzähle. Aber was nicht ist kann ja noch werden …

Hier mal ein kleiner Vorgeschmack auf das was vielleicht mal kommen wird, oder nicht, oder vielleicht doch ;)?

http://Windows4all.com 

image

Es ist wieder ice-Zeit!

21.08.2009 09:38:48 | Lars Keller

Heute Abend geht es zur ice:2009 – Intelligent Communities for Europe! Nicki hat mal wieder eingeladen zur kostenlosen Community Konferenz in Lingen/Ems.

Die Agenda ist prall gefüllt mit Tracks für IT-Pros, VT Track, Business, Developer. Ich selber werde einen Vortrag zur MS Office Entwicklung halten.

Ich freue mich auf alle bekannten und neuen Gesichert! Morgen ist ice-Zeit! ;-)

ice2009

This weblog is sponsored by netcreate OHG.

Es ist wieder ice-Zeit!

21.08.2009 08:38:48 | Lars Keller

Heute Abend geht es zur ice:2009 – Intelligent Communities for Europe! Nicki hat mal wieder eingeladen zur kostenlosen Community Konferenz in Lingen/Ems.

Die Agenda ist prall gefüllt mit Tracks für IT-Pros, VT Track, Business, Developer. Ich selber werde einen Vortrag zur MS Office Entwicklung halten.

Ich freue mich auf alle bekannten und neuen Gesichert! Morgen ist ice-Zeit! ;-)

ice2009

Es ist wieder ice-Zeit!

20.08.2009 23:38:04 | Lars Keller

Heute Abend geht es zur ice:2009 – Intelligent Communities for Europe! Nicki hat mal wieder eingeladen zur kostenlosen Community Konferenz in Lingen/Ems.

Die Agenda ist prall gefüllt mit Tracks für IT-Pros, VT Track, Business, Developer. Ich selber werde einen Vortrag zur MS Office Entwicklung halten.

Ich freue mich auf alle bekannten und neuen Gesichert! Morgen ist ice-Zeit! ;-)

ice2009

Zweites Bootcamp bei der DNUG Braunschweig: Software Design Principles / CCD

20.08.2009 16:40:11 | Lars Keller

Unser zweites Bootcamp findet am 09.09.09 statt. Das Thema wird dieses Mal “Software Design Prinicples / CCD” sein. Als Referenten konnten wir dafür Stefan Lieser (http://lieser-online.de) gewinnen.

Dieses Bootcamp wird auch nach dem LdL-Prinzip gehalten. LdL bedeutet Lernen durch Lehren. Hierbei müssen die Teilnehmer aktiv mitmachen. Jeder Teilnehmer bekommt 1-2 Fragen vor dem Event zugeteilt und soll diese dann in dem Bootcamp erklären. Natürlich mit der Hilfe von Stefan.

Interessierte können sich gern hier anmelden.

Ich freue mich auf das Bootcamp!

Links:



This weblog is sponsored by netcreate OHG.

Zweites Bootcamp bei der DNUG Braunschweig: Software Design Principles / CCD

20.08.2009 15:40:00 | Lars Keller

Unser zweites Bootcamp findet am 09.09.09 statt. Das Thema wird dieses Mal “Software Design Prinicples / CCD” sein. Als Referenten konnten wir dafür Stefan Lieser (http://lieser-online.de) gewinnen.

Dieses Bootcamp wird auch nach dem LdL-Prinzip gehalten. LdL bedeutet Lernen durch Lehren. Hierbei müssen die Teilnehmer aktiv mitmachen. Jeder Teilnehmer bekommt 1-2 Fragen vor dem Event zugeteilt und soll diese dann in dem Bootcamp erklären. Natürlich mit der Hilfe von Stefan.

Interessierte können sich gern hier anmelden.

Ich freue mich auf das Bootcamp!

Links:

USB Memory Stick DIY Gehäuse – Wenn Geeks auch Eltern sind

20.08.2009 15:09:12 | Jan Schenk

digg_url = "http://blogs.msdn.com/jansche/archive/2009/08/20/usb-memory-stick-diy-geh-use-wenn-geeks-auch-eltern-sind.aspx";digg_title = "USB Memory Stick DIY Gehäuse – Wenn Geeks auch Eltern sind";digg_bgcolor = "#FFFFFF";digg_skin = "normal";digg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;

CIMG0308 CIMG0310 CIMG0305 Dann wird aus einem Holzbauklotz mal eben ein USB-Stick. Bohrmaschine raus, Loch fräsen, USB-Speichermodul rein, Heisskleber drüber und fertig. Jetzt nur noch hoffen, dass es ne Weile hält. Aber wer kann schon von sich behaupten, dass er nen 4GB Bauklotz in rot besitzt.

Jetzt hoffe ich mal, dass meine Tochter, das Ding nicht in die Finger bekommt. Obwohl, vielleicht will sie dann zum nächsten Level aufsteigen und mit Stecksystemen anfangen, fischertechnik zum Beispiel.

Zweites Bootcamp bei der DNUG Braunschweig: Software Design Principles / CCD

20.08.2009 06:40:00 | Lars Keller

Unser zweites Bootcamp findet am 09.09.09 statt. Das Thema wird dieses Mal “Software Design Prinicples / CCD” sein. Als Referenten konnten wir dafür Stefan Lieser (http://lieser-online.de) gewinnen.

Dieses Bootcamp wird auch nach dem LdL-Prinzip gehalten. LdL bedeutet Lernen durch Lehren. Hierbei müssen die Teilnehmer aktiv mitmachen. Jeder Teilnehmer bekommt 1-2 Fragen vor dem Event zugeteilt und soll diese dann in dem Bootcamp erklären. Natürlich mit der Hilfe von Stefan.

Interessierte können sich gern hier anmelden.

Ich freue mich auf das Bootcamp!

Links:

Grenzfälle – Wann ist Code Clean?

20.08.2009 04:20:00 | Jürgen Gutsch

Aus meinem letzten Blogpost entwickelte sich eine interessante Diskussion zum Thema Clean Code.

Im Grunde ging es in dem Blogpost darum, dass ich mich beschwerte, dass es in LINQ to XML keine “saubere” Möglichkeit gibt XElements mit Namespaces abzufragen. Außer  mit einer vom Peter zur Verfügung gestellten Extension Method.

René wies mich per Kommentar darauf hin, dass man auch die statische Methode XName.Get() verwenden könne um Namen für XElemente mit Namespaces zu generieren.

Ich übernahm Renés Idee wie folgt:
XDocument xdoc = XDocument.Load(xmlResponseReader); 
XName xname = XName.Get("multistatus", "DAV:");
XElement xelement = xdoc.Element(xname);

Damit ging die ganze Diskussion los :-)

René war nun der Ansicht, dass diese drei Zeilen nicht Clean Code seien, da die Erzeugung einer separaten Variablen, die den Wert aus der statischen Methode zugewiesen bekommt, unnötig sei.

René schrieb:
In Bezug auf statische Methode bleibe ich aber bei der Aussage, dass wenn ich den Wert nur 1 mal benötige, dann rufe ich die Methode direkt auf, andernfalls nutze ich einen zusätzlichen Parameter.

René hat absolut recht, was die gezeigten Codes angeht. Die sind klein genug :-)

René und ich haben allerdings nun die unterschiedlichen Anforderungen nicht Berücksichtigt. Der im Blogpost dargestellte Code war natürlich vereinfacht, um das Prinzip zu veranschaulichen. In Wirklichkeit habe ich ein relativ großes XML mit verschiedensten Elementen deren Werte ich abfragen möchte.

Um jetzt mehrere XElemente abzufragen, sähe der Code nach Renés variante so aus:
string nsDAV = “DAV:”;
Folder inboxFolder = new Folder();
inboxFolder.HRef = xfolder.Element(XName.Get(“href”, nsDAV)).Value;
inboxFolder.DisplayName= xfolder.Element(XName.Get(“displayname”, nsDAV)).Value;
inboxFolder.FolderSize= xfolder.Element(XName.Get(“foldersize”, nsDAV)).Value;
inboxFolder.HasChildren= xfolder.Element(XName.Get(“haschildren”, nsDAV)).Value;
inboxFolder.HasSubs= xfolder.Element(XName.Get(“hassubs”, nsDAV)).Value;
// …

Eine Variable vom Typ XName zu erstellen macht hier natürlich keinen Sinn

Aus meiner Sicht bläht diese statische Methode den Code allerdings mehr auf, als die gezeigten Extension Methods:
XNamespace nsDAV = "DAV:";
Folder inboxFolder = new Folder();
inboxFolder.HRef = xfolder.Element(nsDAV, “href”).Value;
inboxFolder.DisplayName= xfolder.Element(nsDAV, “displayname”).Value;
inboxFolder.FolderSize= xfolder.Element(nsDAV, “foldersize”).Value;
inboxFolder.HasChildren= xfolder.Element(nsDAV, “haschildren”).Value;
inboxFolder.HasSubs= xfolder.Element(nsDAV, “hassubs”).Value;
// …

Zurück zum Clean Code: René war der Meinung das es kein Clean Code sei, wenn ich eine separate Variablenzuweisung schreibe. Ich dagegen bin der Meinung, dass man lieber zwei Zeilen schreiben sollte, als zu viele Anweisungen in eine Zeile zu setzen. Ich bin der Meinung das Der Code für jeden vor allem einfach lesbar sein sollte. Je mehr Anweisungen in einer Zeile zu finden sind, desto länger verharrt der “Leser” in der Zeile und desto schwieriger ist es die Zeile schnell zu verstehen. (Und mir ist es dabei egal, ob der Leser ein Einsteiger oder ein erfahrener Entwickler ist)

Natürlich kann es auch hier Ausnahmen geben. In dem letzten Code (oben) habe ich die Ermittlung des XElements und das Auslesen dessen Wertes in eine Zeile gesetzt. Hier wird allerdings auch der Lesefluss nicht beeinträchtigt:
XElement ermitteln => seinen Wert auslesen

An der Stelle habe ich natürlich die extremen Ansicht von Robert C. Martin übernommen, der in seinem Buch Clean Code schreibt, man solle den Code wie einen Zeitungsartikel lesen können. Das setzt nicht nur Lesbarkeit voraus, sondern auch die Einhaltung eines Lesefluss.

Nebenbei: ReSharper beeinflusst: Habe gerade versucht im Live Writer einen Schreibfehler mit [Alt][Enter] zu korrigieren *fg*

René schrieb:
Mein Verständnis von "Clean Code" fängt da an, wo der Code optimiert ist, funktionell korrekt und verständlich. Wenn ich nur den Schwerpunkt auf Verständlichkeit lege, dann hat das wenig mit "Clean Code" im eigentlichen Sinne zu tun.

Clean Code entsteht nur aus einem längeren Prozess heraus und kann nicht einfach so erzeugt, bzw. geschrieben werden. Clean Code entsteht unter anderem durch die Einhaltung der Prinzipien und Regeln des CCD. Clean Code entsteht dabei vor allem aus Wiederholungen von Reviews und Refactoring. Natürlich muss die Funktionalität des Codes immer im Vordergrund stehen, aber beim nachträglichen Bearbeiten seines Codes sollte nach und nach auch an der Lesbarkeit des Codes gearbeitet werden.

Pfadfinderregel:
Verlasse einen Ort sauberer, als du ihn vorgefunden hast.

Zu Ralfs Uommentar:

Jetzt ich gehe mal schnell auf den Kommentar von Ralf Westphal ein:

Ralf schrieb:
Ob
XDocument xdoc = XDocument.Load(xmlResponseReader);
XElement xelement = xdoc.Element("{DAV:}multistatus");

wirklich viel umständlicher ist
XDocument xdoc = XDocument.Load(xmlResponseReader);
XNamespace ns = "DAV:";
XElement xelement = xdoc.Element(ns, "multistatus");

wage ich eigentlich nicht zu beurteilen.

Stichwort: Redundanzen ;-)
Der Namespace “DAV:” kann öfter vorkommen. Ihn jedes Mal angeben zu müssen ist mühsam. Zudem lenkt der Namespace vom eigentlichen Elementnamen ab. Zumindest ist das die Erfahrung beim schreiben des Codes. Wenn man allerdings nur diese kleinen Codesnippets für sich betrachtet ist es wirklich egal.

Ralf schrieb:
Mir schiene jedoch eine Ext Meth, der ich keinen Namespace übergeben muss, noch geeigneter:
XDocument xdoc = XDocument.Load(xmlResponseReader);
XElement xelement = xdoc.Element("DAV:", "multistatus");

Bei so einer Extension Methode sehe ich keine Probleme. Allerdings arbeite ich in der Regel ungerne mit Strings, wenn es sich vermeiden lässt. Wenn es ein Objekt gibt versuche ich dieses zu nutzen.

Ralf schrieb:
An CCD wurde die Frage gestellt, ob 1 Statement pro Zeile angezeigt sei.

Meine Meinung dazu: da ist unter dem Radar von CCD

Logisch, das ist ja auch nicht Aufgabe des CCD das zu definieren. Wie oben bereits geschrieben gibt an dieser Stelle Robert C. Martin eine Empfehlung wie der Code seiner Ansicht nach am besten auszusehen hat. CCD verweist ja lediglich auf sein Buch.

Ralf schrieb:
Was der eine oder andere für lesbar hält, fällt in die Nähe eines Geschmacksurteils…

Im Detail, ja.

Ralf schrieb:
Das Gesamtbild muss stimmen. Und das kann im Detail dann auch mal unterschiedlich aussehen

Logisch.

Ralf schrieb:
Ich wäre zwar nicht allzu traurig, wenn C# nicht mehr als eine Anweisung pro Zeile zuließe, doch ich nehme gern auch die Möglichkeit mit, dass es mehrere sein dürfen.

Dem kann ich nur zustimmen…

Ralf schrieb:
Noch ein Wort zu statischen Methoden, die in der Diskussion auftauchten. Wenn die im API drinstecken, dann kann man nix machen. Sollten wir selbst aber statische Methoden schreiben? Eher nicht. (Auch wenn R# immer mal wieder vorschlägt, eine Methode statisch zu machen.) Der Grund: static methods don´t compose.

Da statische Methoden keine Interfacemethoden implementieren können, kann man ihre Funktionalität nicht gut injizieren. (Von Funktionszeigern darauf sehe ich mal ab.)

Dito…

Zeilenlänte und Schachtelungstiefe

Und damit damit folgende Aussage – die nicht ganz zum Ursprünglichen Thema passt - nicht in den Untiefen der Kommentarfunktion verloren geht, nehme ich sie ebenfalls hier mit rein.

Ralf schrieb:
Wichtiger finde ich zwei andere Dimensionen:

-Zeilenlänge

-Schachtelungstiefe

Eine Zeile mit wievielen Anweisungen auch immer sollte nicht über eine normale Editorfensterbreite hinausgehen. Wenn man scrollen muss, dann sinkt die Verständlichkeit bzw. die Aufnahmegeschwindigkeit rapide.

Und ich finde Schachtelungen beobachtenswert. Es ist ein Unterschied, ob ich

A(B(C()));

oder

var c=C();

var b=B(c);

A(b);

schreibe. Letzteres macht mehr Aufwand, ist aber flüssiger zu lesen, weil man von oben nach unten lesen kann.

Bei der Schachtelung kehrt sich die Leserichtung quasi um: man muss von innen nach außen, d.h. eher von rechts nach links lesen. Das hakt schnell mal. Da hilft auch eine andere Schreibweise nicht viel wie

A(

B(

   C()

  )

);

Deshalb bin ich ja ein Freund von Flow-APIs oder allgm Fluent Interfaces. Die machen nicht nur bei async Verarbeitung das Verständnis und die Notation einfacher.

Wer die Variablen b und c scheut, der könnte doch vielleicht so lesbarer schreiben:

C | B | A

Das ist in C# natürlich nicht so recht möglich. Wie wäre es jedoch mit:

Flow

.From(C)

.To(B)

.To(A)

.Execute();

Sieht für so ein kleines Beispiel etwas überkandidelt aus. Aber wenn die Szenarien größer werden, halte ich das für ein unterschätztes Programmiermodell.

Ich bedanke mich bei allen beteiligten für die anregende Diskussion. Ich finde es immer wieder schön, wenn ein einfacher Blogpsot so eine Diskussion losreißen kann.

DotNetKicks-DE Image

Dev Tools

19.08.2009 23:38:12 | Oliver Scheer

Jeder von uns hat seine Werkzeuge die er im täglichen Entwicklerleben nicht mehr missen möchte. Aber wenn man mal danach gefragt wird, fallen einem die täglichen Helfer nicht ein. Daher möchte diese hier mal aufführen.

Kommentare und weitere Vorschläge sind sehr willkommen und sogar erwünscht.

 

Fiddler Web Debugger

Fiddler ist ein Web Debugging Proxy der den HTTP(S)-Verkehr zwischen dem eigenen Computer und dem Internet protokollieren kann. Fiddler ermöglicht es diesen Verkehr zu untersuchen, Breakpoints einzubauen und den Ein- und Ausgehenden Verkehr zu manipulieren. Fiddler beinhaltet ein eigenes Scripting Subsystem und kann mit .NET Sprachen erweitert werden.

Link: http://www.fiddlertool.com/fiddler/version.asp

 

FileZilla – FTP

FileZilla ist ein FTP-Programm für Windows, MAC und Linux Betriebssysteme. FileZilla ist "Open Source" unter GPL-Lizenz.

Link: www.filezilla.de

 

Internet Explorer 8 Developer Tools

Der Internet Explorer 8 bringt die Developer Tools als zusätzliches Feature mit. Einfach F12-Taste drücken

Link: www.microsoft.com/ie8

 

Live Mesh – Geräte-Synchronisation und mehr

Mit Live Mesh lassen sich verschiedene Computer (Mac und PCs) sowie Mobiltelefone miteinander synchronisieren. Zusätzlich können die Daten im Internet auf dem Live Desktop gespeichert und mit anderen geteilt werden.

Link: www.mesh.com

 

Notepad++ - Texteditor

Notepad++ ist ein Open-Source-Editor, der äußerst viele Programmiersprachen unter MS Windows unterstützt.

Link: notepad-plus.sourceforge.net/de/site.htm

 

Paint.NET – Mehr als Paint

Paint.NET ist ein freier Image- und Foto-Editor für Windows. Leicht durch eigene Plug-Ins erweiterbar, sehr große Community.

Link: www.getpaint.net

 

Windows Problem Steps Recorder

Mit dem Windows Problems Steps Recorder lassen sich Schritte zu einem Problem aufzeichnen und an eine dritte Person schicken. Diese Person kann einfach die Schritte nachvollziehen und so die Lösung besser erkennen.

In Windows 7 enthalten.

 

SDKs – Software Development Kits

 

tbd

 

SysInternals

Die SysInternals sind ein Toolset von Anwendungen die von Microsoft stammen und kostenfrei über die Microsoft-Seite heruntergeladen werden können.

Link: http://technet.microsoft.com/en-us/sysinternals/default.aspx

SysInternals ZoomIT

Werkzeug zu vergrößern des aktuellen Bild. Sehr gut für Präsentationen geeignet.

Link: http://technet.microsoft.com/en-us/sysinternals/bb897434.aspx

"Checked out by somesone else or in another place"... aber wer und wo?

19.08.2009 14:08:00 | Martin Hey

Bei der Arbeit mit dem TFS ist mir aufgefallen, dass an einigen Dateien der Status "Checked out by somesone else or in another place" gesetzt ist.

Zum einen wird man aus dieser Nachricht nicht viel schlauer, zum anderen erscheint sie manchmal auch dann, wenn man allein an einem Projekt arbeitet.

Der erste der genannten Fälle ist ein Bug im TFS - Dateien, für die ein Shelveset existiert werden fälschlicherweise mit diesem Status angezeigt.

Ob eine Datei wirklich von jemand anders angecheckt ist, kann man über das Kommandozeilentool tf.exe erfahren. Dazu öffnet man den Visual Studio 2008 Command Prompt. Der Befehl "tf status $/project /user:* /recursive" zeigt in einer Übersicht mit den Spalten File name, Change, User und Local path alle augechecken Dateien aller Nutzer des angegebenen Projektes an:


Internet Explorer 8 (IE8) Befehlszeilenparameter

19.08.2009 14:04:52 | Kay Giza

Vor einigen Tagen wurde ich danach gefragt, ob es möglich ist den Internet Explorer 8 (IE8) so zu starten, dass man keinerlei neue Internet Adressen eingeben kann. Das ist natürlich mit hauseigenen Internet Explorer 8-Mitteln möglich, durch einen Startparemeter. Dabei wurde mir auch die Frage gestellt, welche Parameter noch möglich sind. In diesem Blogposting erkläre und zeige ich die möglichen Startparameter des Internet Explorer 8. Vorweg: Die sogenannten Befehlszeilenparameter, Befehlszeilenoption, Command Line Parameter, Command Prompt Commands, Command Prompt Parameter oder wie Sie gerne auch noch genannt werden, sind praktisch Anweisungen wie man ein bestimmtes Programm direkt starten kann. In diesem hier beschriebenen Kontext bedeutet dies, dass man den IE8 über 'Start --> Ausführen', über die Windows Eingabeaufforderung, über Verknüpfungen oder bei neueren Windows Betriebssystem auch direkt über das Startmenü mit einem gewissen Parameter starten lassen und ein bestimmtes Programmverhalten erzwingen kann. In diesem Blogposting finden Sie die Internet Explorer 8 Befehlszeilenparameter sowie deren Erklärungen sowie Hinweise zum IE8 Kiosk-Mode... [... mehr]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
Visit:  MSDN Online | Follow MSDN Online on Twitter | Follow Kay Giza on Twitter
Daily News on MSDN:  MSDN Aktuell
© Copyright 2006-2010 Kay Giza. All rights reserved. Legal

“Good News” - SQL Server Driver for PHP 1.1 Community Technology Preview - August 2009

19.08.2009 09:49:15 | Jan Schenk

digg_url = "http://blogs.msdn.com/jansche/archive/2009/08/19/good-news-sql-server-driver-for-php-1-1-community-technology-preview-august-2009.aspx";digg_title = "“Good News” - SQL Server Driver for PHP 1.1 Community Technology Preview - August 2009";digg_bgcolor = "#FFFFFF";digg_skin = "normal";digg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;

Unter http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=ccdf728b-1ea0-48a8-a84a-5052214caad9 steht die CTP, die Community Technology Preview, des neuen SQL Server Treibers für PHP Version 1.1 zum herunterladen bereit.

Ich finde es toll, wenn sich da was bewegt!

Interoperabilität, sie lebe hoch! Hoch! HOCH!

Treffen der .NET Usergroup Dresden

18.08.2009 19:38:00 | Martin Hey

Das nächste Treffen der .NET Usergroup Dresden findet am 09.09. im Gebäude der Communardo Software GmbH statt. Beginn ist wie immer 18:00 Uhr. Folgende Themen gibt es an diesem Abend:
  • Silverlight 2.0 im Unternehmenseinsatz - Integration eines Prozess-Editors à la Visio in SharePoint (Kai-Uwe Gärtner)
  • Lambda Expressions & LINQ Teil 2 (Oliver Guhr)
Weitere Informationen zum Termin und einen Link zur Anmeldeliste findet man auf der Seite der .NET Usergroup.

Gesucht? Gefunden. Im Azure-Forum.NET

18.08.2009 15:20:17 | Jan Schenk

Unter http://www.azure-forum.net/ findet sich ein hilfreiches Forum zu den Themen rund um Azure, Windows Azure, SQL Azure und den .NET Services. Ein Blick, vor allem aber die aktive Teilnahme lohnt sich.

image

IndexOf und LastIndexOf erweitern

18.08.2009 08:58:00 | Martin Hey

IndexOf und LastIndexOf sind sehr mächtige Funktionen. Sie ermöglichen es, die erste bzw. die letzte Position eines Zeichens oder einer Zeichenkette innerhalb einer anderen Zeichenkette zu ermitteln. Leider ist out-of-the-box keine Implementierung vorgesehen, die das zweite Vorkommen oder das vorletzte Vorkommen sucht.
Eine mögliche Lösung kann man sich aber leicht selbst mit Hilfe von Extension-Methods erzeugen:
public static class StringExtensionMethods
{
public static int IndexOf(this string input, string value, int startIndex, int count, int occurrence, StringComparison comparisonType)
{
int retval = startIndex;
for (int i = 0; i < occurrence; i++)
{
retval = input.IndexOf(value, retval + 1, comparisonType);
}
return (retval);
}

public static int LastIndexOf(this string input, string value, int startIndex, int count, int occurrence, StringComparison comparisonType)
{
int retval = startIndex + 1;
for (int i = 0; i < occurrence; i++)
{
retval = input.LastIndexOf(value, retval - 1, comparisonType);
}
return (retval);
}
}

Der zusätzliche Parameter occurrence ermöglicht es, zu spezifizieren, das wievielte Ergebnis man als Rückgabewert bekommen möchte.

dot.NET Code Camp in Bad Ems

18.08.2009 08:40:00 | Jörg Neumann

Im Oktober gibt es beim dot.NET Code Camp wieder geballtes Wissen in kompakter Form. Rainer Stropek, Holger Schwichtenberg und ich vermitteln 5 Tage lang die wichtigsten Grundlagen zu C# 3.0, WPF, Silverlight und WCF. Mehr Infos gibt's hier.

Dot.NET Code Camp - .NET 3.5 & C#
26.10.-30.10 in Bad Ems

Nachtrag zum X200t: Touchscreen mit einem Klick (de-)aktivieren und Digitizer verwenden

17.08.2009 14:52:39 | Jan Schenk

Wer an seinem X200t beides – den Stift und den Finger - als Zeigegerät einsetzen will, der wird früher oder später die Touch-Fähigkeit zeitweise ausschalten wollen, weil er sich mit der aufliegenden Hand immer wieder behindert. Zwar ist die Priorität bei Stiftnähe auf dem Stift, das funktioniert aber nicht immer einwandfrei.

Ich habe auf den LockButton am unteren Bildschirmrand den Aufruf der “Touch Panel”-Settings aus der Systemsteuerung gelegt:

image

image

Als Programm wird einfach nur “C:\Windows\system32\control.exe GzUtil.cpl” verwendet. Dann lässt sich mit einem Klick der Haken in erscheinendem Fenster entfernen, und das Display reagiert nicht mehr auf Touch-Eingaben:

image 

Schöner wär es noch, wenn man mit Druck auf die Taste die Touch-Fähigkeit ohne extra Fenster deaktivieren könnte, und mit langem Druck wieder einschalten. Aber soweit bin ich noch nicht gekommen. Wer es weiss, bitte gerne als Kommentar einsenden!

Visual Studio Team System 2010 Quickhits: 16 Kurzvideos [VSTS 2010 CodeClips]

17.08.2009 14:23:43 | Kay Giza

Kollege Christian Binder hat sechzehn (in Zahlen: 16) Kurzvideos zum Thema Visual Studio Team System 2010 (VSTS 2010) veröffentlicht. Die Videos bzw. CodeClips sind allesamt sehr kurz, knapp und auf den Punkt gebracht. Danke Christian - sehr informativ :) Als kleinen Service habe ich alle diese Videos hier mal zusammengeführt und gleich das Video eingebunden, so dass man direkt einen Blick in das Video werfen kann... [... alle Videos und Links finden Sie in diesem ausführlichen Blogeintrag auf Giza-Blog.de]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
Visit:  MSDN Online | Follow MSDN Online on Twitter | Follow Kay Giza on Twitter
Daily News on MSDN:  MSDN Aktuell
© Copyright 2006-2010 Kay Giza. All rights reserved. Legal

“Wie geil ist das denn” Teil 3 – Mein X200t hat doch Fingertouch

17.08.2009 13:44:59 | Jan Schenk

Als ich vor 4 Wochen meinen neuen Arbeitsrechner bekommen habe, hatte ich scho neinen kleinen Kampf hinter mir. Erst hiess es, das Display ist nur mit Digitizer-Pen zu verwenden. Dann, dass es genau so kommt, wie ich es in unserem internen Shop ansehen kann. Und dann wiederum, dass es leider aber doch keine kapazitiven Fähigkeiten hat, sondern nur auf den Stift reagiert.

Gerade, nachdem ich dabei bin WIndows 7 RTM zu installieren, habe ich den Treiber installiert, den ich im Zuge meiner Grundinstallation vor 4 Wochen heruntergeladen hatte (nennt sich: TouchPanel – Treiber \n Ver 1.2.0 \n Copyright© 2006 GUNZE LIMITED). Der ist von der Lenovo Seite, und ich schreibe das deshalb so ausführlich auf, damit ich selber im Bedarfsfall darauf zurückgreifen kann. Bei der nächsten Installation zum Beispiel.
Auf der Lenovo-Seite läuft der Treiber unter dem schicken Namen 7wgl05ww.exe, zu finden unter lenovo.de –> Support & downloads –> “ThinkPad Tablet Button Driver II for Microsoft Windows Vista 64-bit- ThinkPad X200 Tablet” vom 12.09.2008.

Ich bin so begeistert von Fingertouch, vor allem weil Windows 7 in vielerlei Hinsicht darauf ausgelegt ist, mit dem Finger bedient zu werden. Und nun kann ich das endlich auch nutzen und benutzen!

Ich geh jetzt mal raus und mache einen Luftsprung! Dass ich das per Zufall heraus finden musste, ist wirklich unglaublich!

Viele Grüße,
jan-happy-to-have-touch

18.08.2008 Treffen der .NET Developer Group Braunschweig – Thema SQL Server 2008 – ein Überblick für Entwickler

17.08.2009 10:03:24 | Lars Keller

dotnet-bs_banner_blog

Unser 35 User Group Treffen der .NET Developer Group Braunschweig findet am 18.08.09, ab 19:00 Uhr in der Kilian's Raffinerie statt.

Dieses Mal kommt uns Constantin Klein mit dem Thema “SQL Server 2008 – ein Überblick für Entwickler “ besuchen:

Ähnlich wie es beim SQL Server 2005 der Fall war, bringt auch der SQL Server 2008 wieder eine ganze Vielfalt an Neuerungen und zusätzlichen Features mit sich. Insbesondere werden neben den traditionell von einer Datenbank unterstützten Datentypen mit dem SQL Server 2008 auch neue Datentypen für das Handling von unstrukturierten Daten und von Geodaten eingeführt. Dieser Vortrag gibt einen Überblick über die Neuerungen und Ideen für Anwendungs- und Einsatzmöglichkeiten. Der Schwerpunkt liegt dabei auf dem Thema „Beyond Relational“.

Weitere Informationen unter www.dotnet-braunschweig.de.

Wie immer ist jeder herzlich willkommen!





This weblog is sponsored by netcreate OHG.

18.08.2008 Treffen der .NET Developer Group Braunschweig – Thema SQL Server 2008 – ein Überblick für Entwickler

17.08.2009 09:03:24 | Lars Keller

dotnet-bs_banner_blog

Unser 35 User Group Treffen der .NET Developer Group Braunschweig findet am 18.08.09, ab 19:00 Uhr in der Kilian's Raffinerie statt.

Dieses Mal kommt uns Constantin Klein mit dem Thema “SQL Server 2008 – ein Überblick für Entwickler “ besuchen:

Ähnlich wie es beim SQL Server 2005 der Fall war, bringt auch der SQL Server 2008 wieder eine ganze Vielfalt an Neuerungen und zusätzlichen Features mit sich. Insbesondere werden neben den traditionell von einer Datenbank unterstützten Datentypen mit dem SQL Server 2008 auch neue Datentypen für das Handling von unstrukturierten Daten und von Geodaten eingeführt. Dieser Vortrag gibt einen Überblick über die Neuerungen und Ideen für Anwendungs- und Einsatzmöglichkeiten. Der Schwerpunkt liegt dabei auf dem Thema „Beyond Relational“.

Weitere Informationen unter www.dotnet-braunschweig.de.

Wie immer ist jeder herzlich willkommen!



18.08.2008 Treffen der .NET Developer Group Braunschweig – Thema SQL Server 2008 – ein Überblick für Entwickler

17.08.2009 00:03:02 | Lars Keller

dotnet-bs_banner_blog

Unser 35 User Group Treffen der .NET Developer Group Braunschweig findet am 18.08.09, ab 19:00 Uhr in der Kilian's Raffinerie statt.

Dieses Mal kommt uns Constantin Klein mit dem Thema “SQL Server 2008 – ein Überblick für Entwickler “ besuchen:

Ähnlich wie es beim SQL Server 2005 der Fall war, bringt auch der SQL Server 2008 wieder eine ganze Vielfalt an Neuerungen und zusätzlichen Features mit sich. Insbesondere werden neben den traditionell von einer Datenbank unterstützten Datentypen mit dem SQL Server 2008 auch neue Datentypen für das Handling von unstrukturierten Daten und von Geodaten eingeführt. Dieser Vortrag gibt einen Überblick über die Neuerungen und Ideen für Anwendungs- und Einsatzmöglichkeiten. Der Schwerpunkt liegt dabei auf dem Thema „Beyond Relational“.

Weitere Informationen unter www.dotnet-braunschweig.de.

Wie immer ist jeder herzlich willkommen!



22. Treffen der PASS-Regionalgruppe Sachsen

16.08.2009 22:32:00 | Martin Hey

Am 14.08. hat sich die Regionalgruppe Sachsen der PASS zum 22. Mal getroffen. Hier hatte ich die Gelegenheit, die Basics des in SQL-Server 2008 neuen Datentyps HierarchyId zu erklären und an ein paar Beispielen zu verdeutlichen. In der anschließenden Diskussionsrunde wurden dann im gemeinsamen Live-Coding die noch offenen Fragen geklärt.

Die Folien und die Beispiele kann man auf der Seite der PASS Regionalgruppe Dresden herunterladen.

Entwickler gesucht! Forschungsprojekt: Open Source, Widgets und Co.

16.08.2009 18:21:55 | Kay Giza

Gerne möchte ich auf eine Studie / Umfrage der Uni Bonn aufmerksam machen, völlig unverbindlich - aber vielleicht interessiert es ja die eine oder den anderen hier und ich habe das Interesse geweckt. Ich denke - wie immer bei solchen "Untersuchungen" kommen am Ende nur gute Resultate heraus, wenn sich möglichst viele beteiligen :) Entwickler gesucht! Forschungsprojekt „Open Source, Widgets & Co.“ Haben sie sich bereits aktiv an einem Open Source-Projekt beteiligt? Haben Sie schon einmal Mashup gebaut oder ein Widget entwickelt? Dann nehmen Sie teil an der Umfrage „Open Source, Widgets & Co.“. Die Befragung ist Teil eines Forschungsprojekts... [... alle Details in diesem Blogeintrag auf Giza-Blog.de]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
Visit:  MSDN Online | Follow MSDN Online on Twitter | Follow Kay Giza on Twitter
Daily News on MSDN:  MSDN Aktuell
© Copyright 2006-2010 Kay Giza. All rights reserved. Legal

Die Suche von Blogengine.NET und Sonderzeichen

15.08.2009 13:44:35 | Klaus Bock

Wer sein Blog mit Blogengine.NET betreibt und auch einmal die Suche mit Ausdrücken gefüttert hat die Sonderzeichen enthalten, wird beim Blättern durch die Ergebnisse bestimmt auch auf folgende Unart gestoßen sein: Beim neubilden der URL schneidet Blogengine.NET die Zeichenfolge ab dem Sonderzeichen einfach ab. Nehmen wir als Beispiel einmal den Ausdruck C#. Bei der Eingabe in die Suchmaske und der Ausgabe auf der Ergebnisseite geht noch alles glatt. Sobald aber auf den Link einer weitere Ergebnisseite geklickt wird, erscheint nur noch der Buchstabe C als Ausdruck zur Abfrage. Das Rautenzeichen # und alles was darauf folgt wird einfach entfernt.

Woher kommt dieses Verhalten? Die Lösung ist mehr als simpel: an der falschen Kodierung der Abfragezeichenfolge aus dem QueryString.
Blogengine.NET kodiert den QueryString mit der Methode HtmlEncode zum zurücksenden an den Server. Besser geeignet ist hier die Methode UrlEncode. Wie der Name schon sagt, kodiert diese Methode eine Zeichenfolge zur Verwendung in einer URL.

Mit folgender kleinen Anpassung in der privaten Methode BindPaging der Klasse search, zu finden im Wurzelverzeichnis der Anwendung, lässt sich dieses unschöne Verhalten beheben:

//a.HRef = "?q=" + Server.HtmlEncode(Request.QueryString["q"]) + comment + "&amp;page=" + (i + 1);
a.HRef = "?q=" + Server.UrlEncode(Request.QueryString["q"]) + comment + "&amp;page=" + (i + 1);

Leider habe ich keine andere Möglichkeit gefunden das Verhalten der Suche zu ändern, als die direkte Änderung im Quelltext.

ASP.NET Sicherheit - Directory Traversal verhindern

15.08.2009 13:12:00 | Peter Bucher

Im Wikipedia Artikel ist schon gut und ausführlich beschrieben, was unter “Directory Traversal” zu verstehen ist, Zitat:

Unter Directory Traversal versteht man eine Sicherheitslücke in Web-Programmen wie z. B. einem Webserver oder einer Webanwendung, bei der durch Manipulation von Pfadangaben auf beliebige Dateien und Verzeichnisse zugegriffen werden kann, die dafür eigentlich nicht vorgesehen waren. Diese kann so ausgenutzt werden, dass sensible Daten wie Passwörter preisgegeben werden.

Was kann der Entwickler dagegen tun?
Im besten Fall eine Guid / Id benutzen, um Dateien anzusprechen, jedoch ist das eine Mehrarbeit und manchmal nicht gewollt.

Hier noch kurz ein Fall, der auf Directory Traversal anfällig ist:

string xmlBasePath = Server.MapPath(“~/App_Data/XmlData/”);
string xmlFilePath = Path.Combine(xmlBasePath, Request.QueryString[“filename”]);
XmlDocument document = new XmlDocument();
document.Load(xmlFilePath);

In diesem Fall sieht der Pfad am Schluss so aus: “C:\Pfad\Zum\Web\App_Data\..\bild.xml”
Wie man sieht, ist das Zurückgehen per “../” noch nicht aufgelöst, dies macht entweder Server.MapPath() oder bspw. auch andere Parteien wie bspw. XmlDocument innerhalb der Load()-Methode.

Server.MapPath() wurde im oberen Beispiel aber nur für die Auflösung des Basispfades genutzt, darum hat sie keinen Einfluss.
Beim nächsten Beispiel ist wieder die selbe Situation, nur das hier Server.MapPath() den Pfad auflöst:

string xmlBasePath = “~/App_Data/XmlData/”;
string filePath = Server.MapPath(Path.Combine(xmlBasePath, Request.QueryString[“filename”]));
// weiterer Code…..

Der Wert vom Benutzer – also Request.QueryString[“filename”] – kann also eine “../” Zeichenfolge vor dem Dateinamen selber enthalten und evt. sogar andere Pfadangaben.

Wenn der Benutzer richtig böse ist, kann er so versuchen an einen anderen Ort innerhalb des Webs oder – bei schlechten Sicherheitseinstellungen – sogar des Webservers zu gelangen.

Die simpelste Abwehrmethode ist das Ersetzen von allen möglichen Vorkommnissen von “../”.
Jedoch ist das mühsam und immer noch nicht 100% sicher, denn über eine Eingabe von “/secureimages/image.jpg” kommt der Benutzer immer noch an eine Datei in einem geschützten Unterordner(App_Data ist grundsätzlich geschützt) ran.

Das denkbar schlimmste Horroszenario wäre die Übernahme einer Datenbank oder oder sogar des Servers, was so durchaus machbar wäre.

Die einfachste und zugleich auf effektivste Abwehrmassnahme ist die Benutzung von Path.GetFileName(<Wert vom Benutzer>);

Im oben stehenden Wikipedia Artikel ist noch beschrieben, dass auch Url kodierte Zeichen genutzt werden können und dann die erste hier vorgestellte Lösung unwirksam wird.
Dies muss bei ASP.NET nicht beachtet werden, da bei Request.QueryString[] immer “../” ankommt, die Methode dekodiert also die Werte in der Url schon.

Ein angriffssicheres Beispiel sieht dann so aus:

string xmlBasePath = Server.MapPath(“~/App_Data/XmlData/”);
string xmlFileName = Path.GetFileName(Request.QueryString[“filename”]);
string xmlFilePath = Path.Combine(xmlBasePath, xmlFileName);

XmlDocument document = new XmlDocument();
document.Load(xmlFilePath);

Windows 7 (RTM, finale Version) jetzt auch auf Deutsch verfuegbar

14.08.2009 08:06:53 | Kay Giza

Ab dem frühen Freitagabend des 14.08.2009 stehen für Inhaber einer MSDN Subscription wie bereits angekündigt auf MSDN Online nun auch die Sprachversionen Deutsch, Französisch, Italienisch, Japanisch und Spanisch der finalen Version von Windows 7 bereit. Laden Sie Windows 7 heute bei Ihren MSDN Subscriber-Downloads oder alternativ von dieser Seite herunter. Informieren Sie sich im Windows Developer Center über aktuelle News & Infos und die ersten Schritte zum Thema Softwareentwicklung für Windows 7 oder Anwendungskompatibilität. Weiterhin empfehlen wir Ihnen unsere MSDN Mediathek, wo Sie alle Videos, Podcasts und Multimediainhalte zu Windows 7 finden. Weitere Details zu den Veröffentlichungswellen von Windows 7 finden Sie in diesem Blogeintrag.

Download: Windows 7 (RTM, finale Version) jetzt auch auf Deutsch verfügbar>

Weiterführende Links:



This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
Visit:  MSDN Online | Follow MSDN Online on Twitter | Follow Kay Giza on Twitter
Daily News on MSDN:  MSDN Aktuell
© Copyright 2006-2010 Kay Giza. All rights reserved. Legal

Mit LINQ To Objects jedes n-te Element selektieren

13.08.2009 23:43:00 | Martin Hey

Besonders nach string.Split()-Aufrufen ist es mir schon häufiger untergekommen, dass ich nur jedes 2. Element aus einem Ergebnis-Array bekommen wollte. Meist läuft man dann einfach mit einer for-each-Schleife durch das Array und nimmt sich die passenden Elemente.

Mit Hilfe der Extension-Methods, die Linq bietet, kann man die gleiche Funktionalität auch erreichen. Im folgenden Beispiel wird aus dem Array jedes 2. Element herausgelöst:
string[] values = new [] { "a", "b", "c", "d" };
var result = values.Select(value => value)
.Where((value, index) => (index+1) % 2 == 0);

Ein Thesaurus-Modell zur Verwendung in einer Suche

13.08.2009 16:45:00 | Klaus Bock

<?xml version="1.0" encoding="utf-8" ?>
<thesaurus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Thesaurus.xsd">
  <extension>
    <syn>JS</syn>
    <syn>JScript</syn>
    <syn>JavaScript</syn>
    <syn>Java Script</syn>
  </extension>
  <extension>
    <syn>MS</syn>
    <syn>Microsoft</syn>
  </extension>
  <extension>
    <syn>VB</syn>
    <syn>Visual Basic</syn>
  </extension>
</thesaurus>

Wie im obigen Listing zu sehen, ist das Schema der XML-Datei sehr einfach aufgebaut.
Jede Erweiterung enthält für jedes mögliche Synonym einen eigenen Kind-Knoten. Falls es später einmal nötig sein sollte auch Ersetzungen zu unterstützen, kann das sehr einfach “nachgerüstet” werden.
Um die Datenstruktur in Objekten abzubilden, habe ich mir folgende Lösung überlegt:

  • Zur Abbildung eines Knoten <extension> verwende ich eine Klasse, die alle Synonyme in einer Aufzählung vorhält.
  • Synonyme müssen nur hinzugefügt werden können.
  • Es muss überprüfbar sein, ob ein bestimmtes Synonym bereits in der Instanz enthalten ist.
  • Alle Klassen mit ihren enthaltenen Synonymen werden in einer Aufzählung gesammelt die den Thesaurus darstellt.
  • Jedes Synonym muss im Thesaurus einzigartig sein.
  • Alle in der Aufzählung enthaltenen Synonyme sind über einen Index jederzeit abrufbar.
  • Jeder der Knoten <extension> ist über jeden seiner enthaltenen Synonyme als ganzer Knoten abrufbar.

Entstanden ist aus diesen Vorgaben folgendes Konstrukt:

Thesaurus Diagram

Da die Thesaurus-Funktionalität nicht für eine Verwendung außerhalb der Suche vorgesehen ist, sind die öffentlichen Methoden auf die Abfrage eines bestimmten Synonym und die Rückgabe einer Instanz der Klasse ThesaurusExtension begrenzt.
Um das laden der Thesaurus-Datei und die Abbildung des Inhalts kümmert sich komplett die Klasse Thesaurus. Sie reagiert ebenfalls auf Änderungen an der Thesaurus-Datei und erstellt das Objekt-Abbild derselben gegebenenfalls neu.
Dementsprechend Einfach ist die Verwendung dieses Thesaurus. Es braucht nur geprüft zu werden ob ein bestimmtes Suchwort, im oben genannten Beispiel JS, im Thesaurus enthalten ist. Wird true zurückgegeben, kann mit der Methode Find die entsprechende Instanz der Klasse ThesaurusExtension abgefragt werden. Natürlich wird auch bei der Abfrage nach anderen Synonymen der Instanz, etwa JScript oder JavaScript, ebenfalls diese Instanz zurückgegeben. In der Eigenschaft Synonyms der Instanz befinden sich alle dem Suchwort entsprechenden Synonyme und können den Suchwörtern hinzugefügt werden.

// Liste für Synonyme erzeugen
List<string> expanded = new List<string>();

// nach Synonymen suchen
foreach (var word in searchTerms)
{
	// wenn der Thesaurus das Suchwort enthält
    if (this.thesaurus.Contains(word))
    {
		// durch die Synonyme iterieren
        foreach(var entry in thesaurus.Find(word).Synonyms)
        {
			// wenn das Synonym nicht gleich
			// dem Suchwort ist
            if (!word.Equals(entry,
					StringComparison.OrdinalIgnoreCase))
            {
				// als erweiterter Suchbegriff hinzufügen
                expanded.Add(entry);
            }
        }
    }
}

Da der Thesaurus lediglich eine Auflistung von Objekten darstellt, kann er, wie bereits weiter oben erwähnt, einfach erweitert werden. Sollten einmal Ersetzungen nötig sein, können diese einfach implementiert werden ohne die Kompatibilität mit der jetzigen Version zu gefährden.

Die vorgestellte Lösung stellt lediglich ein sehr einfaches Modell eines Thesaurus dar. Zudem ist diese Lösung auf die Verwendung in einer Suche zugeschnitten.

Technorati-Tags: | | |

LINQ to XML: Queries auf XML mit Namespaces

13.08.2009 04:30:00 | Jürgen Gutsch

Beim Zugriff auf XML mit bestimmten XML-Namespaces kommt es beim herkömmlichen Queries zu einem Fehler. Wie auch beim XMLDoxument muss beim den Abfragen auf bestimmte Knoten ein Namespace angegeben werden.

Ausgangspunkt bei mir ist eine Abfrage per WebDAV auf einen Exchange Server, bei der ich ungefähr folgende Antwort erhalte:
<?xml version="1.0" ?>
<a:multistatus
    xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"
    xmlns:d="urn:schemas:httpmail:"
    xmlns:c="xml:"
    xmlns:a="DAV:">
  <a:response>
    <a:href>http://mdomain/exchange/Account/</a:href> 
    <a:propstat> 
      <a:status>HTTP/1.1 200 OK</a:status> 
      <a:prop>
      </a:prop>
    </a:propstat>
  </a:response>
</a:multistatus>

Folgende Abfrage liefert einen Fehler:
XDocument xdoc = XDocument.Load(xmlResponseReader);
XElement xelement = xdoc.Element("a:multistatus");

XmlException: The ':' character, hexadecimal value 0x3A, cannot be included in a name.

Um das Element nun fehlerfrei zu erhalten muss es wie folgt abgefragt werden:
XDocument xdoc = XDocument.Load(xmlResponseReader);
XElement xelement = xdoc.Element("{DAV:}multistatus");

Damit haben wir den – aus meiner Sicht - ersten und einzigen, aber recht großen Nachteil von LINQ to XML gefunden: Die Namespaces müssen direkt in den Namen des Elements eingegeben werden.

Die Lösung die in der MSDN angeboten wird, ist auch nicht besser:
XDocument xdoc = XDocument.Load(xmlResponseReader);
XNamespace a = "DAV:";
XElement xelement = xdoc.Element(a + "multistatus");

Mir stellt sich hier die Frage: Wieso erstelle ich ein XNamespace-Object wenn ich es dann doch per String-Gebastel in den Elementnamen einbauen muss. Der Kommentator in der MSDN Dokumentation ist ganz offensichtlich der selben Meinung.

Peter hat für dieses Problem eine kleine elegante Lösung, indem er für die Methoden Element und Elements jeweils eine Extension Methode geschrieben hat:
public static IEnumerable<XElement> Elements(
    this XContainer source,
    XNamespace ns,
    string name)
{
  return source.Elements(ns + name);
}
public static XElement Element(
    this XContainer source,
    XNamespace ns,
    string name)
{
  return source.Element(ns + name);
}

So kann ich wenigstens außerhalb der Extension Methoden ohne String-Gebastel auskommen:
XDocument xdoc = XDocument.Load(xmlResponseReader);
XNamespace a = "DAV:";
XElement xelement = xdoc.Element(a, "multistatus");

René hat mich per Kommentar darauf hingewiesen, dass man die Elemente natürlich auch per XName abfragen kann. Das ganze sieht dann so aus:
XDocument xdoc = XDocument.Load(xmlResponseReader); 
XName xname = XName.Get("multistatus", "DAV:");
XElement xelement = xdoc.Element(xname);

DotNetKicks-DE Image

Webcast-Serie: 24 Hours of PASS

12.08.2009 11:06:00 | Martin Hey

Am 02.09.2009 0:00 (UTC) bis 02.09.2009 24:00 (UTC) organisiert die Professional Association for SQL Server (PASS) 24 jeweils 1-stündige Webcasts zu Themen rund um SQL Server. Dabei geht es sowohl um Themen wie Performanceoptimierung und Backup-Strategien als auch Business Intelligence und Reporting Services. Eine komplette Liste der Session sowie einen Link zur Registrierung gibt es hier.

Eine eigene Suche für kleine Webs – Teil 7

11.08.2009 16:01:10 | Klaus Bock

Im vorherigen Artikel der Reihe habe ich die bisher erstellte Suche als linear und naiv so stehen gelassen. In diesem Artikel will ich nun ein Konzept zeigen, welches einer echten Volltextsuche schon sehr nahe kommt.
Dazu werden zunächst einmal zwei verschiedene Container benötigt:

  1. Ein Index welcher die Seiten des Web mit all ihren Informationen enthält.
  2. Ein Volltextkatalog der mit allen im Web vorkommenden Wörtern gefüllt ist. Dabei wird jedes Wort mit einer Liste von URLs verknüpft, in denen das entsprechende Wort vorkommt.

Gesucht wird jetzt nicht mehr im Index des Web, sondern im Volltextkatalog. Doch dazu gleich mehr.

Um nicht die verschiedensten Schreibweißen eines Wortes indizieren zu müssen, wird jedes Wort mit Hilfe der Kölner Phonetik kodiert und in den Volltextkatalog geschrieben. So wird gewährleistet, dass auch jede phonetische Ähnlichkeit in nur einem Datensatz gespeichert wird. Wie der Algorithmus der Kölner Phonetik in .NET verwendet werden kann, habe ich in diesem Artikel schon einmal erläutert.
Es macht allerdings keinen Sinn, jedes mögliche Wort zu kodieren. Also muss ein Kriterium erstellt werden welches festlegt, was ein Wort ist und was nicht. Nach diesem Kriterium muss einmal bei der Erstellung der Kataloge und zum anderen bei der Analyse der Zeichenfolgen aus der Suchmaske unterschieden werden. Zur Unterscheidung eines “echten” Wort von Pseudowörtern wie etwa einer Formel oder einer anderen Abkürzung, habe ich mir folgende Kriterien überlegt:

  • Ein echtes Wort darf nur Buchstaben enthalten, keine Ziffern und Sonderzeichen.
  • Es muss mindestens vier Buchstaben lang sein.

Anhand dieses Kriteriums werden zwei Wortlisten erstellt: eine für die “echten” Wörter und eine für alle vorkommenden Abkürzungen, Formeln udgl. Anschließend werden die beiden Listen entsprechen ihres Inhalts entweder kodiert oder als Klartext im Volltextkatalog gespeichert.

Da in einem etwas umfangreicheren Web schnell einige Tausend verschiedene Wörter vorkommen können, muss der Zugriff auf solch einen Volltextkatalog dementsprechend schnell sein. Da bekanntlich der schnellste Zugriff bei der Abfrage eines einzelnen Element ein O(1)-Vorgang ist, muss der Katalog auch so gestaltet werden, dass die abfragende Methode ein Resultat in einem O(1)-Vorgang liefern kann. Um diese Vorgabe umzusetzen, habe ich mich für ein Dictionary<TKey, TValue> als Kernelement für den Katalog entschieden. Da gewährleistet werden kann, dass jeder Schlüssel, in diesem Fall ein Wort, nur einmal im Dictionary vorkommt, kann die Vorgabe eines O(1)-Vorgang bei der Abfrage als erfüllt angesehen werden.
Wenn jetzt zum Beispiel nach der Zeichenfolge C# im Katalog gesucht wird, ist diese nur einmal enthalten und es wird sofort eine Liste der URLs zurückgegeben in denen die Zeichenfolge C# vorkommt.

Bis jetzt liegt bei der Suche nach der Zeichenfolge C# nur eine Liste von URLs vor, ohne jegliche Information der Seiten welche sich hinter den URLs befinden. Dazu wird nun der Seitenindex des Web benötigt.
Hier verhält es sich etwas anders mit der internen Architektur. Da der Seitenindex nicht nur für die Suche verwendet wird, liegen die Daten intern in einer List<T> welche die Informationen einer jeden Seite in einem Objekt vom Typ SiteEntry speichert. Die Struktur SiteEntry habe ich bereits in früheren Artikeln, z.B.: hier, erläutert.
Da die Aufzählung List<T> keine Zugriffe unterstützt die einem O(1)-Vorgang nahe kommen, habe ich mir hier mit einem kleinem Kniff beholfen. Die Klasse SiteIndex bietet unter anderem einen Indexer, der eine direkten Zugriff auf das jeweilige Element am angegebenen Index zulässt. Parallel zur List<T>, welche die Seiteninformationen speichert, wird ein Dictionary geführt, welches als Schlüssel eine URL verwendet und als jeweiliger Wert wird der Index des betreffenden Elements in der List<T> gespeichert. Das ganze verhält sich ähnlich wie verzweigte Arrays.

 Jagged Dictionary List

Das Dictionary wird nach einer URL abgefragt und liefert den Indexwert des betreffenden SiteEntry-Objekts in der List<T>. Nun wird das Objekt,dessen Index jetzt bekannt ist, direkt und ohne Iteration aus der List<T> zurückgegeben. Auf diese Art und Weiße besitzt der Seitenindex jetzt auch eine Methode, die einem O(1)-Vorgang nahe kommt.
Die Erstellung des parallelen Dictionary ist denkbar einfach. Wenn ein Element dem Seitenindex, also einer List<T>, hinzugefügt wird, fügt die Liste dieses Element am Ende an. Dem Dictionary kann jetzt ein Eintrag mit der aktuellen URL als Schlüssel und der Länge der List<T> –1 als Wert hinzugefügt werden.

public void Add(SiteEntry item)
{
    // prüfen ob der Eintrag noch nicht vorhanden ist
    if (!list.Contains(item))
    {
        this.list.Add(item);

		// Eintrag im Dictionary erzeugen
        this.index.Add(item.Url, this.list.Count - 1);
    }
}

Wenn ein Eintrag aus der List<T> gelöscht wird, muss das Dictionary natürlich ebenfalls aktualisiert werden.

Werfen wir jetzt einen Blick auf den Ablauf einer Suche.

// Liste welche die URLs der Ergebnisse aufnimmt.
List<Uri> uriList = new List<Uri>();

// die einzelnen Suchwörter abfragen
foreach (var word in searchTerms)
{
    // Liste für ein einzelnen Suchwort
    List<Uri> results = null;

    if (SiteSearch.IsRealWord(word))
    {
        // "echtes" Wort; kodiert suchen
        results = (List<Uri>)this.fulltextCatalog.Find(
                        ColognePhonetic.Encode(word));
    }
    else
    {
        // Abkürzung oder Formel; Klartextsuche
        results = (List<Uri>)this.fulltextCatalog.Find(word);
    }

    // prüfen ob Resultate vorliegen
    if (results == null)
    {
        continue;   // nichts gefunden
    }

    // Resultate der URL-Liste hinzufügen
    foreach (var entry in results)
    {
        if (!uriList.Contains(entry))
        {
            uriList.Add(entry);
        }
    }
}

// Liste mit den Seiten als Ergebnis zur Auswertung erzeugen
List<SiteEntry> preSelected = new List<SiteEntry>(uriList.Count);

// die Liste anhand der gefundenen URLs aus dem Seitenindex füllen
foreach (var entry in uriList)
{
    preSelected.Add(this.siteIndex.Find(entry));
}

Für jedes Suchwort aus der Eingabemaske ist nur ein Zugriff als O(1)-Vorgang auf den Volltextkatalog nötig, um sofort alle relevanten URLs zum Suchwort zu erhalten. Die Zurückgegebenen URLs werden in der Liste uriList gesammelt bis alle Suchwörter abgearbeitet sind. Beim übernehmen in die uriList wird geprüft, ob die aktuelle URL aus dem Ergebnis bereits enthalten ist.
Anschließend wird die Liste preSelected als List<T> vom Typ SiteEntry erzeugt und mit den Seiten, die jeweils den URLs entsprechen, aus dem Seitenindex gefüllt. Auch hier ist jede Abfrage ein O(1)-Vorgang.
Wie man im obigen Listing sehen kann, müssen nur zwei Schleifen verwendet werden; ausgenommen der Schleife für die einzelnen Suchwörter.
Wenn es eine Möglichkeit gäbe um zwei Listen zu mergen, so dass in der resultierenden Liste jedes Element nur einmal vorkommt, könnte auch auf die Schleife in der Zeile 277 verzichtet werden.
Was jetzt noch zu tun bleibt, ist die Aus- und Bewertung der Ergebnisse. Eine Umsetzung dazu habe ich schon in Teil – 6 der Artikelreihe gezeigt.

Wen mit dem .NET-Framework in der Version 4.0 endlich offiziell die Parallelisierung Einzug hält, können auch längere Schleifen in ausreichend kurzer Zeit verarbeitet werden. Damit dürfte sich die Ausführungszeit einer Suche noch einmal deutlich verkürzen lassen. Vor allem die Bewertung der Resultate wird davon profitieren.

Das eben vorgestellte Konzept kommt meiner Vorstellung einer Websuche schon sehr nahe. Ein paar Details müssen aber noch überarbeitet werden. Durch die Verwendung der Kölner Phonetik besitzt die Suche schon eine gewisse Fehlertoleranz. So werden z.B.: Resultate zu “shared memory” geliefert auch wenn sich vertippt wird wie etwa": “sharde” anstatt “shared” oder “memmory” anstatt “memory”. Im Ergebnis wird jedoch noch nicht darauf hingewiesen. Um den Hinweis darauf umzusetzen, werde ich wohl um die Verwendung des “teuren” Algorithmus zur Berechnung der Levenshtein-Distanz nicht herumkommen.
Auch die Verwendung eines Thesaurus zum Umsetzen von Erweiterungslisten währe Sinnvoll. Damit könnte z.B.: bei der Eingabe von JS auch zusätzlich nach JScript oder JavaScript gesucht werden.
Die Umsetzung Thesaurus könnte ich mir in naher Zukunft vorstellen, aber für die Implementierung des Levenshtein-Algorithmus warte ich definitiv auf .NET 4.0.

VSTS 2010 Beta Quickhits : Video Index

10.08.2009 04:07:00 | Christian Binder

Nachdem ich jetzt einige kurze Videos zur Beta bereitgestellt habe, möchte ich mit diesem Index eine Übersicht geben. Es fehlen natürlich noch einige Bereiche :-)

VSTS2010Beta1QuickHits

PS: Die Pfeile sind Links zu den Videos

Viel Spass
Chris

“Wie geil ist das denn?” Teil 2 – Office 2010: The Movie

09.08.2009 13:26:20 | Jan Schenk

digg_url = "http://blogs.msdn.com/jansche/archive/2009/08/09/wie-geil-ist-das-denn-teil-2-office-2010-the-movie.aspx";digg_title = "“Wie geil ist das denn?” Teil 2 – Office 2010: The Movie";digg_bgcolor = "#FFFFFF";digg_skin = "normal";digg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;

Ok, ich habe nicht laut gelacht, aber das lag hauptsächlich daran, dass meine 2-jährige Tochter zu dem Zeitpunkt gerade Mittagsschlaf gehalten hat. Ich finde das Video sehr lustig, gelungen und unterhaltsam. Was braucht es mehr?

BizTalk Eloquent: You must specify at least one already-initialized correlation set...

08.08.2009 10:24:00 | Wolfgang Kluge

Die Lösung ist unglaublich einfach - die Frage danach klingt aber alles andere als das *g*. Folgende Fehlermeldung kann beim kompilieren eines BizTalk-Projekts erscheinen.

Error 3: you must specify at least one already-initialized correlation set for a non-activation receive that is on a non-selfcorrelating port.

Die Macher dieser wortgewaltigen Fehlermeldung haben durchaus recht. Damit eine Nicht-aktivierende Receive-Shape (wie übersetzte man das *g*?) auf einem nicht-Selbst-Korrelierenden Port (Anschluss) funktioniert, muss mindestens ein initialisierter Korrelationssatz vorgegeben werden... Das klingt kompliziert - und das ist es auch.

Die andere Seite hätte man - meiner Meinung nach - aber auch dazuschreiben können. Will man keine Korrelationssätze definieren oder braucht man diese erst gar nicht, reicht es auch aus, von einem Nicht-aktivierenden auf einen aktivierenden Port umzustellen. D.h. dass man die Eigenschaft "Activate" des ersten Receive Ports auf "True" stellen muss. Dies dürfte in vielen Fällen auch das gewünschte Verhalten sein...

 Einstellung Activate einer Receive-Shape in Biztalk-Orchestation

Was das ist? Ein aktivierender Receive Port initialisiert die Orchestration, sobald eine Nachricht diesem Anschluss zugeordnet wird. D.h. die Orchestration wird nach dem Empfang auf diesem Port ausgeführt. Daher darf es nur einen solchen Receive Port geben (Ausnahmen gibt's mittels Listen- und Parallel-Shape auch hier) und dieser aktivierende Receive Port muss ganz am Anfang stehen (sonst würde man die Orchestration ja zu einem Zeitpunkt aktivieren wollen, zu dem sie bereits läuft).

Bye Bye Popfly

07.08.2009 10:50:00 | Lori Grosland

logoFalls ihr noch nicht gehört habt, wird Popfly am 24. August eingestellt und alle Sites, Referenzen und Ressourcen werden abgeschaltet. Das bedeutet, dass alle Spiele und Mashups, die ihr gemacht habt, wird gelöscht. Ich finde das sehr traurig und werde Popfly vermissen. Sad

Aber das Popfly-Team hat uns ein Abschiedsgeschenk gegeben: das Popfly Game Downloader. Es ist ein Tool, das erlaubt man Popfly Spiele herunterzuladen und offline zu spielen. Um das Game Downloader zu bekommen, müsst ihr nur ein .Zip-File herunterladen und das Tool installieren.

Das Game Downloader Tool findet ihr auf dieser MSDN-Seite: http://code.msdn.microsoft.com/PopflyGameDownloader

Mit dem Game Downloader Tool könnt ihr jede geteilte (shared) Spiele, die du selbst gebaut hast oder von dem Community herunterladen. Mashups und private Spiele sind nicht unterstützt.

Tipps und Tricks zum Dowloader Tool findet ihr auf der Coding4Fun Webseite: http://blogs.msdn.com/coding4fun/archive/2009/07/22/9845135.aspx

Obwohl Popfly bald weg ist, gibt es immer noch viele andere Möglichkeiten eure Programmierung-Fähigkeiten weiterzuentwickeln. Schau mal diese Ressourcen an, um mehr zu lernen:

Web Applikationen -Microsoft Web Plattform Installer: http://www.microsoft.com/web/

Xbox – Microsoft XNA: http://msdn.microsoft.com/en-us/xna/default.aspx

Xbox – Kodu: http://research.microsoft.com/en-us/projects/kodu/

Windows Programmierung – Microsoft Express: http://www.microsoft.com/express/

Und natürlich auch AntMe: http://antme.net/

Bye Bye Popfly

07.08.2009 10:50:00 | Lori Grosland

logoFalls ihr noch nicht gehört habt, wird Popfly am 24. August eingestellt und alle Sites, Referenzen und Ressourcen werden abgeschaltet. Das bedeutet, dass alle Spiele und Mashups, die ihr gemacht habt, wird gelöscht. Ich finde das sehr traurig und werde Popfly vermissen. Sad

Aber das Popfly-Team hat uns ein Abschiedsgeschenk gegeben: das Popfly Game Downloader. Es ist ein Tool, das erlaubt man Popfly Spiele herunterzuladen und offline zu spielen. Um das Game Downloader zu bekommen, müsst ihr nur ein .Zip-File herunterladen und das Tool installieren.

Das Game Downloader Tool findet ihr auf dieser MSDN-Seite: http://code.msdn.microsoft.com/PopflyGameDownloader

Mit dem Game Downloader Tool könnt ihr jede geteilte (shared) Spiele, die du selbst gebaut hast oder von dem Community herunterladen. Mashups und private Spiele sind nicht unterstützt.

Tipps und Tricks zum Dowloader Tool findet ihr auf der Coding4Fun Webseite: http://blogs.msdn.com/coding4fun/archive/2009/07/22/9845135.aspx

Obwohl Popfly bald weg ist, gibt es immer noch viele andere Möglichkeiten eure Programmierung-Fähigkeiten weiterzuentwickeln. Schau mal diese Ressourcen an, um mehr zu lernen:

Web Applikationen -Microsoft Web Plattform Installer: http://www.microsoft.com/web/

Xbox – Microsoft XNA: http://msdn.microsoft.com/en-us/xna/default.aspx

Xbox – Kodu: http://research.microsoft.com/en-us/projects/kodu/

Windows Programmierung – Microsoft Express: http://www.microsoft.com/express/

Und natürlich auch AntMe: http://antme.net/

Bye Bye Popfly

07.08.2009 10:50:00 | Lori Grosland

logoFalls ihr noch nicht gehört habt, wird Popfly am 24. August eingestellt und alle Sites, Referenzen und Ressourcen werden abgeschaltet. Das bedeutet, dass alle Spiele und Mashups, die ihr gemacht habt, wird gelöscht. Ich finde das sehr traurig und werde Popfly vermissen. :-(

Aber das Popfly-Team hat uns ein Abschiedsgeschenk gegeben: das Popfly Game Downloader. Es ist ein Tool, das erlaubt man Popfly Spiele herunterzuladen und offline zu spielen. Um das Game Downloader zu bekommen, müsst ihr nur ein .Zip-File herunterladen und das Tool installieren.

Das Game Downloader Tool findet ihr auf dieser MSDN-Seite: http://code.msdn.microsoft.com/PopflyGameDownloader

Mit dem Game Downloader Tool könnt ihr jede geteilte (shared) Spiele, die du selbst gebaut hast oder von dem Community herunterladen. Mashups und private Spiele sind nicht unterstützt.

Tipps und Tricks zum Dowloader Tool findet ihr auf der Coding4Fun Webseite: http://blogs.msdn.com/coding4fun/archive/2009/07/22/9845135.aspx

Obwohl Popfly bald weg ist, gibt es immer noch viele andere Möglichkeiten eure Programmierung-Fähigkeiten weiterzuentwickeln. Schau mal diese Ressourcen an, um mehr zu lernen:

Web Applikationen -Microsoft Web Plattform Installer: http://www.microsoft.com/web/

Xbox – Microsoft XNA: http://msdn.microsoft.com/en-us/xna/default.aspx

Xbox – Kodu: http://research.microsoft.com/en-us/projects/kodu/

Windows Programmierung – Microsoft Express: http://www.microsoft.com/express/

Und natürlich auch AntMe: http://antme.net/

Jetzt verfuegbar: Download von Windows 7 Version (RTM, Englisch) fuer MSDN Subscriber ab 06.08.2009 19.00 Uhr

06.08.2009 19:15:09 | Kay Giza

Freudige Nachricht :-): Windows 7 und u.a. die Sprachpakete (Language Packs) sind ab sofort auf den Download-Servern von Microsoft im MSDN Portal verfügbar.

Download-Links und Details siehe hier:
Download: Finale Windows 7 Version (RTM, Englisch) fuer MSDN Subscriber ab 06.08.2009


PS: Kann es sein das Twitter down ist? Schon ziemlich lange? Daher nur hier ein kurzes Posting. Details bitte obigen Link entnehmen.
 


This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
Visit:  MSDN Online | Follow MSDN Online on Twitter | Follow Kay Giza on Twitter
Daily News on MSDN:   MSDN Aktuell
© Copyright 2006-2009 Kay Giza. All rights reserved. Legal

Verwendung der Kölner Phonetik in .NET

06.08.2009 17:39:57 | Klaus Bock

Nachdem ich im vorherigen Artikel eine mögliche Implementierung der Kölner Phonetik gezeigt habe, möchte ich in diesem Artikel den Entwurf einer Klasse für den täglichen Gebrauch vorstellen.

Das Ziel ist eine flexible Verwendung sowohl mit statischen Methoden zum einfachen direkten Vergleich einzelner Wörter und Analyse kleiner Listen, als auch die Verwendung von Instanzen zur Verarbeitung großer und komplexer Wortlisten. Ich gehe heute bewusst nicht auf die technischen Details ein, sondern zeige die Verwendung aus der Sicht des Anwendungsentwicklers.

KoelnerPhonetic Diagram

Werfen wir zunächst einmal einen Blick auf die statischen Methoden:

Mit Encode wird das Ziffernabbild eines Wortes als Zeichenfolge zurückgegeben. Als Parameter wird ein einzelnes Wort erwartet. Ob diese Methode sehr oft benötigt wird kann ich im Moment noch nicht beurteilen. Doch da sie intern zwangsläufig vorhanden ist, kann ich sie genauso gut öffentlich zur Verfügung stellen.

Für den direkten Vergleich zweier Wörter kann die Methode IsSimilar, vom Typ bool, verwendet werden.

Zum finden einer Gruppe von ähnlich klingenden Wörtern in einer Aufzählung, steht die Methode FindSimilar zur Verfügung. Als zu durchsuchende Aufzählung, erwartet die Methode eine beliebige Auflistung deren Inhalt vom Typ string ist. Es kann ein String-Array genauso sein wie eine generische Liste vom Typ string. Der Typ der Aufzählung muss lediglich die Schnittstelle IList<T> implementieren. Zurückgegeben wird eine Liste von gefundenen Ähnlichkeiten in einer IList<T>-Aufzählung. Diese Methode ist zur einfachen Verarbeitung von kleinen Listen gedacht.

Für die Verarbeitung großer und vor allem komplexer Wortlisten, sind die Instanz-Member der Klasse gedacht. Hier kann schon einer Konstruktor-Überladung eine Wortliste übergeben werden. Wenn diese Überladung verwendet wird, muss nach dem Initialisieren der Instanz unbedingt entweder die Methode Analyze oder AnalyzeAsync aufgerufen werden. Der Grund hierfür ist folgender:
Wenn eine sehr große Liste verarbeitet wird, kann das eine beträchtliche Zeit in Anspruch nehmen. Wenn jetzt im Konstruktor die Methode Analyze verwendet wird, blockiert die Anwendung bis die Analyse abgeschlossen ist. Die asynchrone Methode AnalyzeAsync wollte ich nicht verwenden, da vom Entwickler noch kein Eventhandler abonniert wurde. Also bleibt es dem jeweiligen Entwickler freigestellt, ob er mit Analyze die Anwendung blockiert, oder nach dem initialisieren der Instanz das Event AnalyzeCompleted abonniert und dann AnalyzeAsync verwendet.

// eine Instanz erzeugen um mit den Instanz-Membern zu arbeiten
KoelnerPhonetic koelner = new KoelnerPhonetic(words);

// Eventhandler abonnieren der ausgelöst wird,
// wenn eine asynchrone Analyse beendet ist.
koelner.AnalyzeCompleted += 
	new EventHandler<AnalyzeCompletedEventargs>(OnAnalyzeCompleted);

// Namensliste asynchron analysieren
koelner.AnalyzeAsync();

// tue hier was sinnvolles
Thread.Sleep(1000);

// Ergebnisse für "huber" abfragen.
List<string> results = (List<string>)koelner.AllSimilarTo("huber");

Der Status der Instanz, ob bereist analysiert wurde oder nicht, kann jederzeit über die Eigenschaft HasAnalyzed abgefragt werden. Die bereits an die Instanz übergebene Wortliste steht mit der Eigenschaft WordList zur Verfügung.

Die interne Liste, die mit der Eigenschaft WordList eingesehen werden kann, lässt sich jederzeit mit der Methode AddContent erweitern oder vervollständigen. Auch hier steht eine Überladung zur Verfügung. Wenn die Instanz bereits eine Liste enthält und nun diese Liste erweitert wird, muss natürlich neu analysiert werden. Da die hinzugefügte Wortliste durchaus Wörter enthalten kann die in einem der internen Dictionary<TKey, TValue> bereits verarbeitet wurden, müssen natürlich auch diese neu erstellt werden. Deshalb habe ich eine Überladung der Methode hinzugefügt. mit der Standardmethode, wird die Wortliste erweitert und anschließend sofort analysiert. Dies kann, bei einer bereits enthaltenen großen Liste, zu einer Blockierung der Anwendung führen. Wenn statt dessen die Überladung verwendet wird, mit der außer einer Aufzählung auch angegeben werden kann ob sofort analysiert werden soll, kann hier als zweiter Parameter false übergeben werden und die Analyse im Anschluss asynchron gestartet. Ich habe hier bereits ein partielles Update der Dictionary’s in Betracht gezogen, allerdings noch nicht umgesetzt.

Mit der Methode Clear ist die Möglichkeit gegeben, alle internen Listen der Instanz zu leeren und diese Listen somit auf den Status einer Neuinitialisierung zurück zusetzen. Ein abonnierter Eventhandler bleibt davon natürlich unbeeinflusst.

Um alle Ähnlichkeiten eines bestimmten Worts zu erhalten, ist die Methode AllSimilarTo vorgesehen. Mit ihr wird eine Aufzählung aller gefundener phonetischen Ähnlichkeiten eines angegebenen Worts zurückgegeben.

Interessierte können sich den Entwurf als Visual Studio Projekt herunterladen.
Über Feedback würde ich mich freuen. Kritik ist ausdrücklich erwünscht.

KoelnerPhonetic.zip

Technorati-Tags: | | |

Download: Finale Windows 7 Version (RTM, Englisch) fuer MSDN Subscriber ab 06.08.2009

06.08.2009 10:47:59 | Kay Giza

Die finale Version von Windows 7 ist ab heute 6. August 2009  für alle Besitzer einer MSDN Subscription als Download verfügbar. Nutzen Sie die Gelegenheit und holen Sie sich als einer der ersten Windows 7 („RTM“ - „Release to Manufacturing“). Bereit stehen, voraussichtlich in den Nachmittags- bis Abendstunden, sowohl die englische 32- als auch die 64-Bit-Version des Betriebssystems sowie alle Language Packs, WAIKs, WDKs, SDKs & Symbols in allen verfügbaren Sprachen. Laden Sie die finale Version des brandneuen Microsoft Betriebssystem Windows 7 heute bei Ihren MSDN Subscriber-Downloads herunter. Weiterführende Informationen wie z.B. Download-Hinweis zu Windows 7, Informationen zur MSDN Subscription, Veröffentlichungswellen von Windows 7, Informationen zum Windows 7 Release Candidate bzw. dessen Ablaufdaten sowie Informationen für Partner, Unternehmen und Privatnutzer sind Bestandteil dieses ausführlichen Blogartikels auf Giza-Blog.de... [... mehr]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
Visit:  MSDN Online | Follow MSDN Online on Twitter | Follow Kay Giza on Twitter
Daily News on MSDN:   MSDN Aktuell
© Copyright 2006-2009 Kay Giza. All rights reserved. Legal

RIA Summer Jam 2009

05.08.2009 16:08:46 | Oliver Scheer

RIA_SummerJam_speaker_200x120 Rich Internet Applications oder kurz RIA stehen für technisch anspruchsvolle,
multimediale Anwendungen, die innovative Möglichkeiten bieten Ästhetik und
Funktionalität miteinander zu verbinden.

In Kooperation zwischen der Adobe Flex User Group München und P//MOD ist die Idee
entstanden den RIA Summer Jam ins Leben zu rufen. Dabei soll die RIA Technologie
nicht ausschließlich unter den Aspekten Design und Technik fokussiert werden, sondern
auch die Bedeutung und Herausforderung für Marken in den Vordergrund gestellt
werden.

Auf dem RIA Summer Jam präsentieren Profis aus den Bereichen Technik, Design,
Marketing und Projektmanagement das Thema Rich Internet Applications auf 2
Präsentations Tracks.

Im Anschluss an den Event gibt es dann die Möglichkeit beim BBQ auf der
Dachterrasse die Eindrücke des Tages weiter zu vertiefen.
Der RIA Summer Jam 2009 findet am 12. September 2009 in München statt und ist
kostenlos.

090727_RIA_SummerJam_468x60

Weitere Infos und Anmeldung unter www.riasummerjam.de.

Windows 7 bereits ab 6. August 09 für alle MSDN Subscriber verfügbar

05.08.2009 15:42:38 | Oliver Scheer

Die finale Verkaufsversion von Windows 7 ist ab 6. August 09 für alle Besitzer einer MSDN Subscription als Download verfügbar – mehr als zwei Monate vor der offiziellen Veröffentlichung am 22. Oktober 09. Alle Besitzer einer MSDN Subscription können Windows 7 direkt über ihr persönliches Downloadportal herunterladen: http://msdn.microsoft.com/de-de/subscriptions

Speziell für Softwareentwickler und IT-Profis via MSDN

Dies ist bereits die dritte Aufwertung der MSDN Subscriptions binnen weniger als sechs Wochen. Bereits im Juli 2009 wurde MSDN Premium um Betriebssysteme und Entwicklungswerkzeuge für Windows Embedded ergänzt; seit dieser Woche ist das komplette Expression Studio 3 für das Design von Silverlightanwendungen und modernen Windows-Benutzeroberflächen Bestandteil aller MSDN Premium Subscriptions. Microsoft betont damit erneut die Wichtigkeit von Entwicklern für Microsoft und bestätigt erneut die Strategie, Softwareentwicklern und IT-Profis mittels MSDN Subscriptions immer kostengünstig und komfortabel alle Werkzeuge und Plattformen zur Verfügung zu stellen, um optimal für die Entwicklung von Anwendungen für Windows und das Web ausgestattet zu sein.

Eine MSDN Subscription ist ein „Rundum-sorglos-Softwareabo“ für Softwareentwickler und IT-Profis und ist der beste Weg, Visual Studio zu lizenzieren. Sie bedeutet geringere Kosten und bessere Planbarkeit, zukunftssichere Lizenzierung durch Software Assurance und umfassenden Zugriff auf viele Microsoft-Produkte für Test- und Entwicklungszwecke. Ausführliche Informationen zu den MSDN Subscriptions finden Sie hier: http://www.microsoft.com/germany/visualstudio/products/software-assurance.

Insgesamt 893 Versionen von Windows 7 in drei Veröffentlichungswellen

Um allen Sprachanforderungen gerecht zu werden Microsoft veröffentlicht Windows 7 via MSDN Subscriber Images in insgesamt 893 Images in drei Wellen. (Für diejenigen MSDN Subscriber, welche zusätzlich zur Downloadmöglichkeit DVDs erhalten wird Windows 7 in der Novemberlieferung enthalten sein.):

  • Erste Veröffentlichungswelle (ab 6. August 2009):
    • Alle Windows 7 Client-Versionen (x86 und x64) in Englisch
    • Alle Language Packs, WAIKs, WDKs, SDKs & Symbols in allen verfügbaren Sprachen
  • Zweite Veröffentlichungswelle (ab 14. August 2009):
    • Windows Server 2008 R2 Standard, Enterprise, Datacenter, Web, Itanium (x64 und ia64) in den Sprachen Englisch, Französisch, Deutsch, Italienisch, Spanisch und Japanisch
    • Alle Windows 7 Client-Versionen (x86 und x64) in den Sprachen Französisch, Deutsch, Italienisch, Spanisch und Japanisch
    • Checked Builds in Englisch
  • Dritte Veröffentlichungswelle (ab 21. August 09):
    • Die verbleibenden Versionen von Windows 7 Client und Windows Server 2008 R2 Editions in den folgenden Sprachen: Holländisch, Russisch, Chinesisch (vereinfacht), Brazilianisch, Polnisch, Koreanisch, Traditionelles Chinesisch (Taiwan), Traditionelles Chinesisch (Hong Kong/SAR), Türkisch, Tschechisch, Portugiesisch, Ungarisch, Schwedisch, Dänisch, Norwegisch, Finnisch, Arabisch, Hebräisch, Griechisch, Ukrainisch, Thailändisch, Rumänisch, Litauisch, Slowakisch, Bulgarisch, Estnisch, Kroatisch, Serbisch, Lettisch und Slowenisch.
    • Alle Sprachversionen der Windows 7 Starter Edition

Informationen zum Windows 7 Release Candidate

  • Windows 7 Release Candidate wird ab 14. Februar 2010 auf das Ablaufen der Lizenz hinweisen, ab 1. März 2010 wird Windows 7 Release Candidate alle zwei Stunden herunterfahren.
Es gibt keine offizielle Upgrademöglichkeit von Windows 7 Beta oder Windows 7 Release Candidate auf Windows 7. Weitere Informationen dazu finden Sie hier: http://technet.microsoft.com/en-us/library/dd772579(WS.10).aspx

Eine Implementierung der Kölner Phonetik in .NET

04.08.2009 17:40:48 | Klaus Bock

Jeder der sich schon einmal mit der “Suche an sich” beschäftigt hat, kennt das Problem der Erkennung von ähnlichen Wörtern. Egal ob es sich dabei um Tippfehler handelt oder nach ähnlich klingenden Wörtern gesucht werden soll.

Prinzipiell gibt es zwei gangbare Verfahren die Problematik umzusetzen. Einmal die Fuzzy-Suche auf Basis der Levenshtein-Distanz und zum andere die phonetische Ähnlichkeit. Günther Foidl hat den Algorithmus der Fuzzy-Suche auf Basis der Levenshtein-Distanz bereits hier sehr schön in C# umgesetzt.
Ich bin der Meinung, dass sich die Fuzzy-Suche besser zum Vergleich mit festen Wortlisten einsetzen lässt, wie etwa in einer Rechtschreibkorrektur, als zur Verwendung in einer Suche mit ständig wechselndem Inhalt. Auch deshalb habe ich mich einmal etwas intensiver mit der phonetischen Suche auseinander gesetzt.

Als erstes stößt man meist auf den Soundex Algorithmus. Da dieser ursprünglich für die englische Sprache Entwickelt wurde eignet er sich nur sehr bedingt für die Verwendung in anderen Sprachen. Auch wird das Abbild eines Wortes immer auf 4 Zeichen, einen Buchstaben gefolgt von 3 Zahlen, begrenzt. Diese Vorgabe kann beim Vergleich sehr langer Wörter zu unvorhergesehenen Ergebnissen führen.
Die wesentlich bessere alternative, gerade für den deutschen Sprachraum, bietet hier die Kölner Phonetik oder auch Kölner Verfahren genannt. Mit diesem Algorithmus werden alle Buchstaben eines Wortes als Ziffer zwischen 0 und 8 abgebildet. Die exakte Definition des Algorithmus kann unter dem vorherigen Link nachgelesen werden.

Im Wesentlichen läuft die Kodierung eines Wortes in drei Schritten ab.

  1. Buchstabenweise Kodierung aller Buchstaben eines Wortes.
  2. Entfernen aller mehrfach hintereinander vorkommenden Ziffern.
  3. Entfernen aller “0”-Ziffern, außer die erste Ziffer ist eine “0”. Diese bleibt erhalten.

Zum kodieren der einzelnen Buchstaben sowie einigen Regeln wann ein bestimmter Buchstabe wie kodiert wird, ist eine kurze Tabelle die Basis. Ebenfalls unter dem Link zum Artikel in der Wikipedia einzusehen.

Hier nun meine Umsetzung des phonetischen Algorithmus:
Da ja die Kodierung buchstabenweise erfolgt und meistens Wörter als Zeichenfolgen, also als string, behandelt werden, ist der kleinste gemeinsame Nenner ein einzelnes Zeichen. Im .NET-Framework ein Wert vom Typ char. Als erstes habe ich jene Buchstaben-Gruppen der Liste, welche mit festen Werten belegt sind, in verschiedene Array vom Typ char verpackt. Auch verschiedene Buchstaben-Gruppen die in verschiedenen Regeln verwendet werden konnten so schon vorab zusammengefasst werden.

/// <summary>
/// Hält eine Gruppe von Buchstaben die dem Code "0" zugeordnet werden.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] group0 = new char[] { 'A', 'E', 'I', 'J', 'O', 'U', 'Y', 'Ä', 'Ö', 'Ü' };

/// <summary>
/// Hält eine Gruppe von Buchstaben die dem Code "3" zugeordnet werden.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] group3 = new char[] { 'F', 'V', 'W' };

/// <summary>
/// Hält eine Gruppe von Buchstaben die dem Code "4" zugeordnet werden.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] group4 = new char[] { 'G', 'K', 'Q', };

/// <summary>
/// Hält eine Gruppe von Buchstaben die dem Code "6" zugeordnet werden.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] group6 = new char[] { 'M', 'N' };

/// <summary>
/// Hält eine Gruppe von Buchstaben die dem Code "8" zugeordnet werden.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] group8 = new char[] { 'S', 'Z', 'ß' };

/// <summary>
/// Hält eine Gruppe von Folgebuchstaben wenn "C" ein Anlaut ist.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] groupCFirst = new char[] { 'A', 'H', 'K', 'L', 'O', 'Q', 'R', 'U', 'X' };

/// <summary>
/// Hält eine Gruppe von Folgebuchstaben wenn "C" kein Anlaut ist.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] groupCNoFirst = new char[] { 'A', 'H', 'K', 'O', 'Q', 'U', 'X' };

/// <summary>
/// Hält eine Gruppe von die vor "C" stehen können.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] groupCPrevious = new char[] { 'S', 'Z' };

/// <summary>
/// Hält eine Gruppe von Buchstaben die vor "D" oder "T" stehen können.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] groupDTPrevious = new char[] { 'C', 'S', 'Z' };

/// <summary>
/// Hält eine Gruppe von Buchstaben denen "X" folgen kann.
/// </summary>
/// <remarks>n/a</remarks>
private static char[] groupXFollow = new char[] { 'C', 'K', 'Q' };

Nun erfolgt als erstes die buchstabenweise Kodierung einer Zeichenfolge. Dazu wird als erstes die übergebene Zeichenfolge in Großbuchstaben gewandelt und in ein Array vom Typ char kopiert um die Buchstaben bequem einzeln zu verarbeiten. Um die Ziffern eines jeden Buchstaben zusammenfügen zu können, habe ich mich für den StringBuilder entschieden. Dieser ist nicht nur wesentlich performanter als String-Operationen sondern zudem auch flexibler beim Anfügen von char-Werten.
Beim iterieren durch das char-Array wird als erstes geprüft, ob das aktuelle Zeichen auch einem Buchstaben entspricht. Sollte dies nicht der Fall sein, wird das Zeichen ignoriert und mit dem nächsten Zeichen fortgefahren. Als nächstes wird geprüft, ob das Zeichen in einer der Standardgruppen enthalten ist und gegebenenfalls der entsprechende Wert an die StringBuilder-Instanz angefügt. Sollte das Zeichen in keiner der Gruppen enthalten sein, werden jetzt nacheinander die Sonderregeln geprüft.

private static string GetEncoding(string input)
{
    // die Eingabe  in ein Zeichen-Array wandeln
    char[] content = input.ToUpperInvariant().ToCharArray();

    // eine Stringbuilder-Instanz zum ausnehmen
    // der Ziffernabbildung
    StringBuilder sb = new StringBuilder();

    // durch das Zeichen-Array iterieren
    for (int i = 0; i < content.Length; i++)
    {
        char entry = content[i];

        // ignorieren wenn kein Buchstabe
        if (!Char.IsLetter(entry))
        {
            continue;
        }

        // H ignorieren
        if (entry.Equals('H'))
        {
            continue;
        }

        // prüfen ob das Zeichen in einer der
        // Standard-Wertegruppen enthalten ist

        if (group0.Contains(entry))
        {
            sb.Append("0");
            continue;
        }

        if (group3.Contains(entry))
        {
            sb.Append("3");
            continue;
        }

        if (group4.Contains(entry))
        {
            sb.Append("4");
            continue;
        }

        if (group6.Contains(entry))
        {
            sb.Append("6");
            continue;
        }

        if (group8.Contains(entry))
        {
            sb.Append("8");
            continue;
        }

        if (entry.Equals('B'))
        {
            sb.Append("1");
            continue;
        }

        if (entry.Equals('L'))
        {
            sb.Append("5");
            continue;
        }

        if (entry.Equals('R'))
        {
            sb.Append("7");
            continue;
        }

        // Zeichen auf spezielle Wertung überprüfen

        if (entry.Equals('P'))
        {
            // prüfen ob letztes Zeichen im Array
            if (i + 1 >= content.Length)
            {
                sb.Append("1");
                continue;
            }

            // das Folgezeichen lesen
            char next = content[i + 1];

            // wenn Folgezeichen "H"
            if (next.Equals('H'))
            {
                sb.Append("3");
                continue;
            }

            sb.Append("1");
            continue;
        }

        if (entry.Equals('X'))
        {
            // wenn erstes Zeichen im Array
            if (i == 0)
            {
                sb.Append("48");
                continue;
            }

            // vorhergehendes Zeichen lesen
            char previous = content[i - 1];

            // mit Gruppe vorhergehender Zeichen vergleichen
            if (groupXFollow.Contains(previous))
            {
                sb.Append("8");
                continue;
            }

            sb.Append("48");
            continue;
        }

        if (entry.Equals('D') || entry.Equals('T'))
        {
            // prüfen ob letztes Zeichen im Array
            if (i + 1 >= content.Length)
            {
                sb.Append("2");
                continue;
            }

            // Folgezeichen lesen
            char next = content[i + 1];

            // prüfen ob das Folgezeichen
            // in der Ausnahmegruppe enthalten ist
            if (groupDTPrevious.Contains(next))
            {
                sb.Append("8");
                continue;
            }

            sb.Append("2");
            continue;
        }

        if (entry.Equals('C'))
        {
            // wenn C ein Anlaut
            if (i == 0)
            {
                // Folgezeichen lesen
                char next = content[i + 1];

                // wenn Folgezeichen in der Gruppe
                // C-Folgezeichen enthalten ist
                if (groupCFirst.Contains(next))
                {
                    sb.Append("4");
                    continue;
                }

                sb.Append("8");
                continue;
            }
            else // kein Anlaut
            {
                // prüfen ob letztes Zeichen im Array
                if (i + 1 >= content.Length)
                {
                    continue;
                }

                // das nächste und vorherige Zeichen lesen
                char next = content[i + 1];
                char previous = content[i - 1];

                // prüfen ob das Vorhergehende Zeichen in
                // der entsprechenden Gruppe enthalten ist
                if (groupCPrevious.Contains(previous))
                {
                    sb.Append("8");
                    continue;
                }
                else
                {
                    // prüfen ob das Folgezeichen in der
                    // entsprechenden Gruppe enthalten ist
                    if (groupCNoFirst.Contains(next))
                    {
                        sb.Append("4");
                        continue;
                    }

                    sb.Append("8");
                    continue;
                }
            }
        }
    }

    return sb.ToString();
}

Nach der Erstellung der buchstabenweisen Kodierung, werden als nächstes alle mehrfach hintereinander vorkommenden Ziffern entfernt. Dazu wird wiederum die übergebene Zeichenkette in ein char-Array kopiert und Zeichenweise immer mit dem vorangegangenen Zeichen verglichen. Sind die beiden Zeichen ungleich, wird das aktuelle Zeichen in eine StringBuilder-Instanz geschrieben.

private static string CleanDoubles(string input)
{
    StringBuilder sb = new StringBuilder();

    char[] content = input.ToCharArray();

    char previous = new char();

    for (int i = 0; i < content.Length; i++)
    {
        char entry = content[i];

        if (!entry.Equals(previous))
        {
            sb.Append(entry);
        }

        previous = entry;
    }

    return sb.ToString();
}

Als letztes brauchen jetzt nur noch alle 0-Zeichen aus der Ziffernfolge entfernt zu werden. Natürlich mit Ausnahme der ersten Ziffer, sollte diese ein 0-Zeichen sein.

Insoweit ist die Umsetzung des Algorithmus abgeschlossen.
In den nächsten Tagen werde ich eine vernünftige Klasse erstellen und auch ein lauffähiges Beispiel veröffentlichen.

Technorati-Tags: | | |

Error: VS2008-SP1 SplashScreen is not defined in the MarkupCompilePass1

04.08.2009 17:13:48 | Lars Keller

Wer nach einem Update auf das Service Pack 1 des .NET 3.5 Frameworks, den Fehler “VS2008-SP1 SplashScreen is not defined in the MarkupCompilePass1” beim Kompilieren eines WPF Projektes bekommt, sollte das Framework 3.5 SP1 erneut installieren.

Links:



This weblog is sponsored by netcreate OHG.

Error: VS2008-SP1 SplashScreen is not defined in the MarkupCompilePass1

04.08.2009 16:13:48 | Lars Keller

Wer nach einem Update auf das Service Pack 1 des .NET 3.5 Frameworks, den Fehler “VS2008-SP1 SplashScreen is not defined in the MarkupCompilePass1” beim Kompilieren eines WPF Projektes bekommt, sollte das Framework 3.5 SP1 erneut installieren.

Links:

MSDN-TechTalk zum Thema "Anwendungsentwicklung mit Visual Studio 2010"

04.08.2009 11:12:00 | Martin Hey

Die letzte TechTalk-Reihe in diesem Jahr widmet sich dem Thema "Anwendungsentwicklung mit Visual Studio 2010". Dariusz Parys und Christian Binder versprechen wenig Slides und viel Live-Experience.

Auf der TechTalk-Anmeldeseite steht dazu:
Der letzte MSDN TechTalk in diesem Jahr nimmt Sie mit auf eine Reise zur nächsten Version von Visual Studio: Visual Studio 2010. Dabei werden Christian Binder und Dariusz Parys die interessantesten Aspekte der neuen Entwicklungsumgebung vorstellen: von Verbesserungen in den einzelnen Frameworks bis hin zu neuen Möglichkeiten in den Application Lifecycle Management Tools, die das Testen und die Entwicklung im Team einfacher machen, wird dieser TechTalk die verschiedenen Aspekte mit Hilfe von Live Codings demonstrieren. Das heißt ganz klar: Keine Slides! Nur Code!

Hier noch eine kurze Terminübersicht:Leider findet diesmal kein Termin in Dresden statt.

Ab 25. August 2009: Aktualisierung auf Internet Explorer 8 ueber WSUS [IE8]

04.08.2009 10:34:49 | Kay Giza

Ab 25. August 2009 wird über Windows Server Update Services (WSUS) die automatische Aktualisierung auf Internet Explorer 8 als Update Rollup angeboten. Entsprechend sollten sich alle Unternehmen, die ihre Desktop-PCs über diesen Dienst verwalten, darauf vorbereiten. Sind „Update Rollups“ freigeschaltet und ist das Lizenzabkommen akzeptiert, wird automatisch die neue Browser-Version auf PCs mit Internet Explorer 6 oder 7 installiert. Dies geschieht auch, wenn der Kunde bisher die Aktualisierung auf Internet Explorer 8 abgelehnt hat. Das Update funktioniert mit allen vom Browser unterstützten Sprachversionen. In Zukunft werden auch kumulierte Sicherheitsupdates und die Kompatibilitätsliste nach Verfügbarkeit über WSUS bereitgestellt. Falls ein Unternehmen die neue Browser-Version nicht... [... mehr in diese Blogeintrag auf Giza-Blog.de sowie weiterführende Links]

This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
Visit:  MSDN Online | Follow MSDN Online on Twitter | Follow Kay Giza on Twitter
Daily News on MSDN:   MSDN Aktuell
© Copyright 2006-2009 Kay Giza. All rights reserved. Legal

.NET Open Space 2009 Leipzig

04.08.2009 09:19:00 | Martin Hey

Die besten Gespräche hat man fernab von einer festgelegten Agenda, bei einem Kaffee und beim "du". Hier gibt es keine Rollenaufteilung in Sprecher / Zuhörer, Entwickler / Administrator, Softwareentwickler / Projektmanager usw. und die Themen finden sich vor Ort ganz von selbst. Das ist die Idee vom .NET Open Space: Alle sind gleich! Auch die Organisatoren halten sich im Hintergrund und moderieren nur wenig. Verantwortliche der Themenfelder ALT.NET, Clean Code Developer, Mobile Computing, Soft Skills, User Interfaces / User Experience sorgen mit Einladungen für viele Teilnehmer.

Welche Inhalte in den einzelnen Themenfeldern und in welcher Form, z. B. als Vortrag oder in der Runde, bearbeitet werden, wird vor Ort bestimmt. Das nennt sich "Open Space". Die Teilnahme ist kostenlos. Erfahrungsaustausch ist das A und O und steht im Vordergrund. Die Sprache beim .NET Open Space 2009 ist Deutsch. Mehr gibt's nicht zu sagen. Die "Unkonferenz", die sich auf Erfahrungsaustausch konzentriert, läuft am 17./18.10.2009. Mehr dazu unter http://netopenspace.de/2009.

Error: VS2008-SP1 SplashScreen is not defined in the MarkupCompilePass1

04.08.2009 07:13:04 | Lars Keller

Wer nach einem Update auf das Service Pack 1 des .NET 3.5 Frameworks, den Fehler “VS2008-SP1 SplashScreen is not defined in the MarkupCompilePass1” beim Kompilieren eines WPF Projektes bekommt, sollte das Framework 3.5 SP1 erneut installieren.

Links:

Webcasts zu Silverlight

04.08.2009 05:53:28 | Oliver Scheer

MSDN Webcast Serie: Silverlight 3

 

Teil 1: Neuerungen für Jedermann


Dieser Webcast gibt einen einfachen Überblick über die wesentlichen Neuerungen von Silverlight 3: neue Medienformate, perspektivisches 3D, Pixel Shader, Out of Browser sowie viele Verbesserungen der Produktivität für Entwickler und Designer.

Link: http://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=1032421548

Teil 2: Out-Of-Browser


Silverlight 3 Anwendungen können ohne viel Aufwand zu Desktop-Anwendungen erweitert werden. Dieser Webcast zeigt, auf welche Dinge man achten muss, wenn man Out-Of-Browser-Anwendungen erstellen möchte. Wie z.B. installiert man eine Web-Anwendung auf dem Desktop? Wie erkennt man, wo die Anwendung ausgeführt wird, ob eine Internetverbindung besteht oder die Anwendung offline arbeitet? Und wie kann ich meine Anwendung so erstellen, dass sie sich automatisch aktualisiert, wenn eine neuere Version verfügbar ist?

Link: http://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=1032421609

Teil 3: Navigation und Deep Linking


Bisher war es nicht ganz einfach, auf die Browsernavigation zu agieren und über einen Link direkt auf bestimmte Inhalte einer Silverlight-Anwendung zuzugreifen. Durch die neuen Navigations-Features hat man jetzt die Möglichkeit, Silverlight-Anwendungen von der Navigation her genauso wirken zu lassen wie normale Webseiten.

Link: http://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=1032422320

Teil 4: Medieninhalte


In diesem Webcast sehen Sie, wie man mit Silverlight 3 Medieninhalte abspielen kann, wie man mit Expression Encoder 3 Medieninhalte aufbereitet und wie man IIS Smooth Streaming benutzt. Zum Schluß wird noch gezeigt, welche Hosting-Möglichkeiten es gibt. Insbesondere beim Kodieren wird auf die Erstellung von Screencasts eingegangen.

Link: http://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=1032422467

MSDN Webcast Serie: Silverlight in Deep

 

Teil 1: Aspektorientierte Programmierung in Silverlight

Die aspektorientierte Programmierung unter Silverlight ermöglicht es, nicht-funktionale Anforderungen als Aspekte getrennt von der funktionalen Anforderung zu entwickeln, zum Beispiel Validierungen, Sicherheit, Performance und Wartbarkeit. Dadurch wird der spätere Source-Code übersichtlicher und somit besser wartbar, außerdem wird durch die Zentralisierung der Aspekte eine grandiose Freiheit für das komplette Projekt ermöglicht.

Link: http://www.microsoft.com/germany/MSDN/webcasts/library.aspx?id=1032422768 

 

MSDN Webcast Serie: Silverlight für Einsteiger

Teil 1: Die Werkzeuge für Silverlight

Silverlight 2 bringt neben dem Plugin noch eine Vielzahl von Tools, SDKs und Websites mit, die in ihrer Fülle dem Entwickler sehr viele Informationen und Hilfen anbieten. Dieser Webcast gibt einen Überblick das Hilfeangebot und die Tools, die man für die Entwicklung von "Silverlight 2"-Anwendungen benötigt.

Teil 2: Silverlight-Grundlagen

Für die Integration von "Silverlight 2"-Anwendungen in seine eigene Website sind nicht viele Schritte notwendig. Dieser Webcast erklärt die Grundlagen und das Funktionsprinzip von "Silverlight 2".

Teil 3: Einführung in XAML

Eine der Grundlagen von Silverlight ist XAML. Mit XAML hat man die Möglichkeit, die gesamte Oberfläche und die Interaktion durch eine beschreibende Sprache zu definieren. Verschiedene Tools wie Visual Studio und Expression Studio können mittels dieser Sprache miteinander kooperieren. Dadurch ergeben sich eine Vielzahl von Möglichkeiten für den Designer und Entwickler.

Teil 4: Silverlight mit JavaScript

Silverlight 2 erlaubt für die Entwicklung sowohl die Verwendung von JavaScript also auch von Managed Code (C#, Visual Basic, etc.). Dieser Webcast zeigt, wie man mit JavaScript und Silverlight dynamische Webanwendungen erstellt.

Teil 5: Silverlight mit Managed Code

Dieser Webcast zeigt die Vorzüge von Managed Code und stellt die Grundlagen des .NET Frameworks vor.

Teil 6: Expression Blend Einführung

Expression Blend bietet einen anderen Ansatz für die Gestaltung von Anwendungen als man es bisher von Tools wie Visual Studio gewohnt ist. Expression Blend fokussiert sich ganz klar auf die Gestaltung und Interaktion mit Oberflächen.

Teil 7: Silverlight mit Visual Studio

Für die Entwicklung von Silverlight-Anwendungen gibt es eine hervorragende Integration von Silverlight-Tools, die in diesem Webcast erklärt und demonstriert werden.

Teil 8: Arbeiten mit dem Deep Zoom Composer und dem MultiScaleImage

Die "Deep Zoom"-Technologie in Silverlight ermöglicht es, sehr große Bilder und Bildersammlungen sehr schnell und effizient über das Internet zu übertragen und gleichzeitig ein völlig neues "Browsing"-Erlebnis zu liefern. Dieser Webcast zeigt, wie man mit Hilfe des Deep Zoom Composer entsprechende Bilder generiert und diese in Silverlight weiterverwendet.

Teil 9: Eigene Controls mit Silverlight

Einer der großen Vorteile von Silverlight ist die Möglichkeit, sehr einfach und schnell eigene Benutzersteuerelemente zu erstellen. Damit hat man einen hervorragenden Mechanismus zur Wiederverwendung von Benutzersteuerelementen. In diesem Webcast wird auf die Grundlagen der Steuerelement-Entwicklung eingegangen.

Teil 10: Einführung in Expression Encoder

Der Expression Encoder ist ein sehr hilfreiches Werkzeug für die Encodierung von Videos und Audios in das von Silverlight unterstützte WMV-Format bzw. WMA-Format. Er bietet eine Vielzahl von Optimierungsmöglichkeiten an und erlaubt es auch direkt einen Medienplayer für das erstellte Format zu generieren, den man beliebig weiterverwenden kann.

 

LiftOff – Webcast-Serie: Silverlight

 

Teil 1: Das Szenario stellt sich vor – die ersten Controls

Das Szenario stellt einen Web-"Shop" vor, der Gebrauchtwagen anbietet. Mit den Möglichkeiten von Silverlight 2 wird eine benutzerfreundliche Oberfläche erstellt. Teil 1 dieser Webcast-Serie stellt das Szenario vor und gibt einen Überblick über die Projektstrukturen in Visual Studio und Expression Blend. Mit Silverlight Standard-Controls werden die ersten Bestandteile der Anwendung aufgebaut.

Teil 2: Eigene Controls entwickeln, Styles anwenden und Animationen erstellen

Teil 2 beschäftigt sich mit dem Entwickeln und Verwenden von eigenen Controls. Es wird ein Formular erstellt und anschließend mit Hilfe von Styles individuell gestaltet. Abschließend erfolgt eine Einführung in Animationen mit Expression Blend und das dynamische Erstellen von Animationen in Visual Studio.

Teil 3: Geschäftslogik, Formulare und Benutzeranmeldung

In Teil 3 geht es um die Business Logik. Formulareingaben werden verarbeitet und einer Plausibilitätsprüfung unterzogen. Außerdem wird am Beispiel einer „Windows Live“-Anmeldung die Integration der Silverlight-Anwendung in eine ASP.NET-Seite und der Datenaustausch mittels Javascript betrachtet.

Teil 4: Arbeiten mit Daten. Datenbindung und LINQ

Teil 4 beschäftigt sich mit Daten. So werden LINQ und Datenlayer am Beispiel der Anbindung von Daten aus XML und Web Services vorgestellt, welche anschließend mit Hilfe der Daten-Controls angezeigt werden. Formulardaten werden in eine Datenbank abgespeichert.

Teil 5: Animationen und Videos

Teil 5 gibt einen tiefergehenden Einblick in eigene Controls und Animationen. Zusätzlich wird das Thema „Videos in Silverlight“ behandelt. Dies umfasst das Encoding, die Erstellung eines Players und das Erstellen von Videos mit Hilfe des Expression Encoders.

 

MSDN Webcast Serie: Tipps und Tricks zu Silverlight 2

Teil 1: Externe Daten einbinden leicht gemacht

Silverlight kann theoretisch mit nahezu allen Datenformaten arbeiten. Allerdings gibt es oftmals Herausforderungen bei Cross-Domain-Calls. Dieser Webcast zeigt, wie man die Cross-Domain-Problematik umgeht und beliebige Daten aus anderen Quellen in Silverlight verwenden kann.

Teil 2: Daten visualisieren mit Templates für Fortgeschrittene

Daten laden ist einfach. Daten visualisieren ebenfalls. Auch Nicht-Designer können mit einfachen Mitteln und leichtem Databinding Daten sehr ansprechend visualisieren und interaktiver visualisieren. Dieser Webcast beschreibt den Mechanismus zum Binden von Daten in Silverlight und zeigt. wie man mit einfachen Mitteln seine Daten ansprechend darstellen kann.

Teil 3: Erstellen eigener Layout-Container

Mit Canvas, Grid, Border, StackPanel und dem Scrollviewer stehen Silverlight schon mächtige Layoutmechanismen zur Verfügung. Allerdings kann man auch selber sehr leicht einen Container zum automatischen Layouten von Steuerelementen verwenden. Dieser Webcast zeigt, wie man solche Container selber baut und liefert gleich einige neue Container mit.

Teil 4: Datenuploads mit Silverlight

Daten in Silverlight hinladen ist sehr einfach. Was viele jedoch (noch) nicht wissen ist, dass man in Silverlight auch Daten an beliebige Server "hochladen" kann. Es ist möglich, beliebig große Dateien einfach auf einen Server zu laden und dem Benutzer während des Upload-Vorgangs eine ordentliche Fortschrittsanzeige zu präsentieren. Dieser Webcast liefert das Know-How und den Code für eigene Datei-Upload-Steuerelemente.

Teil 5: Design-Time-und Debugger-Tricks

In Silverlight sind einige praktische Features enthalten, die es Entwicklern ermöglichen, UI-Designern die Arbeit zu erleichtern. So können bereits in Blend Daten angezeigt werden, die eigentlich erst zur Laufzeit von Anwendungen verfügbar wären. Dieser Webcast demonstriert einige Features, die das Leben von Designern wesentlich angenehmer machen.

Teil 6: Deep Zoom für Fortgeschrittene

Der Deep Zoom Composer ist nur ein möglicher Weg, um 'Deep Zoom'-Bilder zu erzeugen. Dies geht auch auf "programmiertechnischem" Weg und völlig automatisierbar. Darüberhinaus kann relativ einfach auf den Inhalt des fertigen Deep Zooms zugegriffen und dieser manipuliert werden. Das nötige Know-How wird in diesem Webcast vermittelt.

Teil 7: Comics

Wer liebt sie nicht: Comics. Wie leicht es ist, aus statischen Zeichnungen kleine Comic-Stories zu bauen, wird in diesem Webcast verraten.

Teil 8: Games

Innerhalb dieses Webcast wird ein kleines aber feines Spiel in Silverlight erstellt. Mehr wird noch nicht verraten.

Teil 9: Grafik-Trickkiste

Dieser Webcast gibt einen Einblick in verschiedene grafische Tricks und wie man diese mit Silverlight umsetzen kann.

Teil 10: Datenbank-Frontends

Die Anbindung von Datenbanken an Silverlight-Frontends ist recht unkompliziert: Mittels Webservices oder ADO.NET Data Services lassen sich vollständige Datenbanken sehr einfach integrieren. Dieser Webcast baut ein Datenbank-Frontend basierend auf diesen beiden Zugriffsmöglichkeiten.

 

Druckbetankungen auf Channel9.msdn.com

 

In diesem ersten Teil unserer Silverlight3-Serie "Druckbetankung - Die Show" geht es um Grundsätzliches, von den Voraussetzungen für Silverlight 3, über die Installation zu der neuen Features. Ausserdem installieren und zeigen ein paar Details der Blend 3 Preview, zum Beispiel die dort integrierte IntelliSense-Unterstützung.
Alles zum Ausprobieren und Nachmachen, wie immer auf unterhaltsame Art präsentiert von Oliver Scheer und meiner Wenigkeit.

Druckbetankung - Die Show -- Silverlight 3 Teil I

Im zweiten Teil unserer Staffel Silverlight 3 der Serie "Druckbetankung - Die Show" (ihr seht, wir haben uns Gedanken gemacht, wie das richtige Wording aussehen soll (= ) seht ihr die Navigation Templates, die neu in Silverlight 3 sind. Navigation Templates vereinfachen das Konzept der Seitentransparenz in Silverlight, so dass einzelne Inhalte einer Silverlight-Applikation auch per URL angesteuert werden und von Suchmaschinen so direkt indiziert werden können. Wie das Ganze funktioniert und wo noch weitere Vorteile liegen erfahrt ihr im Video!

Druckbetankung - Die Show -- Silverlight 3 Teil II

Der dritte Teil unserer Silverlight 3 Staffel der Serie Druckbetankung befasst sich mit der Out-of-Browser-Funktionalität, die in Silverlight 3 neu hinzugekommen ist. Diese ermöglicht es dem User, eine Web-Silverlight-Applikation auf dem Desktop bzw. lokal auf dem PC abzulegen, und von dort wie gewohnt zu verwenden, ohne dass ein Browser involviert ist. Oliver Scheer und ich zeigen, wie man seine Applikation Out-of-Browser-Ready macht, und welche zusätzlichen Möglichkeiten der Programmierung dadurch möglich werden. Wir zeigen, wie man der Applikation beibringt zu wissen, ob sie im Browser oder lokal läuft und wie man den Onlinestatus überprüft.

Druckbetankung - Die Show -- Silverlight 3 Teil III

Im vierten Teil unserer Staffel Silverlight 3 der Serie "Druckbetankung - Die Show" erklären Oliver Scheer und ich das Thema Animation und Storyboarding in Expression Blend 3. Ausserdem kommt das Thema "Easing Functions" zur Sprache. Easing Functions erleichtern dank vorgegebener Bewegungsabläufe die natürliche Animation von Objektbewegungen.

Druckbetankung - Die Show -- Silverlight 3 Teil IV

Im fünften Teil der Staffel Silverlight 3 aus der Serie "Druckbetankung - Die Show" geht es um das Binden von Elementeigenschaften an die Werte der Eigenschaften anderer Elemente. Das Sogenannte Element-to-Element Binding ist dafür verantwortlich, dass man in Silverlight mit Hilfe eines Sliders beispielsweise die Darstellungsgröße eines Textes verändern kann. An einem praktischen Beispiel zeigen Oliver Scheer und ich wie diese Technik verwendet wird.

Druckbetankung - Die Show -- Silverlight 3 Teil V

In Teil sechs der Staffel Silverlight 3 aus der Serie "Druckbetankung - Die Show" dreht sich alles um die Plane Projection, die 3D-Projektion in Silverlight 3. Diese Projektion lässt sich sowohl in Expression Blend 3 verändern, als auch an Eingabefelder, beispielsweise Slider, binden und so in der Anwendung selber interaktiv verändern. Oliver Scheer und ich programmieren uns explorativ durch die Möglichkeiten der 3D-Projektion.

Druckbetankung - Die Show -- Silverlight 3 Teil VI

MSDN Solve CodeClips // www.msdn-solve.de

 

Wie kann ich Untertitel in meinen Silverlight Player einbauen?
In diesem CodeClip lernen Sie wie Sie eine eigene Klasse schreiben können, die Ihnen das anzeigen von Untertiteln ermöglicht.

Wie kann ich in Silverlight (RSS) Feeds konsumieren und in meiner Anwendung anzeigen?
In diesem CodeClip lernen Sie wie mit Hilfe der SyndicationFeed Klasse und dem Nutzen der DataContext Eigenschaft sehr einfach (RSS) Feeds konsumieren und anzeigen können.

Wie kann ich Videos mit Hilfe von Streaming.live.com und Silverlight in einer bestehenden PHP, JSP oder ASP.NET Webseite anzeigen?
In diesem CodeClip lernen Sie wie Sie mit Hilfe von Streaming.live.com und Silverlight Videos in Ihre bestehende Webseite einbinden können.

Wie kann ich Bilder aus Flickr in einer PHP-Seite via Silverlight darstellen?
In eine existierende PHP Seite soll eine graphisch ansprechende Image-Gallery mit visuellen Effekten eingebaut werden, die Bilder aus Flickr Anzeigt. Die Gallery basiert auf Silverlight und wird von der PHP Seite mit dem Thema der anzuzeigenden Bildern versorgt.

Wie streame ich Videos in Silverlight mit den IIS Media Services?
Es wird eine Basisinstallation des Windows Server 2008 Standard mit Hilfe des Web Platform Installers für die Nutzung der IIS Media Services konfiguriert. Anschließend wird ein Beispiel Video gestreamt und in Silverlight angebunden.

Wie binde ich eine Silverlight Bildergallerie in eine PHP-Seite ein?
In eine existierende PHP Seite soll eine graphisch ansprechende Image-Gallery mit visuellen Effekten eingebaut werden. Die Gallery basiert auf Silverlight und wird von der PHP Seite mit den anzuzeigenden Bildern versorgt.

Wie greife ich auf Daten eines SAP-Systems in Silverlight zu?
Es wird gezeigt, wie mithilfe der ADO.NET Data Servcies und LINQ to SAP auf Geschäftsdaten eines SAP-Systems in einer Silverlight-Anwendung zugegriffen werden kann. Exemplarisch werden die SAP-Daten in einer Listbox auf einer Silverlight-Seite ausgegeben.

Wie erstelle ich einen Silverlight Client der Datenbankinhalte anzeigen und ändern kann durch Verwendung einer bestehenden WPF Anwendung? [MSDN Solve-CodeClip]
Es soll ein Silverlight Client, der Datenbankinhalte anzeigen und ändern kann durch Verwendung einer bestehenden WPF Anwendung, erstellt werden.

Wie verwende ich DeepZoom in Silverlight2? [MSDN Solve-CodeClip]
Es wird die Deep Zoom Technologie anhand eines Showcases vorgestellt und anschließend ein erstes Deep Zoom Image mit Hilfe des Deep Zoom Composers erstellt und die einzelnen Bestandteile eines Deep Zoom Images erklärt.

Wie zeige ich Silverlight Videos auf einer Webseite an? [MSDN Solve-CodeClip]
Importieren, bearbeiten, kodieren und veröffentlichen von Videos mit dem Expression Encoder

Wie verwende ich das StackPanel in Silverlight? [MSDN Solve-CodeClip]
Controls sollen sich in einer Silverlight-Anwendung automatisch untereinander oder nebeneinander anordnen.

Wie verwende ich das Slider Control in Silverlight? [MSDN Solve-CodeClip]
Erstellen eines Slider Controls und behandeln von Ereignissen

Wie verwende ich das ScrollViewer Control in Silverlight? [MSDN Solve-CodeClip]
Es wird ein ScrollViewer Control erstellt und diesem ein Inhalt zugewiesen

Wie verwende ich das RadioButton Control in Silverlight? [MSDN Solve-CodeClip]
Es werden mehrere RadioButton Controls erstellt, gruppiert und ein EventHandler programmiert

Wie verwende ich das ListBox Control in Silverlight? [MSDN Solve-CodeClip]
Erstellen eines ListBox Control und verarbeiten von Ereignissen

Wie verwende ich das Grid Control in Silverlight? [MSDN Solve-CodeClip]
Es wird mit Hilfe des Grid Controls ein mehrspaltiges und mehrzeiliges Layout erzeugt

Wie verwende ich das DatePicker Control in Silverlight? [MSDN Solve-CodeClip]
Es wird ein DatePicker Control erstellt und bei Auswahl eines Datums, dieses über ein TextBlock Control ausgegeben

Wie verwende ich das DataGrid Control in Silverlight? [MSDN Solve-CodeClip]
Es wird eine Liste erstellt und diese anschließend an eine DataGrid zur Ausgabe gebunden

Wie erstelle ich eigene Controls in Silverlight? [MSDN Solve-CodeClip]
Eigene Controls in Expression Blend erstellen und verwenden. Mit Hilfe von Visual Studio öffentliche Eigenschaften zuweisen und diese in Expression Blend nutzen.

Wie verwende ich das CheckBox Control in Silverlight? [MSDN Solve-CodeClip]
Erstellen einer CheckBox Control und behandeln von Ereignissen

Wie verwende ich das Calendar Control in Silverlight? [MSDN Solve-CodeClip]
Es wird ein Calendar Control erstellt und bei Auswahl eines Datums, dieses über ein TextBlock Control ausgegeben

Wie arbeite ich mit Text in Silverlight? [MSDN Solve-CodeClip]
Verschiedene Eigenschaften des TextBlock-Elementes einsetzen und mit Hilfe des Run-Elementes einzelne Abschnitte innerhalb eines TextBlock-Elementes unterschiedlich formatieren.

Wie kann ich mit Styles in Silverlight arbeiten? [MSDN Solve-CodeClip]
Eigenschaften von Elementen einer Silverlight Anwendung zentral verwalten

Wie arbeite ich mit Ressourcen in Silverlight? [MSDN Solve-CodeClip]
Farben und Füllungen als Ressourcen speichern und nutzen

Wie realisiere ich ein flexibles Layout Management mit Silverlight? [MSDN Solve-CodeClip]
Es wird mit Hilfe von Grid, StackPanel und ScrollView Controls ein flexibles Layout in Silverlight erzeugt.

Wie erstelle ich eine Webseite mit Silverlight 2? [MSDN Solve-CodeClip]
Es wird in Visual Studio eine neue Silverlight Anwendung sowie eine passende Webseite erstellt und die zugehörigen Dateien erklärt.

 

Externe Videos


Für die Inhalte kann keine Garantie übernommen werden

YourExpression.de (WMV-Dateien, mit rechter Maustaste “Speichern unter”)

Video-Casts zu Silverlight und Datenbindung

Silverlight: Architektur und Webservices (WMV, 30MB)

Silverlight: und Data Services (WMV, 30MB)

Silverlight Übersicht

Die 8 goldenen Regeln des UI-Designs (LINK)

Einführung in Silverlight 2.0 (WMV)

Programmierung meets Design: Erzeugen von Objekten via Code (WMV)

Einführung in Expression Web (WMV)

Menüs erstellen mit Expression Web (PDF)

Einführung in Expression Design (WMV)

Die Pipetten in Expression Design (WMV)

Einführung in Expression Blend - Teil A (WMV)

Einführung in Expression Blend - Teil B (WMV)

Expression Blend: Grundlagen von Styles (WMV)

Expression Blend: Anpassen von Controls-Designs mit Control-Templates (WMV)

Die Montagsmeinung: Windows liebt PHP

03.08.2009 21:20:43 | Jan Schenk

Bin ich froh! Also ganz ehrlich, ich bin so froh, dass das Thema Interoperabilität bei Microsoft ernst genommen wird. Dass es ernsthafte und aufrichtige Bemühungen gibt, PHP im IIS und auf Windows sauber zu unterstützen. Und dass PHP-Entwickler ernst genommen werden. Das ist im Prinzip ein Kompliment an alle PHP-Entwickler und auch eins an mich. Und ihr könnt euch sicher sein, dass ich mit wehenden Fahnen auf den Konferenzen dieses Landes stehen werde, und laut und glücklich darüber sprechen werde, dass es endlich eine realistische Chance für das “One Web” gibt und dass PHP-Entwickler keine Softwareprogrammierer zweiter Klasse sind. Warum ich gerade jetzt glücklich darüber bin? Einfach so, aber es lohnt sich natürlich am Ball zu bleiben. Am besten hier auf meinem Blog!
Viele Grüße aus dem Urlaub,
jan

Eine eigene Suche für kleine Webs – Teil 6

03.08.2009 14:39:31 | Klaus Bock

Nach dem der Katalog nun erstellt und mit den Inhalten der Seiten des Webs gefüllt wurde, steht der Benutzung desselben nun nichts mehr im Weg.
Für den Anfang habe ich eine einfache lineare Wortsuche mit einem sehr einfachen Bewertungssystem gewählt. Um Binde- und Füllwörter udgl. von der Suche auszuschließen, verwende ich eine sogenannte Stoppwort-Liste die als einfache Textdatei vorliegt. So kann diese sehr einfach bearbeitet werden. Diese Textdatei wird in ein string-Array geladen und sortiert. Die Abfrage des Array erfolgt mit der statischen Methode BinarySearch der Array-Klasse, was eine sehr schnelle Lösung darstellen dürfte.

Um die Ergebnisse in einem Objekt abzubilden wird die gleiche Struktur SiteEntry verwendet, wie auch schon zur Abbildung einer Inhaltseite im Katalog. Ich habe bereits in Teil 3 auf die mehrfache Verwendung der SiteEntry Struktur hingewiesen.

Um die einzelnen Ergebnisse aufzunehmen, wird noch ein Container dafür benötigt.
Dieser Container, ich habe ihn SearchResult genannt, muss mehrere Voraussetzungen erfüllen. Er soll zum einen leicht über Code zu bearbeiten sein, also Elemente hinzufügen, löschen, sortieren udgl., aber auch an Datensteuerelemente gebunden werden können. Herausgekommen ist dabei diese Klasse.

SearchResult Diagram

Wie schon Eingangs erwähnt, verwende ich erst einmal eine einfache Wortsuche, die sich sequentiell durch den Katalog arbeitet und dabei die Wörter aus der Stoppwort-Liste übersprungen werden. Die Methode, welche die eigentliche Suche ausführt, befindet sich in der Singleton-Instanz der Klasse SiteSearch die ich in diesem Artikel kurz vorgestellt habe, und gibt eine Instanz der SearchResult-Klasse zurück.
Um die Relevanz des Ergebnis zu werten habe ich mir ein einfaches Punktesystem überlegt, dass noch ausgebaut werden kann. Für den Moment wird jeder Treffer im Titel mit 10 und im Text mit 5 Punkten gewertet.
Wenn als z.B. in einer Seite mit dem Titel “Shared Memory in verwaltetem Code” nach shared memory gesucht wird und im Text auch noch beide Wörter vorkommen, erhält dieses Suchergebnis 30 Punkte. Jeweils 10 für beide Suchwörter im Titel und nochmals jeweils 5 für die Treffer im Text. Dabei spielt die Anzahl des Vorkommen eines Worts im Text keine Rolle, sondern nur das es vorhanden ist. Würde die Anzahl gewertet werden und ein Wort währe sehr oft im Text enthalten, entstünde ein falsches Bild der Relevanz da eine andere Seite die mehrere Suchwörter enthält schlechter gewertet würde.

public SearchResult ExecuteSearch(string term)
{
    // wenn noch eine SearchResult-Instanz aktiv ist
    if (this.searchResult != null)
    {
        // Instanz zerstören
        this.searchResult.Dispose();
        this.searchResult = null;
    }

    // Zeichenfolge in ein Array splitten
    string[] searchTerms = term.Split(
                new char[] { ' ' },
                StringSplitOptions.RemoveEmptyEntries);

    // Wenn keine Wörter enthalten
    if (searchTerms.Length < 1)
    {
        // eine neue leere instanz zurückgeben
        return new SearchResult();
    }

    // neue Instanz erzeugen
    this.searchResult = new SearchResult();

    // durch den Volltextkatalog iterieren
    foreach (var entry in SiteSearch.GetInstance().fulltextCatalog)
    {
        // neue Instanz der SiteEntry-Struktur erzeugen
        SiteEntry resultEntry = new SiteEntry();

        // durch die einzelnen Wörter der Suche iterieren
        foreach (var word in searchTerms)
        {
            // prüfen ob das Wort in der Stopword-Liste enthalten ist
            if (Array.BinarySearch(SiteSearch.stopwords, word) > 0)
            {
                // suchwort in der Stoppwortliste enthalten,
                // weiter mit dem nächsten Suchwort
                continue;
            }

            // prüfen ob das Suchwort im Titel vorhanden ist
            if (entry.Title.ToUpperInvariant().Contains(word.ToUpperInvariant()))
            {
                resultEntry.Title = entry.Title;

                // Suchwort im Titel enthalten; 10 Punkte
                resultEntry.Rank += 10;
            }

            // prüfen ob das Suchwort im Inhalt enthalten ist
            if (entry.Content.ToUpperInvariant().Contains(word.ToUpperInvariant()))
            {
                // wenn noch kein Content dem Ergebnis hinzugefügt wurde
                if (string.IsNullOrEmpty(resultEntry.Content))
                {
                    resultEntry.Content = SiteSearch.GetFragment(entry.Content);
                }

                // Wort enthalten; 5 Punkte
                resultEntry.Rank += 5;

                // prüfen ob der Titel noch leer ist
                if (string.IsNullOrEmpty(resultEntry.Title))
                {
                    // Titel hinzufügen
                    resultEntry.Title = entry.Title;
                }

                // prüfen ob die Url und das Datum schon gespeichert wurden.
                if (resultEntry.Url == null)
                {
                    // Datum und Url speichern
                    resultEntry.PubDate = entry.PubDate;
                    resultEntry.Url = entry.Url;
                }
            }
        }

        // Wenn der Titel nicht leer ist
        if (!string.IsNullOrEmpty(resultEntry.Title))
        {
            // dem Ergebnis hinzufügen
            this.searchResult.Add(resultEntry);
        }
    }

    // Ergebnisse nach Relevanz sortieren
    this.searchResult.Sort();

    // Ergebnis zurückgeben
    return this.searchResult;
}

Im Moment ist die Suche noch sehr naiv. Es werden keine Wortvarianten, wie etwa außer JS auch JavaScript und JScript oder ähnliches, erkannt. Auch werden keine Tippfehler berücksichtigt. Doch um ein Konzept zu zeigen, dürfte die Ausführung allemal ausreichen.

Was noch fehlt, ist die Ausgabe des Ergebnis auf einer ASP.NET-Seite, doch das sollte kein Problem darstellen. Das zu bindende Objekt ist vorhanden und der Rest sollte Routine sein.

Ich lasse diese Artikelreihe hier so offen stehen, denn vieleicht folgt ja noch die ein oder andere Ergänzung wie etwa die Verwendung eines Thesaurus oder ähnlichem.

Eine eigene Suche für kleine Webs – Teil 5

02.08.2009 13:52:06 | Klaus Bock

Oder wie analysiere ich eine gerenderte Seite?
Im letzten Artikel habe ich bereits erwähnt, dass in diesem Artikel die Analyse der einzelnen Seiten mit der Klasse SiteAnalyzer näher beleuchtet wird. Wie das folgende Klassendiagramm bereits erahnen lässt, ist die Verwendung denkbar einfach.

SiteAnalyzer DiagramDer parameterlose Konstruktor ist nur enthalten um bei einem Type-Cast keine Probleme zu verursachen. Verwendet wird eigentlich nur die Überladung, bei der die Uri der zu analysierenden Seite mit angegeben wird. In der Eigenschaft TitleDelimeter kann ein Zeichen angegeben werden, welches den Titel trennen kann, da in vielen Blogs und Websites der Name des Blog oder der Site dem eigentlichen Titel vorangestellt wird.
Die eigentliche Analyse wird mit der Methode AnalyzeSite ausgeführt.
Nach erfolgter Analyse enthalten die Eigenschaften SiteTitle und SiteContent den Titel der Seite bzw. den Inhalt ohne jegliches HTML. Falls die Seite über keinen Titel verfügt, oder dieser nicht ermittelt werden kann, wird die Uri der Seite als Titel zurückgegeben.
Die beiden privaten Felder body und title, vom Typ RegEx, halten die Instanzen der regulären Ausdrücke um den Inhalt und den Titel-Tag der Seite zu finden. Die privaten Methoden GetContent und GetTitle extrahieren sowohl den Titel als auch den Inhalt der Seite mit Hilfe der beiden RegEx-Instanzen und werden ihrerseits von der öffentlichen Methode AnalyzeSite verwendet. Soweit zur Theorie.

 

Zur Definition des RegEx für den Title-Tag dürfte nicht sehr viel zu sagen sein. Nur soviel, alle Tags in einer Seite können sowohl auf eine einzelne Zeile begrenzt, als auch über mehrere Zeilen erstreckt sein. Das sollte bei der Initialisierung der RegEx-Instanzen beachten werden. Genauso sollte auf die Beachtung der Groß- und Kleinschreibung verzichtet werden.
Für die Bestimmung des Content der Seite, habe ich mich allerdings eines kleinen Kniffs bedient. Da die Suche in einem Web läuft welches ich selbst erstellt habe, kann ich auch im Markup mittels eines Kommentar diesen als solchen kennzeichnen.

<!-- begin SiteContent -->
<asp:ContentPlaceHolder ID="ContentBody" runat="server" />
<!-- end SiteContent -->

Wie im obigen Listing zu sehen ist, wird in der MasterPage der ContentPlaceHolder zwischen zwei Kommentare gesetzt und ist so im gerenderten HTML sehr leicht zu finden. Diese Vorgehensweise funktioniert natürlich nur, wenn man auch Zugriff auf den Quelltext der Webanwendung hat. Mit diesem Vorgehen, lässt sich der eigentliche Inhalt der Seite mit einem einfachen RegEx finden.

private static Regex body = new Regex(
    "<!-- begin SiteContent -->(.*)<!-- end SiteContent -->",
    RegexOptions.IgnoreCase |
    RegexOptions.Multiline |
    RegexOptions.Singleline |
    RegexOptions.CultureInvariant);

Bevor aber der Inhalt gesucht werden kann wird erst einmal eine Text benötigt, in dem gesucht wird. Hierzu wird einfach die Seite in einem Stream von einem HttpWebResponse-Objekt gelesen und in einem string gespeichert.

public void AnalyzeSite()
{
    var request = (HttpWebRequest)WebRequest.Create(this.SiteUrl);
    request.UserAgent = "klaus_b@.NET SiteAnalyzer";
    string rawContent = null;
    var response = (HttpWebResponse)request.GetResponse();
    var responseStream = response.GetResponseStream();

    using (var reader = new StreamReader(responseStream, Encoding.UTF8))
    {
        rawContent = reader.ReadToEnd();
    }

    response.Close();
    responseStream.Dispose();

    if (string.IsNullOrEmpty(rawContent))
    {
        return;
    }

    string title = SiteAnalyzer.GetTitle(
						rawContent,
						this.TitleDelimeter);
    this.SiteTitle = title != null ? title : this.SiteUrl.ToString();
    this.SiteContent = SiteAnalyzer.GetContent(rawContent);
}

Wenn der String rawContent nichts enthält wird die Methode beendet, da eine weitere Verarbeitung sinnlos währe. Wenn Daten enthalten sind, liegt der komplette Inhalt der Seite in einem sehr rohen Format vor. Soll heißen: alle HTML-Tags sind noch enthalten. Jetzt wird als erstes versucht, den Title-Tag zu finden. Dies geschieht mit der privaten statischen Methode GetTitle, die den Inhalt einer Seite und ein eventuelles Trennzeichen als Parameter erwartet. Das Trennzeichen kann auch null sein, wenn keines verwendet wird.

private static string GetTitle(string siteContent, string delimeter)
{
    string value = null;

    Match match = SiteAnalyzer.title.Match(siteContent);
    if (!match.Success)
    {
        // kein Titel gefunden
        return value;
    }

    // Titel gefunden
    value = match.Groups[1].Value;

    if (!string.IsNullOrEmpty(delimeter))
    {
        int index = value.IndexOf(delimeter, StringComparison.OrdinalIgnoreCase) + 1;

        if (index >= 0)
        {
            value = value.Substring(index, value.Length - index);
        }
    }

    value = value.Replace("\r\n", string.Empty)
                 .Replace("\t", string.Empty);

    return HttpUtility.HtmlDecode(value).Trim(); ;
}

Dann wird der zurückgegebene Wert auf null geprüft. Wenn der Wert null ist, wird statt des Titel die URL der Seite zurückgegeben. Zu sehen in Zeile 107.
Nachdem der Titel verarbeitet wurde, kommt jetzt der Inhalt an die Reihe.

private static string GetContent(string siteContent)
{
    string value = null;

    Match match = SiteAnalyzer.body.Match(siteContent);

    if (!match.Success)
    {
        return value;
    }

    value = match.Groups[1].Value;

    value = Utils.StripHtml(value);

    value = value.Replace("\r\n", string.Empty)
                 .Replace("\t", string.Empty)
                 .Replace("      ", " ")
                 .Replace("     ", " ")
                 .Replace("    ", " ")
                 .Replace("   ", " ")
                 .Replace("  ", " ");

    value = HttpUtility.HtmlDecode(value).Trim();

    return value;
}

Zunächst wird der Bereich des relevanten Inhalt mittels des weiter oben beschrieben regulären Ausdrucks ermittelt und in der Variablen value als String gespeichert. Das entfernen der HTML-Tags geschieht, in Zeile 124 zu sehen, mit Hilfe der Methode StripHtml aus der Hilfsklasse Utils. In dieser Klasse sind mehrere Methoden und Eigenschaften enthalten, die ich immer wieder an den verschiedenen Stellen benötige. Die Methode StripHtml entfernt die Tags mittels eines einfachen RegEx.

/// <summary>
/// Hält eine Regex-Instanz zum entfernen von jeglichem Html
/// aus einer Zeichenfolge.
/// </summary>
/// <remarks>n/a</remarks>
private static readonly Regex htmlStrip = new Regex(
    "<[^>]*>",
    RegexOptions.Multiline |
    RegexOptions.Singleline |
    RegexOptions.Compiled);

Dabei werden einfach alle möglichen Tags durch das Feld Empty der String-Klasse ersetzt.

/// <summary>
/// Entfernt jegliches Html aus einer Zeichenfolge.
/// </summary>
/// <param name="html">
/// Die zu bereinigende Zeichenfolge.
/// </param>
/// <returns>
/// Eine Zeichenfolge ohne jegliches Html.
/// </returns>
/// <remarks>n/a</remarks>
public static string StripHtml(string html)
{
    if (string.IsNullOrEmpty(html))
    {
        return string.Empty;
    }

    return Utils.htmlStrip.Replace(html, string.Empty);
}

Anschließend werden noch Zeilenumbrüche, Tabulatorzeichen und überzählige Leerzeichen entfernt. Jetzt braucht die Zeichenfolge nur noch HTML-dekodiert zu werden und es liegt ein sauber lesbarer Text vor.

Soweit ist die Erstellung des Katalog mit lesbaren Abbildungen der Seiten des Web abgeschlossen. Im nächsten Artikel werde ich mich mit der Ausführung einer Suche und der Bewertung des Ergebnis der Suche befassen.

C# oder VB: Welche Sprache soll ich lernen?

01.08.2009 09:37:00 | Peter Bucher

Am 13. Oktober 2008 haben Golo Roden und ich unter dem Titel Noch Fragen, Roden? Ja, Bucher! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen. Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. Juli 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

C# oder VB: Welche Sprache soll ich lernen?

So wohl Golo wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Außerdem nimmt diesen Monat auch Christian Wenz an unserem Streitgespräch teil.

Golos und Christians Kommentare finden sich zeitgleich in den entsprechenden Blogs, folgend nun mein Kommentar zu diesem Thema:

Also gleich vorneweg, es geht hier nicht um eine Glaubensfrage und auch nicht um “C# vs VB.NET” das bei einer Google Suche knapp 7 Millionen Treffer ergibt und von denen die meisten in einem Glaubenskrieg ausarten.

Ich werde zwar auch C# vs VB.NET ansprechen, jedoch neutral und nüchtern verglichen sowie auf den Titel dieses Streitgespräches bezogen.

Zuerst meine Erfahrungen zu diesem Thema:

Ich habe den Einstieg in die Programmierung mit VBScript (Classic ASP) und ein wenig Javascript gefunden.
Es gab zu dieser Zeit auch die Möglichkeit JScript zu benutzen, um Classic ASP zu entwickeln, jedoch gab es viel weniger Beispielcode dazu im Netz und mir kam die Syntax für einen Anfänger nicht wirklich natürlich und intuitiv vor.

Später machte ich dann neben Visual Basic 6 auch Versuche in PHP (Ja, Jevoha Stefan ;-)).
Desto mehr ich Erfahrungen sammelte und auch mit Sprachen die C ähnliche Syntax aufwiesen, herumexperimentierte, desto mehr wandte sich meine Einstellung das diese Art von Syntax doch nicht so unnatürlich und unintuitiv wirkt.

Im gleichen Zug fand ich dann auch, das die kompaktere Art der Syntax den Code eleganter machte und auch auf das wesentliche reduzierte.

Das waren meine Gründe das ich bei meinem Start in die .NET Welt gleich mit C# losgelegt habe.
Am Anfang war das natürlich eine ziemliche Umstellung und vorallem der Switch, wieder mal VBScript zu schreiben und zurück auf C# komisch.

Bei meinem ersten Arbeitsgeber musste ich dann erzwungenermassen VB.NET entwickeln, weil die bestehende Software darauf basierte.
Am Anfang habe ich mir natürlich ein wenig schwer getan, jedoch sitzte die andere Syntax innerhalb von zwei Wochen schon sehr gut. Das ist natürlich auch meinen Erfahrungen mit VBScript zu verdanken, sodass die Elemente und Konventionen doch nicht so fremd waren.

Mit der Zeit fand ich richtig Gefallen an VB.NET. Wichtig und zugleich interessant war für mich zu dieser Zeit (Da ich immer noch C# präferierte), dass ich privat immer mit C# gearbeitet habe.

Schlussendlich bin ich froh das ich "erzwungenermassen” mit VB.NET arbeiten musste und dabei auch C# nicht aus den Augen verloren habe. Der Horizont wird erweitert und wenn irgendwo mal was in VB.NET steht, versteht man auch was damit gemeint ist.

Auch wegen meiner Erfahrungen denke ich, das es für komplette Anfänger leichter ist mit VB.NET einzusteigen, da die Sprache am Anfang natürlicher und intuitiver erscheint. Nicht ohne Grund, denn der Ursprung von VB.NET wurde genau für diesen Zweck entwickelt, eine einsteigerfreundliche Sprache zu sein.

Nun, das war jetzt meine Situation und meine Einschätzung. Was kann den generell dazu gesagt werden?

Wenn jemand schon Erfahrungen in einer anderen Sprache hat, die auf dem BASIC-Dialekt basiert, wird er es beim Umstieg mit VB.NET sicher bequemer haben.

Schlussendlich ist es (fast) eine reine Geschmacksfrage, was jemand bevorzugt oder auch was ihm besser liegt.

Da VB.NET und C# bis auf das Aussehen der Syntax im Hintergrund genau dasselbe Paket haben und im Moment bis auf ein paar Featureungleichheiten das gleiche leisten, kommt es in den allermeisten Fällen auch nicht darauf an welches Feature jetzt von der zu lernenden Sprache unterstützt wird.

Folgend finden sich noch zwei Verleichsauflistungen von C# und VB.NET:

Ich bin jetzt mal ganz böse und möchte behaupten das es gar nicht so schlecht ist, wenn zuerst – also in der Anfangszeit - mit einer untypisierten und nicht objektorientierten Sprache geübt wird.
So kann man sich ohne grosse Hindernisse und Dinge die Zeit und Wissen benötigen um sie zu verstehen, mit den grundlegenden Dingen der Programmierung beschäftigen, strukturiert. Wenn dies möglichst modular gelernt wird, ist dann auch der Umstieg auf eine objektorientierte Sprache – die ja auch die Konzepte der Strukturen beinhaltet – einfacher und nicht so überladen.

Bei vielen Integrationen wie die von Tools in Visual Studio (bspw. ReSharper) oder der Unterstützung von VB.NET auf Mono hinkt VB.NET hinterher. Dasselbe gilt auch für die Unterstützung der Sprache in anderen IDEs.
Auch ist es so, das die meisten grossen und bekannten Open Source Projekte meistens in C# geschrieben sind.
Und wissentlich ist die Einsicht in fremden Quellcode für das Lernen unabginglich und sehr zu empfehlen.

An verschiedenen Quellen habe ich gelesen, das C# Entwickler auf dem Arbeitsmarkt besser bezahlt werden und das mehr Stellen vorhanden sind, wo C# gefordert wird.
Wieviel da wirklich dran ist, kann ich nur gefühlsmässig einschätzen und würde da zustimmen. Es gibt sicherlich irgendwo noch Statistiken dazu.

C# hat auch den Vorteil, das der Umstieg zu anderen Sprachen die C ähnliche Syntax benutzt, wie bspw. Java, leichter fällt.

Wie sieht es nun mit der Weiterentwicklung und dem Support für VB.NET und C# in der Zukunft aus?

Microsoft will in nächster Zukunft eine Featuregleichheit von C# und VB.NET erreichen, sodass sich die Sprachen featuremässig ebenwürdig sind. Das finde ich eine gute Entwicklung und stärkt die Position von VB.NET als Nummer zwei der Sprachen für das .NET Framework.

Fazit:

Um direkt auf die Titelfrage zu antworten, würde ich sagen: Lernt beide Sprachen, nein, lernt so viele Sprachen wie möglich. Allerdings fokusiert euch auf eine, damit ihr dort sehr gut werdet / bleibt.

Wenn es darum geht mit welcher Frage man anfangen soll, bleibt es schlussendlich dem Geschmack überlassen.
Im jetzigen Stand haben beide Kontrahenten jeweils Features die der andere nicht hat, jedoch sind diese in den meisten Fällen zu vernachlässigen. Das heisst, alle wichtigen Merkmale und Funktionen ist bei beiden vorhanden.
Und das reicht für den Einstieg mehr als aus.

Wichtiger finde ich, das einem späteren Umstieg eigentlicht nichts im Wege steht und das sich die Geschmäcker mit der Zeit auch ändern können.

Expression Studio 3 (e.) – das Komplettpaket für Silverlight-Entwicklung und professionelles Webdesign – ist ab sofort für alle MSDN Premium Subscriber verfügbar

01.08.2009 00:12:31 | Oliver Scheer

Die englische Fassung des brandneuen Expression Studio 3 ist ab sofort für alle Besitzer einer gültigen MSDN Premium Subscription als Download über die MSDN Subscriber Downloads verfügbar. Expression Studio 3 ist die Programmfamilie professioneller Interface-Designwerkzeuge für Silverlight, .NET und das Web.

Die MSDN Premium Subscription wird dadurch erneut aufgewertet denn bisher war das vollständige Expression Studio bis Version 2 nur in Visual Studio Team System Team Suite mit MSDN Premium enthalten – nicht in den anderen Versionen von MSDN Premium (beispielsweise Visual Studio Professional mit MSDN Premium) diese Varianten enthielten bisher nur Expression Web und Expression Blend. Ab sofort ist das gesamte Expression Studio 3 für alle MSDN Premium Subscriber in jeder MSDN Premium Subscription enthalten. Expression Studio 3 enthält Expression Blend, Expression Web, Expression Encoder und Expression Design. Vorläufig ist nur die englische Fassung von Expression Studio 3 verfügbar, die deutsche Version steht voraussichtlich ab Ende September/Anfang Oktober für MSDN Premium Subscriber bereit.

Eine MSDN Subscription ist ein „Rundum-sorglos-Softwareabo“ für Softwareentwickler, Architekten,  Qualitätssicherung, IT-Profis und Support und ist der beste Weg, die Microsoft-Plattform zu lizenzieren – unabhängig davon welche Werkzeuge sie verwenden. Mit MSDN Subscriptions können Sie immer die neuesten Werkzeuge und Technologien einsetzen und bleiben trotzdem immer korrekt, legal und günstig lizenziert. Eine MSDN Subscription bedeutet geringere Kosten und bessere Planbarkeit, zukunftssichere Lizenzierung durch Software Assurance und umfassenden Zugriff auf viele Microsoft-Produkte für Test- und Entwicklungszwecke, üblicherweise bereits vor der offiziellen Veröffentlichung. 

Weiterführende Links:

· Ausführliche Informationen zu MSDN Subscriptions finden Sie hier.

· Ausführliche Informationen zu Expression Studio finden Sie hier.

· Für MSDN Subscriber: Klicken Sie hier, um direkt zu Ihren neuen MSDN Subscriber Downloads mit Expression Studio 3 zu gelangen.

Ihr Ansprechpartner bei Microsoft:

· Ansprechpartner für Handel und Vertrieb ist Gesa Ehmsen: gesae@microsoft.com

· Ansprechpartner für Fragen zu MSDN Subscriptions und Visual Studio Team System
ist Steffen Ritter: steffen.ritter@microsoft.com

· Ansprechpartner für Fragen zu Expression Studio
ist Sebastian Grassl: sebastian.grassl@microsoft.com

Regeln | Impressum