Friday, October 05, 2007

Dynamic Method Performance

In einem interessanten Artikel im MSDN Magazine wird auf unterschiedliche Performance Probleme, im Speziellen im Zusammenhang mit Reflection, eingegangen. Mich interessierte vor allem die gelobte Performance der dynamischen Methoden, die seit der .NET Framework Version 2.0 zur Verfügung stehen. Eine einfache Testanwendung hat gezeigt, dass der Artikel recht behält.
In der Testanwendung wird einem Objekt ein String eine Million mal zugewiesen. Dies zuerst direkt verdrahtet, danach mit dynamischer Methode und zuletzt via Reflection. Das Ergebnis ist eindeutig. Die direkt verdrahtete Methode ist natürlich die Schnellste, die dynamische Methode braucht dafür doppelt so lange (was ich immer noch sehr gut finde) und mittels Reflection dauert es 100mal länger. What a gain!
Übrigens, die Assembly habe ich mit Lutz's Reflector untersucht, um sicher zu stellen, dass die Schlaufe auch wirklich bei allen drei Varianten ausgeführt wird.

Und hier noch der Code:

public class Program
{
private delegate void DemoDelegate(Foo arg);

static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();

Foo f = new Foo();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
f.Text = "Hello World!";
}
stopwatch.Stop();
Console.WriteLine("Direct: {0}", stopwatch.Elapsed);

stopwatch.Reset();

DemoDelegate del = createMethod();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
del(f);
}
stopwatch.Stop();

Console.WriteLine("Dynamic method: {0}", stopwatch.Elapsed);

stopwatch.Reset();

PropertyInfo property = f.GetType().GetProperty("Text");
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
property.SetValue(f, "Hello World!", null);
}
stopwatch.Stop();
Console.WriteLine("Reflection: {0}", stopwatch.Elapsed);


Console.ReadKey();
}

private static DemoDelegate createMethod()
{
Type[] parameterTypes = new Type[] { typeof(Foo) };
DynamicMethod method = new DynamicMethod("Demo", null, parameterTypes, typeof(Program));

ILGenerator iLGenerator = method.GetILGenerator();
iLGenerator.Emit(OpCodes.Ldarg_0);
iLGenerator.Emit(OpCodes.Ldstr, "Hello World!");
MethodInfo setMethod = typeof(Foo).GetProperty("Text").GetSetMethod();
iLGenerator.EmitCall(OpCodes.Call, setMethod, null);
iLGenerator.Emit(OpCodes.Ret);

return (DemoDelegate)method.CreateDelegate(typeof(DemoDelegate));
}
}

public class Foo
{
private string _text;

public string Text
{
get { return _text; }
set { _text = value; }
}
}

Friday, September 14, 2007

Remote Debbuging

Wenn man eine Applikation remote debuggen soll, wird man feststellen, dass verschiedene Punkte beachtet werden müssen, damit das Ziel erreicht wird. Einige hoffentlich nützliche Hinweise möchte ich hiermit weitergeben:

1. Remotedebugging heisst, mit dem lokalen Visual Studio eine laufende Applikation auf einer anderen Maschine, typischerweise einem Server, zu debuggen.
2. Der Applikationscode (dll und pdb Files) muss auf beiden Systemen identisch sein.
3. Auf der Remotemaschine muss der Remote Debugger, im Speziellen das File msvsmon.exe vorhanden sein. Auf der lokalen Maschine muss Visual Studio vorhanden sein.
4. Der lokale Account (unter dem Visual Studio läuft) muss auf dem Remotesystem Administratorrechte haben, damit sich Visual Studio attachen kann.
5. Auf dem Remotesystem muss der Remotedebugger (msvsmon.exe) unter dem lokalen Account (unter demselben wie Visual Studio läuft), gestartet werden (im Contextmenü Run as ... ausführen).
6. In Visual Studio muss unter Tools, Options, Debugging, General die Option ‚Enable just my Code’ inaktiv sein, damit die Symbols geladen werden und Breakepoints gesetzt werden können.
7. In Visual Studio kann nun unter Debug, Attach to Process der Remoteprozess angebunden werden. Dazu Transport: Default und Qualifier: SERVERNAME wählen. Nun den gewünschten Prozess, z. Bsp. W3wp.exe auswählen. Ist der gewünschte Prozess nicht aufgelistet, muss sichergestellt werden, dass die Applikation wirklich läuft. Dazu z. Bsp. Die Webseite aufrufen.
8. Nun wie gewohnt debuggen.

Viel Spass.

http und Textfile

Für einen Kunden sollte ich von einer Webseite (http://.../mytext.php) ein File downloaden und den Text auf einem Server Share speichern. Und so einfach ist das mit .NET 2.0.

// Get stream from any webserver over HTTP response object
WebRequest request = (WebRequest)WebRequest.Create(new Uri("http://.../mytext.php"));
WebResponse response = request.GetResponse();
// create reader to read the stream and save it in a string
StreamReader reader = new StreamReader(response.GetResponseStream());
// write string to a file
File.WriteAllText(@"c:/test.txt", reader.ReadToEnd());
// close objects
reader.Close();
response.Close();

Wednesday, February 14, 2007

Microsoft Expression - Tools for Designer or Developer?

Vier neue Produkte aus dem Hause Microsoft warten auf uns Entwickler... oder doch nicht?

* Microsoft Expression Media (endgültige Version erscheint voraussichtlich Mitte 2007)
Expression Media ist ein Produkt für das Digital Asset Management. Basierend auf der Software iView MediaPro, die im Juni 2006 von Microsoft übernommen wurde, dient es der Katalogisierung und Verarbeitung von Mediendateien wie Grafiken und Videos.

Ich denke nicht, dass dieses Produkt für Entwickler von Interesse ist.


* Microsoft Expression Design (Beta 1 verfügbar, endgültige Version erscheint voraussichtlich Mitte 2007)
Expression Design ist das Bildbearbeitungsprogramm, also der PhotoShop von Microsoft. Das Produkt deckt höchste Anforderungen ab, könnte aber auch einige Entwickler überfordern. Vielleich hält man sich da doch besser ans Paint.NET 3.0 mit dem auch ein Entwickler das gewünschte Resultat erreicht und zudem erst noch der Sourcecode vorliegt (siehe letzte Posts).

Ich denke nicht, dass dieses Produkt für Entwickler von Interesse ist.


* Microsoft Expression Web (bereits verfügbar)
Das aus Microsoft FrontPage hervorgegangene Expression Web ist eine Web-Entwicklungsumgebung die leider nicht alles bietet was man sich wünscht. Ich war total entäuscht von diesem Produkt. Zum Beispiel werden keine Themes und Skins von ASP.NET 2.0 unterstützt aber auch Basics wie ein tabellenloses Layout (mit DIV Tags und CSS) wird nicht unterstützt. Das heisst, der Designer kann's nicht anzeigen und es gibt auch keine Tools, Intellisense, ... um damit zu arbeiten.

Ich denke nicht, dass dieses Produkt für Entwickler von Interesse ist.


* Microsoft Expression Blend (Beta 2 verfügbar, endgültige Version erscheint voraussichtlich Mitte 2007)
Expression Blend ist ein Designwerkzeug für das Erstellen von interaktiven Benutzeroberflächen. Es fungiert als WYSIWYG-Editor für XAML, eine in XML formulierte Sprache zur Beschreibung und Erstellung von Oberflächen der Windows Presentation Foundation (WPF und WPF/E). Vektorgrafiken, Rastergrafiken, 3D-Objekte aus bekannten 3D-Programmen, Videos, Sound und Text lassen sich miteinander vereinen und mit Hilfe einer Zeitleiste animieren.

Ich denke, dass dieses Produkt bis zu einem bestimmten Punkt auch für Entwickler von Interesse ist. Um alle Möglichkeiten auszuschöpfen, sollte es allerdings in die Hände eines Grafikers gelegt werden.

Wednesday, February 07, 2007

UpdatePanel und Validation Controls

Natürlich wollen wir alle das UpdatePanel einsetzen. Speziell wenn wir ein oder mehere GridViews auf der Seite haben, die ein Paging, Sorting und Edit bieten.
Gerade im Edit Fall kommen aber sicher die Validator Controls ins Spiel, die aber leider im UpdatePanel nicht funktionieren.

Das Problem wird gelöst, in dem AJAX-Compatible Validators verwendet werde, die im CTP auch bereits vorhanden waren. Im RTM sind sie aber nicht dabei, sondern ausgelagert in den ASP.NET AJAX January Futures CTP, den man hier downloaden kann.

Wer weder verzichten, noch den CTP einsetzen will, der kann auf den Validater Controls einfach die Property enableclientscript="false" setzen und das Ganze funktioniert. Ein paar Einschränkungen gibt's natürlich. Z.Bsp. showmessagebox="true" auf dem ValidationSummary funktioniert nicht.

Sunday, February 04, 2007

GridView and Formating

Ich will ein Datum im GridView formatieren und es gibt auch eine entsprechende Property. Einfach? Gar nicht! Den die Property will einfach nicht greifen. Nach langem finde ich den Weg der funktioniert, obwohl mir da noch etwas das Verständnis dafür fehlt.
Die Formatierung greift nur, wenn die Property HTMLEncode auf false gesetzt wird.

Das funktionierende Beispiel:







Friday, February 02, 2007

February CTP of WPF/E

Der Dezember Release ist bereits abgelaufen, obwohl dieser bis Ende Februar hätte laufen müssen. Macht nichts, den der Februar Release ist bereits da.

Einige schöne, neue Features sind hinzugekommen. Aber auch einige Änderungen an bestehenden Sachen, so das viele Beispiele nicht mehr laufen.

Mehr Infos gibt's hier.

Wednesday, January 31, 2007

Paint.NET

Auch als Software Entwickler ist ein Grafikprogramm immer wieder von nutzen. Nur soll es nicht so teuer und kompliziert sein wie ein PhotoShop und doch etwas mehr Möglichkeiten bieten als ein Paint.
Definitiv das richtige Tool für den .NET Entwickler ist Paint.NET. Dies ist nicht etwa Paint in .NET programmiert sondern wirklich ein kleiner aber feiner PhotoShop.

Hier geht's zum Produkt. Übrigens, es gibt's sogar den Source Code zum downloaden ;-)

Monday, January 29, 2007

Redirecting to another page

Um von einer zur anderen Seite navigieren zu können, kennen wir heute die unterschiedlichsten Methoden. Mit ASP.NET werden hauptsächlich vier Arten eingesetzt.
- Hyperlinks
- Browser Redirect
- Server Transfer
- Cross-Page Posting

Die Vor- und Nachteile werden hier von Microsoft beschrieben.


Für alle die immer noch eine gewisse Unsicherheit spüren, hier noch ein paar Ergänzungen.

Sofern von der einen zur anderen Seite keine Daten übertragen werden müssen, sollte der Hyperlink verwendet werden. Ausnahme, wenn man die URL 'verstecken' will.

Auf das Redirect wird wenn immer möglich verzichtet, da dies einen zusätzlichen Roundtrip bedeutet.

Wenn Daten ausgetauscht werden müssen, kommen die beiden Möglichkeiten 'Server Transfer' und 'Cross-Page Posting' ins Spiel.
'Cross-Page Posting' ist seit ASP.NET 2.0 möglich und die etwas schönere Variante. Dabei ändert sich die Browserfunktionalität nicht, jedoch muss das Ziel fix verdrahtet werden.
Beim 'Server Transfer' ist ein GoBack im Browser nicht möglich, die dynamische Adressierung jedoch kein Problem.
In der Praxis merkt man aber sehr schnell, dass beide Methoden ihre Berechtiging haben und man am Besten fährt, wenn eine Kombination der beiden Möglichkeiten verwendet wird.

Datenübergabe:
Beim 'Server Transfer' werden die Daten über public Properties übergeben, die auf der aufrufenden Seite implementiert werden. Auf der Zielseite können sie über das Object Context.Handler abgefragt werden.
((PagesClassName)Context.Handler).PropertyName

Beim 'Cross-Page Posting' können die Felder mit FindControl() ausgelesen werden.
((TextBox)((PagesClassName)PreviousPage).FindControl("MyTextBox")))).Text

Diese Methode muss verwendet werden da die Controls protected sind. Aus Performance-Gründen (und OO Sicht) sollte auf diese Methode verzichtet werden. Wenn analog dem 'Server Transfer' mit public Properties gearbeitet wird, lassen sich zudem Schwierigkeiten vermeiden, die beim Einsatz von Masterpages und UserControls entstehen und mit einem zwischenschritt über den ContentPlaceholder gelöst werden müssten.
prePage = (PagesClassName)PreviousPage;
ContentPlaceHolder c = (ContentPlaceHolder)prePage .Master.FindControl("ContentPlaceHolder1");
(((TextBox)(c.FindControl("MyTextBox"))).Text



Wednesday, January 24, 2007

WPF/E for the real world

Ich war sofort begeistert von WPF/E als ich die ersten Beispiel sah. Wenn man aber erst mal einen Tag damit rumgespielt und selber die ersten Demos realister hat kommt plötzlich die Frage: War's das schon?

Im Moment ja, den wichtige Elemente für eine 'richtige' Anwendung fehlen noch. So gibt's nicht einmal eine Textbox, was die Interaktivität schwierig macht.
Das ist natürlich alles bereits angekündigt, wir müssen uns aber noch etwas in Geduld üben.

Wer schon mal einen kleinen Vorgeschmack möchte, soll sich das Beispiel von Tony anschauen. Nice!

Stay tuned, more is coming up.

Tuesday, January 23, 2007

ASP.NET AJAX 1.0 Released

Leider reichte es dazumal mit dem Release nicht auf den Projektstart vom Dezember 2006. Das wir ihn jetzt bereits bekommen haben ist aber sehr erfreulich. Dann wollen wir uns mal ans Update machen.

Den ASP.NET AJAX 1.0 Release gibt's hier. Die Online Doku ist nun auch ganz ordentlich und die Upgrade Whitepaper funktionieren.

Auch vom ASP.NET AJAX Control Toolkit gibt's am selben Ort einen neuen Release. Wie man im Blog von Scott sieht, sind ein paar schöne Controls wie der Calendar Extender dazu gekommen.

Monday, January 22, 2007

Templated Control with Designer Support

Für mein aktuelles Projekt benötigten wir eine schön formatierte Box die einen Titel hat. Statt diese auf jeder Seite x-mal mit Table Tags zu bauen und zu formatieren, wollten wir ein eigenes Control verwenden.

1. Versuch: Erstellen eines einfachen Controls abgeleitet von der Klasse Controls befriedigte unsere Bedürfnisse nur mässig, da zwischen dem Start- und Endtag nur Text verwendet werden konnte. Wir wollten jedoch ASP.NET Controls in der Box platzieren.

[DefaultProperty("Title"), ToolboxData("<{0}:SimpleBox runat=server>")]
public class SimpleBox : Control
{
private string _title;

[Bindable(true), Category("Appearance"), DefaultValue("")]
public string Title
{
get { return _title; }
set { _title = value; }
}

protected override void Render(HtmlTextWriter output)
{
string outputString = string.Empty;

// generate output (html)
outputString = "<table cellspacing="0" cellpadding="0" border="1">"
+ " <tr>"
+ " <td>" + Title + "</td>"
+ " </tr>"
+ " <tr>"
+ " <td>";

// read between the begin and end tag
if ((HasControls()) && (Controls[0] is LiteralControl))
{
outputString += ((LiteralControl)Controls[0]).Text;
}

string outputStringEnd = "</td>"
+ " </tr>"
+ "</table>";

// speak your mind
output.Write(outputString);
}
}


2. Versuch: Erstellen eines Composite Controls
Das war schon besser. Die Controls zwischen Start- und Endtag wurden erkannt und gerendert. Einziges Problem waren die Events der Childcontrols. Diese wurden nicht gefeuert. Könnte man ausprogrammieren, aber...

[DefaultProperty("Title"), ToolboxData("<{0}:ComposedBox runat=server>")]
public class ComposedBox : Control, INamingContainer
{
private string _title;

//[Bindable(true), Category("Appearance"), DefaultValue("")]
public string Title
{
get
{
return _title;
}
set
{
_title = value;
}
}

protected override void CreateChildControls()
{
string outputStringStart = "<table cellspacing="0" cellpadding="0" border="1">"
+ " <tr>"
+ " <td>" + Title + "</td>"
+ " </tr>"
+ " <tr>"
+ " <td>";

string outputStringEnd = "</td>"
+ " </tr>"
+ "</table>
";

this.Controls.AddAt(0, (new LiteralControl(outputStringStart)));
this.Controls.AddAt(this.Controls.Count - 1, (new LiteralControl(outputStringEnd)));
}
}


3. Versuch: Das Templated Control
Hier funktioniert alles auf anhieb, ohne grossen Programmieraufwand. In kurzer Zeit war unser Control erstellt und die formatierte Box stand zur Verfügung. In einer überarbeiteten Variante integrierten wir dann auch noch den fehlenden Designer Support. Great!


public class BoxTemplate : CompositeControl, INamingContainer
{
private String _message = null;
public BoxTemplate() { }
public BoxTemplate(String message)
{
_message = message;
}
public String Message
{
get { return _message; }
set { _message = value; }
}
}

[DefaultProperty("Title"),
ParseChildren(true), PersistChildren(false),
Designer("CSBS.TVCITTool.Client.Web.Controls.TemplatedBoxControlDesigner, CSBS.TVCITTool.Client.Web.Controls"),
ToolboxData("<{0}:TemplatedBox runat=server>")]
public class TemplatedBox : CompositeControl, INamingContainer
{
private string _title;
private ITemplate _messageTemplate = null;
private String _message = null;

public String Message
{
get { return _message; }
set { _message = value; }
}

[Bindable(true), Category("Appearance"), DefaultValue("")]
public string Title
{
get { return _title; }
set { _title = value; }
}

[PersistenceMode(PersistenceMode.InnerProperty), DefaultValue(null), TemplateContainer(typeof(BoxTemplate)),
TemplateInstance(TemplateInstance.Single), Browsable(false)]
public ITemplate MessageTemplate
{
get { return _messageTemplate; }
set { _messageTemplate = value; }
}

public override void DataBind()
{
EnsureChildControls();
base.DataBind();
}

protected override void CreateChildControls()
{
// If a template has been specified, use it to create children.
// Otherwise, create a single literalcontrol with message value

string outputStringStart = "
<table class="boxframe" cellspacing="'\">"
+ " <tbody><tr>"
+ " <td class="boxheader">" + Title + "</td>"
+ " </tr>"
+ " <tr>"
+ " <td>";

string outputStringEnd = "</td>"
+ " </tr>"
+ "</tbody></table>
";

if (MessageTemplate != null)
{
Controls.Clear();
BoxTemplate i = new BoxTemplate(this.Message);
MessageTemplate.InstantiateIn(i);
Controls.Add(i);
}
else
{
this.Controls.Add(new LiteralControl(this.Message));
}

this.Controls.AddAt(0, (new LiteralControl(outputStringStart)));
this.Controls.AddAt(this.Controls.Count, (new LiteralControl(outputStringEnd)));
}
}

public class TemplatedBoxControlDesigner : CompositeControlDesigner
{
private TemplatedBox _designControl;
private TemplateGroupCollection _templateGroupCollection;

public override void Initialize(System.ComponentModel.IComponent component)
{
base.Initialize(component);
_designControl = (TemplatedBox)component;
SetViewFlags(ViewFlags.DesignTimeHtmlRequiresLoadComplete, true);
SetViewFlags(ViewFlags.TemplateEditing, true);
}

public override TemplateGroupCollection TemplateGroups
{
get
{
if (_templateGroupCollection == null)
{
_templateGroupCollection = base.TemplateGroups;
TemplateGroup group;
TemplateDefinition templateDefinition;
group = new TemplateGroup("ContextRowTemplates");
templateDefinition = new TemplateDefinition(this, "MessageTemplate", _designControl, "MessageTemplate", false); //der vierte Parameter ist der Name der Property des Control
group.AddTemplateDefinition(templateDefinition);
_templateGroupCollection.Add(group);
}
return _templateGroupCollection;
}
}
}

Tuesday, January 09, 2007

Passed 70-554

I did it again... und bin nun endlich MCPD.

Hilfen und Links findet ihr in den weiteren Blogs mit dem Label Learning.

Friday, January 05, 2007

WPF/E Code Samples

Es ist noch nicht lange her das wir WPF/E erhalten haben und schon gibt's dutzende Beispiele.
Microsoft hat gleich selber ein Sample Pack erstellt das man hier downloaden kann. Weitere Informationen gibt's auf MSDN WPF/E Dev Center.
Weitere interessante Beispiele inklusive Source Code findet man im Blog von Mike Harsh hier oder hier von Richard Leggett.
Mein technisches Lieblingsbeispiel kommt von Simon, leider ohne Source Code und befindet sich hier.

Friday, December 15, 2006

ASP.NET AJAX 1.0 RC

Und gleich noch der RC von ASP.NET AJAX.
Get it here.

Microsoft Visual Studio 2005 Service Pack 1

Get it here!

Thursday, December 14, 2006

WPF/E CTP available

Endlich ist WPF/E als Community Technologie Priview verfügbar.

Damit man eine WPF/E Anwendung im Browser sehen und erleben kann, muss das Browser Plug-In installiert werden.

Um eine WPF/E Anwendung zu bauen braucht's das WPF/E SDK. Wie man das WPF/E Project Template ohne 'Web Application Projects' installiert und weitere gute Infos gibt's hier.

Die offizielle Microsoft Dokumentation findet man hier. Natürlich haben auch Scott und Mike wie immer gute Posts in ihren Blogs.

Nun geht's los und wir bauen die erste WPF/E Anwendung. Das Resultat und weitere Infos folgen. Have fun!

Wednesday, November 29, 2006

Discount on MCP Certifications

Wer sich heute entschliesst seinen MCAD oder MCSD.NET Titel auf die Version .NET 2.0 upzugraden, der kann das mit 25% Rabatt machen. Mehr Infos dazu gibt's hier (Achtung, Passport required).

Wer MCT ist hat übrigens auf allen MCP Prüfungen einen Rabatt von 45%. Mehr dazu unter https://mcp.microsoft.com/mct/courses_exams/exams_discount.mspx (Achtung, Passport required).

Tuesday, November 14, 2006

Visual Studio 2005 SP1

Das Service Pack 1 für Visual Studio soll noch dieses Jahr, nämlich im Dezember ausgeliefert werden. Die Beta kann weiterhin bei Microsoft herunter geladen werden.

Was darf man vom Service Pack erwarten:
  • The Hotfixes and General Distribution Release Updates released between Visual Studio 2005 Release to Market and the end of the Service Pack customer beta period.
  • Any fixes addressing security issues categorized by the Microsoft Security Response Center as "Critical", "Important" or "Moderate".
  • Fixes for product reliability and stability issues, including those reported by customers via the Product Feedback Center, and the crashes most frequently reported via Watson.
  • Fixes for common "eligible" functional issues reported by customers via the Product Feedback Center. "Eligible" functional issues are those that do not require breaking changes, architectural changes, or Design Change Request level feature work and that do not create unacceptable product quality risk and/or cost of implementation.
  • Fixes for the top customer and supportability issues as reported by Customer Support Services.
Weitere Infos gibt's hier.

Friday, November 03, 2006

Doodle or how to find the right time for a meeting

Wer oft Meetings plannen muss, kennt die Schwierigkeit einen Termin zu finden, der allen Beteiligten passt. Mit www.doodle.ch wird das nun aber etwas einfacher.
Ohne sich anzumelden kann ein Thema eröffnet werden und die zur Auswahl stehenden Daten werden fixiert. Danach kann der resultierende Link an alle Teilnehmer versendet werden, die ihre Verfügbarkeit eintragen können.