.
Anmeldung | Registrieren | Hilfe

.NET-Blogs Archiv Dezember 2010

2010: Schön war es!

31.12.2010 15:57:37 | Thorsten Hans

prosit_neujahr 2010 war in der .NET Community ein erfolgreiches und bewegendes Jahr. Microsoft hat mit der Wave 2010 großes geleistet! Gerade die Integration der verschiedenen Produkte / Technologien stand im Mittelpunkt und wurde mit Bravur abgeliefert. Das wohl beste Beispiel ist und bleibt SharePoint 2010. SharePoint bietet Integration in eine Vielzahl von Microsoft Produkten, ja sogar die Integration von Drittanbieterprogrammen ist dank den BCS problemlos möglich.

Das wichtigste Release hier in der Entwickercommunity ist wohl mit Visual Studio 2010 geschehen. Im Bundle mit dem .NET Framework 4.0 erblickte Microsofts IDE im April offiziell das Licht der Erde und ist seit dem nicht mehr wegzudenken. Letztendlich ist hierbei auch die neue VSX API schuld, denn Sie macht es noch einfacher Visual Studio zu erweitern und an die individuellen Bedürfnisse anzupassen.

Doch auch für mich persönlich war 2010 ein sehr gutes Jahr. Dank meinem Arbeitgeber war es mir in 2010 auch möglich als Speaker auf diversen Konferenzen teilzunehmen. Hierfür ein Dankeschön an die Data One GmbH.

Im Jahr 2010 konnte ich somit 22 Vorträge im .NET Kontext halten. Hierbei waren auch einige Vorträge bei den deutschen UserGroups wie zum Beispiel bei

  • .NET Stammtisch Konstanz Kreuzlingen
  • .NET UserGroup Karlsruhe

Des Weiteren wurde 2010 auch hier in Saarbrücken von mir die .NET UserGroup Saar gegründet, die sich einmal im Monat zu einem UserGroup treffen zusammenfindet.  Auch die Gründung und Ausrichtung der .NET UserGroup Saar wird maßgeblich von DataOne supported, was die Ausrichtung der Meetings relativ einfach macht. Danke auch an dieser Stelle.

 

Hier auf .NET Rocks ist auch viel geschehen in 2010 so habe ich zum Beispiel die beliebte Serie Das MSBuild Universum geschrieben, welche bis heute noch als zentrale Anlaufstelle für MSBuild im Deutschsprachigem Raum gilt. Auch ein Einsteigertutorial zum DI Framework Ninject habe ich 2010 hier published. 93 Artikel wurden in diesem Jahr auf meinem Blog veröffentlicht, welche sich um die verschiedenen alltäglichen Themen im Leben eines .NET Entwicklers drehen.

Auch im Jahr 2011 wird es demnach munter weiter gehen, zunächst werde ich die Artikelserie Mission Qualitätssicherung in SharePoint Projekten fertigstellen, an deren Ende ein schönes Gewinnspiel auf euch wartet. Stand heute sind meine Zielthemen für 2011 die folgenden

  • ASP.NET MVC
  • Windows Identity Foundation
  • SharePoint 2010
  • jQuery

Auch meine Alltime Favs wie MSBuild und IronRuby werden natürlich auch im neuen Jahr weiterhin vertreten sein.

 

Abschließend möchte ich noch einige Blogs auflisten, die meiner Meinung nach in 2010 guten Content gebracht haben

Natürlich lese ich noch viele weitere Blogs, allerdings wollte ich hier einfach mal ein paar auflisten, die für mich persönlich 2010 den ein oder anderen Post geliefert haben, der mir geholfen hat, oder in meinem Gedächtnis geblieben ist.

So genug .NET rocks für 2010, ich wünsche euch allen einen guten Rutsch in 2011 und viel Spaß im neuen Jahr mit den alltäglichen Freuden und Sorgen im Entwicklerleben.

2011

 

PS: Ein großes Dankeschön an meine Frau und meine Tochter die so manchen Abend alleine verbracht haben, wenn ich mal wieder im Dienste der Community unterwegs war.

 

Technorati-Tags: ,,
DotNetKicks-DE Image

Using HM55B Compass Module from Parallax with Arduino and Processing

29.12.2010 20:28:00 | Ozgur Aytekin

In this post, you'll find code samples for using HM55B Compass Module from Parallax with Arduino and Processing.

The Parallax Compass is a dual-axis magnetic field sensor built around the Hitachi HM55B. Parallax makes this compass accessible by providing their surface-mount sensor chip with a 3V onboard voltage regulator and resistor protection in a 0.3 wide 6-pin DIP module. The HM55B is compatible with the BASIC Stamps 5V supply and signal levels. Compass date is read using a simple synchronous serial interface (the BASIC Stamps SHIFTIN and SHIFTOUT commands).


You can buy the Thumb Joystick Module from: http://www.parallax.com/StoreSearchResults/tabid/768/txtSearch/hm55b/List/0/SortField/4/ProductID/98/Default.aspx or http://www.zerko.ch/parallaxshop/robotzubehoer/hm55b-digital-compass.php

Arduino part of this post is based on Arduino Playground sample from http://www.arduino.cc/playground/Main/HM55B

Pin connections are:
Compass Pin 1and Pin 2 => Arduino Pin 10
Compass Pin 3 => Arduino GND
Compass Pin 4 => Arduino Pin 8
Compass Pin 5 => Arduino Pin 9
Compass Pin 6 => Arduino 5V

The Processing code block is getting the miscellaneous (delivered from arduino) values from Serial protocol and using these values for rotating a box in a circle.


Arduino Code (from http://www.arduino.cc/playground/Main/HM55B):
/*
/////////////////////////////////
 Htachi HM55B Compass
 parallax (#)
 
 AUTHOR:   kiilo kiilo@kiilo.org
 License:  http://creativecommons.org/licenses/by-nc-sa/2.5/ch/
 
 http://parallax.com/Store/Microcontrollers/BASICStampModules/tabid/134/txtSearch/hm55b/List/1/ProductID/98/Default.aspx?SortField=ProductName%2cProductName
 http://sage.medienkunst.ch/tiki-index.php?page=HowTo_Arduino_Parallax_HM55B_Kompass
 http://arduino.cc/playground/HM55B
 
 /////////////////////////////////
 */
#include <math.h> // (no semicolon)
//// VARS
byte CLK_pin = 8;
byte EN_pin = 9;
byte DIO_pin = 10;

int X_Data = 0;
int Y_Data = 0;
int angle;

//// FUNCTIONS

void ShiftOut(int Value, int BitsCount) {
  for(int i = BitsCount; i >= 0; i--) {
    digitalWrite(CLK_pin, LOW);
    if ((Value & 1 << i) == ( 1 << i)) {
      digitalWrite(DIO_pin, HIGH);
      //Serial.print("1");
    }
    else {
      digitalWrite(DIO_pin, LOW);
      //Serial.print("0");
    }
    digitalWrite(CLK_pin, HIGH);
    delayMicroseconds(1);
  }
  //Serial.print(" ");
}

int ShiftIn(int BitsCount) {
  int ShiftIn_result;
  ShiftIn_result = 0;
  pinMode(DIO_pin, INPUT);
  for(int i = BitsCount; i >= 0; i--) {
    digitalWrite(CLK_pin, HIGH);
    delayMicroseconds(1);
    if (digitalRead(DIO_pin) == HIGH) {
      ShiftIn_result = (ShiftIn_result << 1) + 1; 
      //Serial.print("x");
    }
    else {
      ShiftIn_result = (ShiftIn_result << 1) + 0;
      //Serial.print("_");
    }
    digitalWrite(CLK_pin, LOW);
    delayMicroseconds(1);
  }
  //Serial.print(":");

  // below is difficult to understand:
  // if bit 11 is Set the value is negative
  // the representation of negative values you
  // have to add B11111000 in the upper Byte of
  // the integer.
  // see: http://en.wikipedia.org/wiki/Two%27s_complement
  if ((ShiftIn_result & 1 << 11) == 1 << 11) {
    ShiftIn_result = (B11111000 << 8) | ShiftIn_result;
  }


  return ShiftIn_result;
}

void HM55B_Reset() {
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B0000, 3);
  digitalWrite(EN_pin, HIGH);
}

void HM55B_StartMeasurementCommand() {
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B1000, 3);
  digitalWrite(EN_pin, HIGH);
}

int HM55B_ReadCommand() {
  int result = 0;
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B1100, 3);
  result = ShiftIn(3);
  return result;
}


void setup() {
  Serial.begin(115200);
  pinMode(EN_pin, OUTPUT);
  pinMode(CLK_pin, OUTPUT);
  pinMode(DIO_pin, INPUT);

  HM55B_Reset();
}

void loop() {
  HM55B_StartMeasurementCommand(); // necessary!!
  delay(40); // the data is 40ms later ready

  Serial.print(HM55B_ReadCommand()); // read data and print Status
  Serial.print(" ");

  X_Data = ShiftIn(11); // Field strength in X
  Y_Data = ShiftIn(11); // and Y direction

  Serial.print(X_Data); // print X strength
  Serial.print(" ");
  Serial.print(Y_Data); // print Y strength
  Serial.print(" ");
  digitalWrite(EN_pin, HIGH); // ok deselect chip
  angle = 180 * (atan2(-1 * Y_Data , X_Data) / M_PI); // angle is atan( -y/x) !!!
  Serial.print(angle); // print angle
  Serial.println("");
  Hm55bCompassModuleProcessingHm55bCompassModuleProcessing
}

Processing Code:
// Author:  Özgür Aytekin - http://ozguraytekin.blogspot.com
// License: http://creativecommons.org/licenses/by-nc-sa/2.5/ch/

// The Processing serial library allows for easily reading and writing data to and
// from external machines.
// It allows two computers to send and receive data and gives you the flexibility
// to communicate with custom microcontroller devices, using them as the input or
// output to Processing programs. 
import processing.serial.*;

// Define variable for receiving data using the communication protocol
Serial serialPort;

// Define variables for storing miscellaneous variables (delivered from arduino)
float hm55bStatus, fieldStrengthInX, fieldStrengthInY, angleRawValue, angleRotateValue = 0;

// Define a variable for storing angle between 0 and 360 degree
float angleDisplayValue = 0;

// Called once when the program is started.
void setup()
{
  // Defines the dimension of the display window in units of pixels.
  // The size() function must be the first line in setup().
  size(640, 480);

  // Specifies the number of frames to be displayed every second.
  // If the processor is not fast enough to maintain the specified rate,
  // it will not be achieved.
  // For example, the function call frameRate(24) will attempt to refresh 24 times a second.
  // It is recommended to set the frame rate within setup().
  // The default rate is 60 frames per second.
  frameRate(24);

  // Gets a list of all available serial ports.
  // Use println() to write the information to the text window.
  println(Serial.list());

  // Class for sending and receiving data using the serial communication protocol.
  // Constructor Serial(parent, name, rate)
  // parent = PApplet: typically use "this", name = String: name of the port (COM1 is the default),
  // rate = int: 115200
  serialPort = new Serial(this, Serial.list()[1], 115200);

  // Sets a specific byte to buffer until before calling serialEvent().
  // Don't generate a serialEvent() until get a newline character
  serialPort.bufferUntil('\n');
}

// Called when data is available.
void serialEvent(Serial serialPort)
{
  // Reads from the port into a buffer of bytes up to and including a particular character.
  // If the character isn't in the buffer, 'null' is returned.
  String inputString = serialPort.readStringUntil('\n');

  if (inputString != null)
  {
    // Removes whitespace characters from the beginning and end of a String.
    // In addition to standard whitespace characters such as space, carriage return,
    // and tab, this function also removes the Unicode "nbsp" character.
    inputString = trim(inputString);

    // The split() function breaks a string into pieces using a character or string as the divider.
    // filling substrings into a float array
    float[] values = float(split(inputString, " "));

    // we are waiting for four elements
    // put the numbers in the values array-variable
    if(values.length >= 4)
    {
      hm55bStatus = values[0];
      fieldStrengthInX  = values[1];
      fieldStrengthInY = values[2];
      angleRawValue = values[3];

      // hm55b is delivering values between 0 and 180 and 0 and -179
      // when the angle value is less than 0, adding 360 to angle
      // is delivering the degree between 0 and 359
      if(angleRawValue >= 0 && angleRawValue <= 180)
      {
        angleDisplayValue = angleRawValue;
      }
      else if(angleRawValue < 0)
      {
        angleDisplayValue = 360 + angleRawValue;
      }
    }
  }
}

// Called directly after setup() and continuously executes the lines of code contained inside
// its block until the program is stopped or noLoop() is called.
// The draw() function is called automatically and should never be called explicitly. 
void draw()
{
  // The background() function sets the color used for the background of the Processing window.
  background(200);
  // Sets the color used to fill shapes.
  fill(153);

  print("angleRawValue: ");
  print(angleRawValue);
  print('\t');
  
  print("angleDisplayValue: ");
  println(angleDisplayValue);

  // Re-maps a number from one range to another.
  angleRotateValue = map(angleRawValue, 0, 359, 0, PI * 2);

  noFill();
  ellipseMode(CENTER);
  ellipse(width/2, height/2, 200, 200);
  ellipse(width/2, height/2, 20, 20);

  text("North", width/2 - 16, 130);
  text("South", width/2 - 16, 360);

  text("West", 180, height/2);
  text("East", 430, height/2);

  // Specifies an amount to displace objects within the display window.
  // The x parameter specifies left/right translation,
  // the y parameter specifies up/down translation,
  // and the z parameter specifies translations toward/away from the screen.
  translate(width/2, height/2);

  // Rotates a shape the amount specified by the angle parameter.
  rotate(angleRotateValue);

  // Draws a rectangle to the screen.
  rect(-6, - 100, 12, 100);

  // Forces the program to stop running for a specified time.
  delay(500);
}

Giza-Blog.de bedankt sich fuer ein super Jahr 2010 und wuenscht ein tolles neues Jahr 2011!

28.12.2010 12:52:46 | Kay Giza

So schnell vergeht ein Jahr, die Weihnachtstage haben wir hinter uns gelassen und das neue Jahr 2011 steht vor der Tür. Ein ereignisreiches Jahr liegt hinter uns, in dem es sehr viel zu berichten gab. Ich möchte mich bei Ihnen für Ihr beständiges Interesse an meinem Blog Giza-Blog.de recht herzlich bedanken sowie für die vielen gemeinsamen Projekte und natürlich auch für Ihre zahlreichen Rückmeldungen und dem daraus resultierenden Dialog. Lesen Sie weiter in diesem Blogartikel, über Giza-Blog.de und Facebook, was die aktuellen beliebtesten Postings auf Giza-Blog.de sind und die Aufklärungsarbeit rund um den Produkt Key 2010 gebracht hat. Einen guten Rutsch ins neue Jahr 2011 wünscht mit diesem Blogposting, Kay Giza... [... mehr in diesem Blogposting auf Giza-Blog.de]

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

Arduino 0022 now available

25.12.2010 10:27:00 | Ozgur Aytekin

Arduino 0022 now available: http://arduino.cc/en/Main/Software.

Includes an SD card library and lots of other fixes and improvements.

ARDUINO 0022 - 2010.12.24

[core / libraries]
* Adding an SD card library based on sdfatlib by Bill Greiman and the
MemoryCard library by Philip Lindsay (follower) for SparkFun.
http://arduino.cc/en/Reference/SD

* Added character manipulation macros (from Wiring): isAlphaNumeric(),
isAlpha(), isAscii(), isWhitespace(), isControl(), isDigit(), isGraph(),
isLowerCase(), isPrintable(), isPunct(), isSpace(), isUpperCase(),
isHexadecimalDigit(), toAscii(), toLowerCase(), toLowerCase().
http://code.google.com/p/arduino/issues/detail?id=418

* Added String.toInt() function.

* Refactoring core to use register-based, not CPU-based, #ifdefs.
Patch by Mark Sproul.
http://code.google.com/p/arduino/issues/detail?id=307
http://code.google.com/p/arduino/issues/detail?id=315
http://code.google.com/p/arduino/issues/detail?id=316
http://code.google.com/p/arduino/issues/detail?id=323
http://code.google.com/p/arduino/issues/detail?id=324
http://code.google.com/p/arduino/issues/detail?id=340

* Modification of serial baud rate calculation to match bootloader and 8U2
firmware at 57600 baud.
http://code.google.com/p/arduino/issues/detail?id=394

* Fixed bug in tone() function.
http://code.google.com/p/arduino/issues/detail?id=361

* Fixed SPI.setClockDivider() function.
http://code.google.com/p/arduino/issues/detail?id=365

* Fixed EEPROM library on Mega 2560.
http://code.google.com/p/arduino/issues/detail?id=381

* Hardware serial receive interrupt optimization.
http://code.google.com/p/arduino/issues/detail?id=391

* Applying the timeout parameter of pulseIn() during measurement of the
pulse, not just while waiting for it.


[environment]
* Fixed problem with copy as html and angle brackets.
http://code.google.com/p/arduino/issues/detail?id=29

* Showing serial port selection dialog if serial port not found on upload.

* Remembering serial monitor window size and line ending selection.
http://code.google.com/p/arduino/issues/detail?id=96
http://code.google.com/p/arduino/issues/detail?id=330

* Replaced oro.jar regular expressions with java.regex ones (patch by
Eberhard Fahle and Christian Maglie).
http://code.google.com/p/arduino/issues/detail?id=171

* Building the user sketch before the core or libraries, so errors appear
faster. Patch by William Westfield and Paul Stoffregen.
http://code.google.com/p/arduino/issues/detail?id=393

* Setting application icon under Windows.

VirtualBox 4.0 binaries are online

23.12.2010 13:04:00 | Ozgur Aytekin

VirtualBox 4.0 released!
Oracle today released VirtualBox 4.0, a new major release. It now has an open architecture using extension packs and the base package is under GPLv2. See the ChangeLog for details.

http://www.virtualbox.org/wiki/Downloads

VirtualBox is a powerful x86 and AMD64/Intel64 virtualization product for enterprise as well as home use. Not only is VirtualBox an extremely feature rich, high performance product for enterprise customers, it is also the only professional solution that is freely available as Open Source Software under the terms of the GNU General Public License (GPL). See "About VirtualBox" for an introduction.

Presently, VirtualBox runs on Windows, Linux, Macintosh and OpenSolaris hosts and supports a large number of guest operating systems including but not limited to Windows (NT 4.0, 2000, XP, Server 2003, Vista, Windows 7), DOS/Windows 3.x, Linux (2.4 and 2.6), Solaris and OpenSolaris, and OpenBSD.

VirtualBox is being actively developed with frequent releases and has an ever growing list of features, supported guest operating systems and platforms it runs on. VirtualBox is a community effort backed by a dedicated company: everyone is encouraged to contribute while Oracle ensures the product always meets professional quality criteria.

Einstieg zur Workflow Foundation 4 : Workflow Extensions

22.12.2010 22:04:00 | Gregor Biswanger

Es gibt nichts schlimmeres wie eine Anwendung oder ein Framework das nicht flexibel genug für Erweiterungen ist. Zum Glück ist es nicht so bei der Workflow Foundation 4. Denn das Framework bietet einige elegante Wege seine gewünschte Logik dazwischen zu klinken. Eines davon ist das Workflow Extension Feature. Hierbei kann eine Instanz mittels Referenzierung an Activities geleitet werden. In den meisten Fällen dient dieses Feature vor allem um den Workflow Hoster mit Events zu erweitern, die dann vom Workflow auf der Code-Ebene auslösen lässt. Das hört sich sehr kompliziert an. Keine Panik! Das folgende Beispiel zeigt „wie“ und „wann“ so etwas umgesetzt wird.

Beispiel: WorkflowExtensionExample

Dazu wird Visual Studio 2010 geöffnet und ein neues Projekt angelegt. Als Template wird unter “Workflow” – “Workflow Console Application” gewählt. Als Name wird “WorkflowExtensionExample” verwendet.

SNAGHTML90d210

Abb. 1 - Neues “Workflow Console Application” Projekt erzeugen.

Workflow deklarieren

Folgende Schritte sollen nun dem Workflow definiert werden:

  1.  
    1. Dem Workflow ein Flowchart Activity setzen.
    2. Dem Flowchart Activity eine Variable Counter mit dem Typ int und einem Default-Wert von 0 setzen.
    3. Dem Flowchart Activity ein Assign Activity hinzufügen. Das Assign Activity soll die Variable Counter jeweils um einen Wert erhöhen (siehe Abb.2).
    4. Dem Flowchart Activity ein Delay Activity hinzufügen und dem Property Duration folgenden Wert setzen:
      TimeSpan.FromSeconds(1)
    5. Gegen Ende alle miteinander von oben nach unten Verknüpfen.

Ist alles korrekt umgesetzt worden sollte es im Designer aussehen wie unter Abb.2 veranschaulicht wird.

image

Abb. 2 – Counter Workflow

Wie beim Blog-Eintrag “Einstieg zur Workflow Foundation 4 : Activity selbst schreiben” gezeigt wurde, werden Daten immer gegen Ende eines laufenden Workflows mittels Dictionary geliefert. Nun besteht allerdings folgendes Szenario: Der Workflow Hoster wird innerhalb der Console gehalten und startet einen endlos laufenden Workflow.

Wie sollte man also auf die Daten vom Workflow kommen? Ganz einfach! Es wird eine Klasse mit Event und einer Methode benötigt. Das Event wird dann von der Code-Ebene abonniert. Von einem selbstgeschriebenen Activity wird dann die Methode aufgerufen die dann das Event mit Daten auslöst. Die Instanz zu dieser Klasse wird dann von der Workflow Runtime geliefert.

Für eine solche Klasse würde der Contract (Interface) wie unter Listing 1 aussehen.

   1:  public interface IWFEventExtension
   2:  {
   3:      event Action<string> SomeDataFromWF;
   4:      void SetData(string value);
   5:  }

Listing 1 – Contract für die spätere Extension-Klasse.

Dann wird eine Klasse mit dem Namen WFEventExtension angelegt, die anschließend den Contract IWFEventExtension zugewiesen bekommt. Die Methode SetData bekommt dann die Implementierung um das Event zu feuern (siehe Listing 2).

   1:  public class WFEventExtension : IWFEventExtension
   2:  {
   3:      public event Action<string> SomeDataFromWF;
   4:          
   5:      public void SetData(string value)
   6:      {
   7:          if (SomeDataFromWF != null)
   8:              SomeDataFromWF(value);
   9:      }
  10:  }

Listing 2 – Die WFEventExtension-Klasse.

In der Program.cs-Datei wird von der WFEventExtension-Klasse eine Instanz erzeugt. Dann wird das SomeDataFromWF-Event abonniert. Wenn das Event ausgelöst wird, soll in dessen Methode die Parameter auf den Bildschirm mittels Console.WriteLine ausgeben. Dann folgt eine Instanz vom WorkflowInvoker. Durch die Methode Extensions.Add kann der Workflow Runtime dann die Instanz vom WFEventExtension überreicht werden. Der Code dazu steht unter Listing 3.

   1:  class Program
   2:  {
   3:      static void Main(string[] args)
   4:      {
   5:          WFEventExtension wfEventExtension = new WFEventExtension();
   6:          wfEventExtension.SomeDataFromWF += wfEventExtension_SomeDataFromWF;
   7:   
   8:          WorkflowInvoker workflowInvoker = new WorkflowInvoker(new Workflow1());
   9:          workflowInvoker.Extensions.Add(wfEventExtension);
  10:          workflowInvoker.Invoke();
  11:   
  12:          Console.ReadLine();
  13:      }
  14:   
  15:      static void wfEventExtension_SomeDataFromWF(string value)
  16:      {
  17:          Console.WriteLine(value);
  18:      }
  19:  }

Listing 3 – Workflow Hoster mit Workflow Extension.

Jetzt wird nur noch ein selbst geschriebenes Activity benötigt, das sich die Instanz von der Workflow Runtime geben lässt.

Dazu wird eine neue Klasse mit dem Namen SetDataToSourceCode angelegt. Als Basisklasse wird die CodeActivity-Klasse verwendet. Der Wert aus dem Workflow soll anschließend über ein InArgument-Property vom Typ String folgen. Um nun auf die Extension-Instanz zu kommen wird auf die Workflow Runtime über den Parameter context.GetExtension zugegriffen. Anschließend wird die Methode SetData mit den Daten aufgerufen. Die Methode feuert später automatisch das Event auf Code-Ebene.

Der Code dazu ist unter Listing 4.

   1:  using System.Activities;
   2:   
   3:  namespace WorkflowExtensionExample
   4:  {
   5:      public class SetDataToSouceCode : CodeActivity
   6:      {
   7:          public InArgument<string> ValueFromVariable { get; set; }
   8:   
   9:          protected override void Execute(CodeActivityContext context)
  10:          {
  11:              IWFEventExtension wfEventExtension = context.GetExtension<IWFEventExtension>();
  12:              wfEventExtension.SetData(ValueFromVariable.Get(context));
  13:          }
  14:      }
  15:  }

Listing 4 – Eigenes SetDataToSourceCode-Activity das auf die Extension zugreift.

Das selbstgeschriebene Activity kann nun dem Workflow hinzugefügt werden. Dazu muss das Projekt komplett gebuildet werden [Strg] + [Shift] + [B]. Dann wird das Activity auch schon in der Toolbox zur Verfügung gestellt. Dieses wird beim 1. Schritt ganz einfach mittels Drag & Drop unter dem Delay Activity hinzugefügt. Beim 2. Schritt werden dann nur noch die Kommunikationsrichtungen zugewiesen. Ganz wichtig ist hierbei das nach der Verarbeitung vom SetDataToSourceCode Activity das Assign Activity wieder aufgerufen wird, um eine Schleife zu bilden (siehe Abb.3).

image

Abb. 3 – Das SetDataToSourceCode Activity wird hinzugefügt.

Jetzt kann wie gewohnt die Anwendung mittels [F5]-Tastendruck ausgeführt werden.

SNAGHTML9f203f

Abb. 4 – Ausgabe des Counters.

Das Beispiel sollte nun vermittelt haben “wie” eine Workflow Extension erzeugt und bereitgestellt wird. Unter Abb.5 wird das komplette Szenario nochmals grafisch abgebildet.

image

Abb. 5 – Das Beispiel im Detail

  1. Eine Instanz der WFEventExtension wird erzeugt und das SomeDataFromWF-Event wird abonniert. Die WFEventExtension Instanz wird der Workflow Runtime mittels Extensions.Add-Methode vom WF Hoster hinzugefügt.
  2. Der Workflow läuft und ruft das SetDataToSourceCode Activity auf.
  3. Das SetDataToSourceCode Activity holt sich von der Workflow Runtime die WFEventExtension Instanz und ruft die SetData-Methode auf. Die SetData-Methode löst auf Code-Ebene das Event aus, worin die Daten vom Workflow enthalten sind.

Using Thumb Joystick Module with Arduino and Processing

22.12.2010 20:06:00 | Ozgur Aytekin

In this post, you find code samples for using a Thumb Joystick Module with Arduino and Processing.

You can buy the Thumb Joystick Module from: http://www.nuelectronics.com/estore/index.php?main_page=product_info&cPath=7&products_id=33



The Arduino code block is reading the Thumb Joystick values from Port A0 and A1 and sending it to Processing using the Serial class.

The Processing code block is getting the X-Axis and Y-Axis values from Serial protocol and using these values for rotating a box.


Arduino code:
// Define Arduino Port A0 as input for X-Axis
#define pinAxisX 0

// Define Arduino Port A1 as input for Y-Axis
#define pinAxisY 1

// Define variables for storing X and Y values
int valueAxisX, valueAxisY = 0;

// The setup() function is called when a sketch starts.
// Use it to initialize variables, pin modes, start using libraries, etc.
// The setup function will only run once, after each powerup or reset of the Arduino board. 
void setup()
{
  // Sets the data rate in bits per second (baud) for serial data transmission.
  Serial.begin(9600);
}

// After creating a setup() function, which initializes and sets the initial values,
// the loop() function does precisely what its name suggests, and loops consecutively,
// allowing your program to change and respond. Use it to actively control the Arduino board. 
void loop()
{
  // Reads the X-Axis value from the specified analog pin and
  // stores in valueAxisX variable
  valueAxisX = analogRead(pinAxisX);
  
  // Prints data to the serial port as human-readable ASCII text.
  Serial.print(valueAxisX);
  Serial.print(",");

  // Reads the Y-Axis value from the specified analog pin and
  // stores in valueAxisY variable
  valueAxisY = analogRead(pinAxisY);
  Serial.println(valueAxisY);

  // Pauses the program for the amount of time (in miliseconds) specified as parameter.
  delay(50);
}

Processing code:
// The Processing serial library allows for easily reading and writing data to and
// from external machines.
// It allows two computers to send and receive data and gives you the flexibility
// to communicate with custom microcontroller devices, using them as the input or
// output to Processing programs. 
import processing.serial.*;

// Define variable for receiving data using the communication protocol
Serial serialPort;

// Define variables for storing x and y angles
float angleX, angleY = 0;

void setup()
{
  // Defines the dimension of the display window in units of pixels.
  // The size() function must be the first line in setup().
  size(640, 480, P3D);

  // Specifies the number of frames to be displayed every second.
  // If the processor is not fast enough to maintain the specified rate,
  // it will not be achieved.
  // For example, the function call frameRate(30) will attempt to refresh 30 times a second.
  // It is recommended to set the frame rate within setup().
  // The default rate is 60 frames per second.
  frameRate(30);

  // Gets a list of all available serial ports.
  // Use println() to write the information to the text window.
  println(Serial.list());

  // Class for sending and receiving data using the serial communication protocol.
  // Constructor Serial(parent, name, rate)
  // parent = PApplet: typically use "this", name = String: name of the port (COM1 is the default),
  // rate = int: 9600 is the default
  serialPort = new Serial(this, Serial.list()[1], 9600);

  // Sets a specific byte to buffer until before calling serialEvent().
  // Don't generate a serialEvent() until get a newline character
  serialPort.bufferUntil('\n');

  // // The background() function sets the color used for the background of the Processing window.
  // background(128);
}

void serialEvent(Serial serialPort)
{
  // Reads from the port into a buffer of bytes up to and including a particular character.
  // If the character isn't in the buffer, 'null' is returned.
  String inputString = serialPort.readStringUntil('\n');

  if (inputString != null)
  {
    // Removes whitespace characters from the beginning and end of a String.
    // In addition to standard whitespace characters such as space, carriage return,
    // and tab, this function also removes the Unicode "nbsp" character.
    inputString = trim(inputString);

    // The split() function breaks a string into pieces using a character or string as the divider.
    // filling substrings into a float array
    float[] values = float(split(inputString, ","));

    // we are waiting for two elements
    // put the numbers in the values array-variable
    if (values.length >= 2)
    {
      // Re-maps a number from one range to another.
      angleX = map(values[0], 0, 1023, 0, PI * 2);
      angleY = map(values[1], 0, 1023, 0, PI * 2);
    }
  }
}

// Called directly after setup() and continuously executes the lines of code contained inside
// its block until the program is stopped or noLoop() is called.
// The draw() function is called automatically and should never be called explicitly. 
void draw()
{
  // The background() function sets the color used for the background of the Processing window.
  background(0);

  // Sets the default ambient light, directional light, falloff, and specular values.
  lights();

  // Specifies an amount to displace objects within the display window.
  // The x parameter specifies left/right translation,
  // the y parameter specifies up/down translation,
  // and the z parameter specifies translations toward/away from the screen.
  translate(width/2, height/2, 0);


  // Rotates a shape around the x-axis the amount specified by the angle parameter.
  rotateX(abs(angleX));

  // Rotates a shape around the y-axis the amount specified by the angle parameter.
  rotateY(abs(angleY));

  // A box is an extruded rectangle. A box with equal dimension on all sides is a cube.
  box(200, 100, 150);

  print("rotateX = ");
  print(angleX);
  print("\t");

  print("rotateY = ");
  println(angleY);
}

Open XML Dateien aufbauen und verändern (Teil 4)

22.12.2010 16:51:13 | Jens Häupel

Formatierte Zellen in Excel:

Um Zellen in Excel formatieren zu können, muss auf ein Stylesheet zurückgegriffen werden. Im Zellenmarkup wird lediglich ein Verweis auf den (Style-) Index des sog. Master Cell Style Records gesetzt, einer Stelle im Stylesheet, an der alle Fäden zusammen laufen und das Format der Zelle definiert wird.

private Cell CreateCellWithNumber(string cellRef, string cellValue, uint styleIndex)
{
Cell c = new Cell();
  c.DataType = CellValues.Number;
  c.CellReference = cellRef;
  c.StyleIndex = styleIndex;
  c.CellValue = new CellValue(cellValue);
return c;
}

Das XML Markup der Zelle könnte danach so aussehen:

<x:c r="B1" s="2" t="n">
  <x:v>42</x:v>
</x:c>

Dieser Master Cell Style Record holt seine Daten aus anderen Bestandteilen des Stylesheets, wie den Abschnitten für Zahlenformate, Rahmen, Zellfüllmuster, Zeichensätze und Formatvorlagen. Die Formatvorlagen verweisen wiederum auf einen Definitionsabschnitt und enthalten Informationen über (in Excel) eingebaute Formate, die nicht explizit definiert werden müssen.

Die Zusammenhänge sind im folgenden Diagramm zu erkennen:

Styles Dependencies full

Wichtig ist, dass einige Beziehungen durch den Index des entsprechenden Eintrags und andere durch dessen ID referenziert werden. Zahlenformate (ebeneso wie Formatvorlagen) sind schon vordefiniert und im Anhang H der Open XML Markup Definition erklärt. Ein Ausschnitt ist hier zu sehen:

40

#,##0.00;[Red](#,##0.00)

45

mm:ss

46

[h]:mm:ss

47

mmss.0

48

##0.0E+

49

@

Wenn man man eine befüllte Excel-Datei mit den Package Explorer (Open XML SDK 2.0 Productivity Tool), oder auch in Visual Studio öffnet, so sieht man diese Zusammenhänge:

Styles und Formats

Das ist nur rein Ausschnitt aus dem gesamten Bild. Mindestens müssen folgende Bestandteile implementiert werden:

  • Zahlenformatedefinitionen (<numFmts …>)
  • Zeichensatzdeinitionen (<fonts …>)
  • Definition der Zellfüllungen (<fills …>)
  • Definition der Umrandungen (yborders …>)
  • Die Zellenformate (<cellXfs…>)
  • Die Formatvorlagen (cellStyles …>) … mind. „Normal“
  • Die Definition der Formatvorlagen (<cellStyleXfs…>)

Wie das dann implementiert wird, erfahren Sie im nächsten Teil.

[Fortsetzung folgt]

Du bekommst mich nicht!

22.12.2010 16:26:00 | Martin Hey

Ich finde ja die Methode Contains auf generischen Listen sehr praktisch. Um so überraschter war ich nun heute, als ich wie selbstverständlich auf eine PointCollection ein Contains aufrufen wollte und mit einer für mich sehr unerwarteten ArgumentException belohnt wurde.

Mein Code ist ganz einfach nachgestellt: Eine PointCollection wird mit 3 Punkten initialisiert, ich hole mir eine Referenz auf den ersten Punkt und verwende dann die Methode Contains, um zu prüfen, ob dieser Punkt in der Liste enthalten ist.
var points = new PointCollection {
new Point(50, 50),
new Point(100, 100),
new Point(150, 150)
};

var point = points[0];

var isInList = points.Contains(point);

Sieht gar nicht so kompliziert aus und sollte eigentlich funktionieren. Aber: PointCollection ist natürlich keine List<Point>, sondern eine PresentationFrameworkCollection<Point>. Trotzdem hätte ich erwartet, dass dieser Typ in der Lage ist, ein enthaltenes Member zu finden.

Abhilfe schafft hier die ExtensionMethod auf IEnumerable mit dem gleichen Namen. Dieser kann als zweiter Parameter ein Comparer übergeben werden. Das bedeutet natürlich zusätzlichen Aufwand - auch wenn dieser hier sehr marginal ist. Aber warum das Rad neu erfinden. Es gibt ja bereits einen Default-Comparer der genau diese Arbeit übernehmen kann. Dazu übergibt man der ExtensionMethod einfach im zweiten Parameter den Wert null.
var points = new PointCollection {
new Point(50, 50),
new Point(100, 100),
new Point(150, 150)
};

var point = new Point(50, 50);

var isInList = points.Contains(point, null);

Keine Fehlermeldung mehr und das Ergebnis stimmt auch.

Kostenlos: MSDN TechTalk rund um Windows 7 Anfang Februar

22.12.2010 14:06:25 | Peter Kirchner

Der MSDN TechTalk startet im neuen Jahr auf eine Tour durch fünf deutsche Städte: Von 31. Januar bis 7. Februar 2011 können sich Interessierte kostenlos über die vielen Möglichkeiten von Windows 7 für Entwickler informieren. Unter dem Titel "Clever unterwegs mit Windows 7!" lernen Teilnehmer nicht nur die typischen neuen Features des Betriebssystems wie Taskbar, Bibliotheken oder Multitouch kennen, sondern erfahren vor allem, wie diese ansprechend eingesetzt werden können.

Peter Kirchner zeigt unter anderem wie intelligentes Energie- und Netzwerkmanagement anprogrammiert werden kann, wie man die Windows-Suche in eigene Anwendungen einbindet und wie die Trigger Start Services dabei helfen, vorhandene Ressourcen zu schonen. Vorgestellt werden außerdem viele interessante Möglichkeiten, um Anwendungen besser ins Betriebssystem zu integrieren, und auch das Thema „moderne Benutzeroberflächen“ und der Einsatz von Multifunktionsleisten bleiben nicht außen vor. Häufig reichen dabei schon ein paar Zeilen Code, um vorhandene Windows-Funktionen clever und gewinnbringend einzusetzen. In diesen fünf Städten macht der MSDN TechTalk im neuen Jahr Halt:

Termine:

  • 31.01.2011: Hamburg
  • 01.02.2011: Dresden
  • 02.02.2011: München
  • 03.02.2011: Karlsruhe
  • 07.02.2011: Köln

Anmeldung: http://www.microsoft.com/germany/msdn/techtalk/CleverUnterwegsMitWindows7.mspx

Einstieg zur Workflow Foundation 4 : Das Flowchart Activity

21.12.2010 20:02:17 | Gregor Biswanger

Mit dem Sequence Activity werden die enthaltenen Activities strukturiert durchlaufen. So wie man es bei einem Programmablauf gewohnt ist. Die Ansicht zeigt sich somit Technisch und es lässt sich unangenehm lesen. Für einen etwas besseren Überblick und einem flexibleren Ablauf der Activites behilft das Flowchart Activity.

Die Vorteile vom Flowchart Activity auf einem Blick:

  • Activities können frei positioniert werden.
  • Der Verarbeitungsprozess der Activities untereinander kann flexibel definiert werden. Dabei ist es vergleichbar mit der GOTO-Anweisung, wobei beim Flowchart Activity eine bessere Übersicht beibehalten wird.
  • Das Flowchart Activity richtet sich auf eine eher fachliche Abbildung aus und soll somit für Stake Holder als “Common Language” dienen.
  • Für das Flowchart Activity werden weitere Activities zur Überprüfung von Statusinformationen bereitgestellt. Diese lehnen sich an bekannte Programmablauf-Bausteine an.

 

Obwohl das Flowchart Activity sehr mächtig für die Workflow Foundation 4 ist, zeigt sich der Designer noch nicht ganz ausgereift. Das allerdings keinesfalls als Warnung vor der Verwendung der WF4 bedeuten soll. Es dient lediglich nur als Erfahrungsbericht und kann sich bei neuen Versionen der WF verbessern.

Folgende Punkte störten bei der Verwendung in der Praxis:

  • Es können nicht mehrere Activities gleichzeitig verschoben werden.
  • Es fehlt eine Ausrichtungsunterstützung
  • FlowDecisions können nicht benannt werden. Nur True- und False-Felder.
  • Felder mit frei definierbarem Text werden nur mit einer stark eingeschränkten Zeichenlänge dargestellt.

Wie bereits geschrieben wird sich das bestimmt mit den Folgeversionen ändern.

 

Beispiel: WorkflowFlowchartExample

Dazu wird Visual Studio 2010 geöffnet und ein neues Projekt angelegt. Als Template wird unter “Workflow” – “Workflow Console Application” gewählt. Als Name wird “WorkflowFlowchartExample” verwendet.

 

SNAGHTML20af90

Abb. 1 - Neues “Workflow Console Application” Projekt erzeugen.

 

Mit Flow bestücken

Für das Flowchart Activity wird ein eigenständiger Bereich mit “Flowchart” bereitgestellt. Hier sind auch weitere Activities für die Arbeit mit dem Flowchart enthalten. Zu Beginn wird das Flowchart Activity auf den Designer mittels Drag & Drop platziert. Ein Flowchart zeichnet sich zudem jeweils mit einem Start-Point aus. Wobei sofort ersichtlich wird, an welcher Stelle der Code ausgeführt wird.

 

image

Abb. 2 – Flowchart gesetzt.

 

Beim nächsten Schritt wird dem Flowchart eine Integer-Variable mit dem Namen Count zugewiesen.

 

image

Abb.3 – Variable Count für den Flowchart setzen.

 

Nun wird direkt unter dem Start-Point ein WriteLine Activity gesetzt. Wobei der Wert der Count-Variable auf dem dem Bildschirm angezeigt werden soll. Dazu wird mittels VB Expression Count.ToString geschrieben.

 

image

Abb. 4 – WriteLine Activity mit Expression gesetzt.

 

Das besondere am Flowchart Activity ist die freie Definition des Prozessablaufes. Daher muss explizit definiert werden, das direkt beim Starten des Workflows mit dem WriteLine Activity begonnen wird.

Dazu einfach mit dem Mauszeiger über den Start-Point. Es erscheinen dann kleine Boxen die mittels gedrückter Maustaste eine Linie mitgibt. Diese Linie wird beim gewünschten Activity gezogen und die Maus an dessen kleinen Box losgelassen.

image

Abb. 5 – Prozessablauf selbst bestimmen.

 

Durch kleine Pfeile gekennzeichnet, wird ersichtlich in welche Richtung der Kommunikationsfluss abläuft. Als nächster Schritt soll die Counter-Variable um einen Wert erhöht werden. Dazu dient das Assign Activity, das direkt unter dem WriteLine Activity gesetzt wird. Als Expression wird angegeben das der Variable Count um einen Wert erhöht wird (Siehe Abb.6).

 

image

Abb. 6 – Count-Variable soll mit einem Wert erhöht werden.

 

Anschließend muss vom WriteLine Activity die Assign Activity als nächster Prozessschritt definiert werden. Dazu einfach wieder mittels Linie verknüpfen.

Als nächstes wird ein Delay Activity direkt unter dem Assign Activity gesetzt und verknüpft. Das Property Duration erhält eine Expression von 00:00:01. Somit wird eine Sekunde lang der Workflow angehalten.

 

 

image

Abb. 7 – Delay Activity wird auf eine Sekunde gesetzt.

 

Um ein weiteres Activity aus dem Bereich Flowchart kennenzulernen, wird das FlowDecision Activity direkt unter dem Delay Activity gesetzt.

Das FlowDecision Activity steht für die Klassische Abbildung von IF-Abfragen. Die Erwartung wird unter dem Property Condition gesetzt. In diesem Beispiel wird abgefragt ob der Count bereits bei 10 angekommen ist, falls nicht soll direkt beim WriteLine Activity von vorne begonnen werden. Dazu kann man ganz einfach die Kommunikationslinie nach oben ziehen und setzten.

Dass dieser Verarbeitungsprozess frei definiert werden kann ist eine große Stärke vom Flowchart Activity.

 

image

Abb. 8 – FlowDecision mit Abfrage vom Count-Wert.

 

Jetzt kann wie gewohnt die Anwendung mittels [Strg] + [F5]-Tastendruck ausgeführt werden.

 

SNAGHTML36d79a

Abb. 9 – Ausgabe der Verarbeitung vom Flowchart Activity.

 

Dieses Beispiel hat keine ernsthafte Business-Logik abgebildet die mit der Workflow Foundation gehandhabt werden sollte. Das Beispiel sollte einfach die Handhabung und Stärken des Flowchart Activity näher gebracht haben.

Visual Studio “Fonts and Colors” Settings für Razor ViewEngine

21.12.2010 16:39:00 | Alexander Zeitler

Für die ASP.NET Razor ViewEngine Views gibt es in Visual Studio zwei Settings, die für das Farbschema in Visual Studio relevant sind:

  • HTML Server-Side-Script
    formatiert den @ und das <text>-Tag

  • Razor Code
    formatiert alles nach dem @ – wobei nur die Hintergrundfarbe geändert werden kann.
    Die Vordergrundfarbe wird aus den entsprechenden HTML-Schema-Settings übernommen.
    Methodennamen etc. werden gemäß “Plain Text”-Einstellungen formatiert
DotNetKicks-DE Image

Einstieg leicht gemacht mit SQL Server 2008 R2 und SharePoint 2010!

21.12.2010 15:54:08 | Oliver Scheer

Microsoft Platform Ready ist die neue Plattform für Softwarehersteller weltweit, auf der zu aktuellen Microsoft-Technologien, Ressourcen, Veranstaltungen, Kompatibilitätstests, Vertriebs- und Marketingunterstützung zusammengefasst werden.

In Deutschland bieten wir Ihnen im Frühjahr 2011 vier neue Veranstaltungen zu den Themen SQL Server 2008 R2 und SharePoint 2010 an. Und damit Sie auch die Informationen erhalten, die Sie in Ihrer Rolle in Ihrem Unternehmen benötigen, haben wir die Veranstaltungen aufgeteilt in Briefings für Geschäftsführer und IT-Leiter sowie in Camps für technische Leiter sowie Entwickler.

Für weitere Informationen, Agenda und zur Anmeldung folgen Sie den einzelnen Links:



Neue Workshop-Termine für Frühjahr 2011!

21.12.2010 14:08:30 | Peter Kirchner

Noch rechtzeitig im alten Jahr können wir Ihnen unsere neuen Workshop-Termine für das kommende Frühjahr mitteilen. Bereits im aktuellen Halbjahr hatten wir diverse Veranstaltungen im Rahmen von Microsoft Platform Ready zum SQL Server 2008 R2, SharePoint 2010, Windows 7 und Windows Server 2008 R2 anbieten können. Das Feedback war überaus positiv und wir haben natürlich Wünsche, Themenvorschläge und Feedback in die neuen Workshops integriert.

SQL Server 2008 R2


Der SQL Server 2008 R2 ist die neueste Version des SQL Servers und stellt die Grundlage für eine Mission Critical Plattform sowie Business Intelligence (BI) dar. Mit dem neuen Release hat sich vor allem im Bereich Business Intelligence einiges getan – großer Schwerpunkt liegt in diesem Release auf der Verbesserung der Funktionen rund um das Thema Self Service BI. Self-Service-Business Intelligence eröffnet Fachbereichen die Möglichkeit, aus verschiedenen Datenquellen mithilfe der vertrauten Office-Oberflächen eigene Berichte zu erstellen und diese über Microsoft SharePoint Server im Intranet beziehungsweise Internet zu teilen. Die IT-Abteilung behält jederzeit die Kontrolle über die Daten.

Briefing zu neuen Geschäftspotentialen für Entscheider am 09.02.2011 in Köln

  • Überblick über SQL Server 2008 R2
  • Was habe ich als Partner vom Microsoft SQL Server?
    • Leistungsfähigkeit, technisches Potential, Kosten-Nutzen-Verhältnis
  • Was habe ich als Partner speziell von der R2-Version?
    • Project Gemini, Reporting Services, Master Data Services, Stream Insight
  • Neues Business durch Migration auf den SQL Server 2008 R2
  • Worauf sollte ich den Kunden hinweisen?
    • Die richtige Erwartungshaltung beim Kunden herstellen
  • Know-How-Bedarf und Deckung beim Partner
    • Welches Know-How Ihre Entwickler aufbauen sollten

Zum Briefing anmelden...

Entwickler-Camp für technischen Einstieg am 14.03.2011 in Unterschleißheim

  • Die SQL Server 2008- und 2008 R2-Plattform
  • Die Editionen vom SQL Server im Überblick
    • Von SQL Compact bis SQL Azure
  • Spezielle Funktionen von SQL Server 2008 R2
    • Project Gemini, Reporting Services, Master Data Services, Stream Insight
  • Welche Vorteile bietet der SQL Server 2008 für Partner?
  • Ablöseszenarien von anderen Herstellern
    • Warum und wie es funktioniert!
  • Migrationsaspekte zum SQL Server 2008 R2
    • Was sollten Entwickler beachten?
    • Worauf sollten Sie Ihre Kunden hinweisen?

Zum Camp anmelden...


SharePoint 2010


Microsoft SharePoint 2010 ist die Business Plattform für Zusammenarbeit im Unternehmen und im Web. SharePoint 2010 ermöglicht es Ihnen einfach in Teams zusammen zu arbeiten. Kollegen, Partner und Kunden können auf neue und effektive Weise Informationen einfach austauschen. Zudem können sie durch die einheitliche Infrastruktur von SharePoint 2010 erheblich Kosten senken und schnell auf Business Anforderungen reagieren. Bei der Verwendung von SharePoint 2010 helfen Ihnen viele neue Funktionen und die verstärkte Integration in die neuen Office 2010-Anwendungen. Neu in SharePoint 2010 integrierte Suchtechnologien machen das Auffinden von Informationen und Personen leichter und das steigert die Produktivität der Anwender.

Briefing zu neuen Geschäftspotentialen für Entscheider am 07.02.2011 in Unterschleißheim

  • Potenziale für Partner durch SharePoint 2010 und Office 365
  • Integration von SharePoint in Partnerlösungen
    • Grundlagen, Vertrieb und Integration mit Visio
  • Integrationsszenarien SharePoint inhouse und Office 365 – Vorteile für Kunden
  • Technische Abgrenzung: wo macht SharePoint in Partnerlösungen Sinn?
  • SharePoint 2010 – eine durchgehende Entwicklerstory für Partner
    • Welches Know-How Ihre Entwickler aufbauen sollten
    • VS 2010, Sandboxed Solutions, Developer Dashboard, Office Integration/Entwicklung

Zum Briefing anmelden...

Entwickler-Camp für technischen Einstieg am 08.03.2011 in Köln

  • Ein technischer Überblick über SharePoint 2010
  • Die Neuerungen in SharePoint 2010 für Entwickler
    • Ribbons, Client Object Model, Silverlight, Workflows
  • SharePoint 2010 in der Cloud mit Office 365
    • Die neue Plattform für SharePoint-Lösungen
  • SharePoint 2010 – eine durchgehende Entwicklerstory für Partner
    • VS 2010, Sandboxed Solutions, Developer Dashboard, Office Integration/Entwicklung, Visio
  • 1-2-3: SharePoint beim Partner
    • Ein Fahrplan für den Wissensaufbau: was sollte man wissen und wo informieren?

Zum Camp anmelden...

Zwei neue SQL Server-Bücher

21.12.2010 13:24:00 | Jörg Neumann

Pünktlich zu Weihnachten erscheinen gleich zwei neue SQL Server-Bücher, an denen ich mitgewirkt habe.

Bei Microsoft Press: “Microsoft SQL Server 2008 R2 - Das Entwicklerbuch” (zusammen mit zusammen mit Georg Urban, Klaus Löffelmann und Alexander Köller)

CoverMSPress

und bei Galileo Press die 4. Auflage von “SQL Server 2008 R2 - Das Programmierhandbuch” (zusammen mit Dirk Mertins und Andreas Kühnel):

CoverGalileo

Welche Demos wollt ihr sehen? Fordert mich heraus!

21.12.2010 11:54:51 | Oliver Scheer

Ja ist den schon Weihnachten ? Ja … Ich möchte die Entwickler beschenken.
Aber nicht nur vor Weihnachten, sondern das ganze nächste Jahr.

Und deshalb frag ich Euch:

Welche Demos im Bereich Windows 7 (Desktop) und Silverlight würdet ihr gerne sehen?

Welche Themen in diesen Bereichen interessiert euch am meisten?

Was wolltet ihr schon immer mal wissen, aber habt euch nicht getraut zu fragen?

Beispiel gefällig?

- Wie kann man eigentlich aus seiner eigenen Anwendung einen Screenshot vom Desktop erstellen und manipulieren?

- Wie kann ein Fenster in Windows designen, das einen ganz eigenen Rahmen hat und nicht den von Windows benutzt?

- Wie kann ich meine Gitarre mit Hilfe von Windows stimmen?

Egal welche Ideen ihr habt, her damit. Ich werde diese sammeln und abarbeiten und mit Code und Video hier in meinem Blog zur Verfügung stellen.

Viel Spaß beim Ausdenken von Herausforderungen an mich.
Oliver



Frisch aus der Druckerpresse: Entwickeln für Windows Phone 7

21.12.2010 10:26:38 | Oliver Scheer

Ich hab es schon gelesen und tatsächlich noch was gelernt.

Aus der offiziellen Produktbeschreibung:

“Mit Windows Phone 7 wagt Microsoft einen Neustart auf dem Smartphone-Markt. Das neue Betriebssystem unterscheidet sich nicht nur in der Bedienung stark vom Vorgänger Windows Mobile 6.5, sondern auch bei der Entwicklung gilt es, viele Neuerungen zu beachten. Neben dem Einsatz von XNA und Silverlight spielt der Windows Phone Marketplace eine wichtige Rolle. Anwendungen können ausschließlich von dieser zentralen Stelle aus vertrieben werden. Dieses Buch zeigt Ihnen, wie Sie attraktive Anwendungen und Spiele für Windows Phone 7 erstellen und diese auf dem Marketplace bereitstellen. Auch die Migration bestehender XNA-Spiele und Silverlight- oder Windows Mobile-Anwendungen wird behandelt.

Lesen Sie:
- Windows Phone 7: Betriebssystem, Funktionen, Architektur
- Erstellen mobiler Anwendungen mit Silverlight
- Erstellen von Spielen mit XNA Gamestudio 4.0
- Arbeiten mit plattformspezifischen APIs
- Arbeiten mit Netzwerken
- Logging und Unit Tests mit Windows Phone 7
- Bereitstellen von Anwendungen auf Windows Phone Marketplace
- Migration von Spielen und Anwendungen “

image

Link



Internet Explorer cached jQuery $.ajax-Methoden Results - Abhilfe

21.12.2010 10:12:00 | Alexander Zeitler

Verwendet man die jQuery $.ajax-Methode, wie z.B. hier beschrieben, kann es vorkommen, dass der Internet Explorer (aber auch andere Browser je nach Einstellungen) die Ergebnisse des aufgerufenen ASP.NET MVC Controllers cached.

function readdata() {
	$.ajax(
    					{
    					type: "GET",
    					url: "Home/ReadData",
    					dataType: "html",
    					success: function (result) {
    						var listdata = $('#listdata').val();
    						$('#listdata').html(listdata + '\r\n' + result);
    					},
    					error: function (error) {
    						alert(error);
    					}

    					});

}

Abhilfe kann man leicht schaffen, indem man den Parameter "cache" verwendet und explizit auf "false" setzt:

function readdata() {
	$.ajax(
    					{
    					type: "GET",
    					url: "Home/ReadData",
    					dataType: "html",
    					cache: false,
    					success: function (result) {
    						var listdata = $('#listdata').val();
    						$('#listdata').html(listdata + '\r\n' + result);
    					},
    					error: function (error) {
    						alert(error);
    					}

    					});

}
DotNetKicks-DE Image

Tools, Demos und Add-Ins für Visual Studio in der Visual Studio Gallery

21.12.2010 09:39:57 | Oliver Scheer

Wer auf der Suche nach Erweiterungen für Visual Studio ist, oder vielleicht spannende Inspirationen für eigene Projekte sucht, der findet auf unserer Visual Studio Gallery sehr viele kostenfreie und kostenpflichtige Tools mit denen man Visual Studio und seine eigenen Projekte erweitern kann.

Link: http://visualstudiogallery.msdn.microsoft.com/de-de/

 

image



Ach, hätte es Word doch schon zur Gründung der Vereinigten Staaten von Amerika gegeben

21.12.2010 09:23:46 | Oliver Scheer

Dann wäre alles viel leicht gewesen Zwinkerndes Smiley



8-Bit Weihnachtslieder

21.12.2010 09:20:58 | Oliver Scheer

Von wegen Weihnachten ist kitschig, bedächtig und langweilig. Mit der richtigen Musik wird es schon … richtig fetzig Zwinkerndes Smiley

image

8-Bit-Sound-Weihnachtsliederplayer



IronPython bei der #NOUG - Quellen meines Spontan Vortrages

21.12.2010 08:29:07 | Rainer Schuster

IronPython

Allgemeine Info und gute Dokumentation

SLIDES von Rainer Stropek, die den Inhalt ungefähr wieder geben:

Python-Hosting:

Buch über DLR:

Contributors / Leadership:

OpenSource Announcement:

Extensions:

Rx

Rx-Wiki:

Hands-On-Lab:

Forum:

Rx für WP7 (MSDN Dokumentation):

Rx in .NET 4.0 (MSDN Dokumentation):

 

MVVM Framework mit Rx:

Channel 9:

DotNetKicks-DE Image

Folien vom ISV Camp für Windows 7 & Windows Server 2008 R2

20.12.2010 14:47:08 | Peter Kirchner

Vielen Dank noch einmal an alle Teilnehmer, die am 09.12.2010 in Köln beim ISV Camp für Windows 7 und Windows Server 2008 R2 dabei waren. Die Diskussionen waren wie immer spannend und aufschlussreich.

Die Folien vom Event habe ich auf mein SkyDrive gelegt und können jetzt heruntergeladen werden: Download Folien Windows 7 & Windows Server 2008 R2

Im Rahmen von Microsoft Partner Ready werden wir auch im kommenden Jahr wieder Veranstaltungen anbieten. Wir werden Sie dazu auf MPR selbst und natürlich auch in diesem Blog informieren.

(m)Ein EA Versuch

20.12.2010 10:23:00 | Jan Christian Selke

Im Zuge meiner ersten Gehversuche mit dem MVVM Light Framework von Laurant Bugnion, habe ich festgestellt, dass ich mit dem EventAggregator (EA) nicht ganz warm werde. Das hat sich zwar mittlerweile etwas relativiert (Hast Recht, André ;-)), jetzt bin ich vor Kurzem auf eine neue Implementierung eines EA von Glenn Block gestoßen. Diese Implementierung basiert auf dem in StoryTeller genutzten EA von Jeremy D Miller.

Alles in allem fand ich diese Version schon sehr spannend: Der EA nutzt WeakRefences, extrahiert selbst aus einem registrierten Objekt die notwendigen Events und entfernt sie auch so wieder…

Letztlich habe ich (in meinen Augen) ein bisschen cherry picking betrieben. Aus den verschiedenen Varianten habe ich versucht, mir einen eigenen “maßgeschneiderten” EA zu erstellen.

Im folgenden das vorläufige Ergebnis:

public class EventAggregator : IEventAggregator
{
private readonly Dictionary<Type, List<WeakReference>> _eventSubscriberLists = new Dictionary<Type, List<WeakReference>>();
private readonly SynchronizationContext _context;
private object _lock = new object();

public EventAggregator(SynchronizationContext context)
{
_context = context;
}

public void Subscribe(object subscriber)
{
Lock(() =>
{
var subscriptionTypes = subscriber.DissectSubscriptionTypes();
subscriptionTypes.Select(SubscribersFor).Each(referenceList =>referenceList.Add(new WeakReference(subscriber)));
});
}

public void RemoveSubscription(object subscriber)
{
Lock(() =>
{
var subscriberTypes = subscriber.DissectSubscriptionTypes();
subscriberTypes.Select(SubscribersFor).Each(referenceList => referenceList
.ForEach(weakReference =>
{
if (weakReference.Target == subscriber)
referenceList.Remove(weakReference);
}));
});
}

public void Publish<T>() where T : class, new()
{
Publish(new T());
}

public void Publish<T>(T eventToPublish) where T : class
{
var subscribersToRemove = new List<WeakReference>();
SubscribersFor(eventToPublish.ToClosedSubscriber<T>()).ForEach(weakSubscriber =>
{
if (!weakSubscriber.IsAlive)
{
subscribersToRemove.Add(weakSubscriber);
}
else
{
PublishingAction(() => weakSubscriber.AsSubscriber<T>().Handle(eventToPublish));
}
});

if (subscribersToRemove.Any())
{
Lock(() => subscribersToRemove.ForEach(removableReference =>
SubscribersFor(referenceList.Target.ToClosedSubscriber<T>()).Remove(removableReference)));
}
}

private void PublishingAction(Action action)
{
_context.Post(s => action(), null);
}

private List<WeakReference> SubscribersFor(Type subscriberType)
{
List<WeakReference> subscribers = null;
Lock(() =>
{
var found = _eventSubscriberLists.TryGetValue(subscriberType, out subscribers);
if (!found)
{
subscribers = new List<WeakReference>();
_eventSubscriberLists.Add(subscriberType, subscribers);
}
});

return subscribers;
}

private void Lock(Action action)
{
lock (_lock)
{
action();
}
}
}

Mir gefiel der Registrierungsansatz mit einem TypeInterceptor besonders sehr gut. Da ich ohnehin meist mit einem IoC Container arbeite, ist eine solche Verwendung naheliegend.

Also findet die Registrierung der Objekte nicht durch das Anmelden von sich selbst statt, wie in den Beispielen von MVVM Light oder dem EA Beispiel von Glenn Block, sondern mittels eines TypeInterceptors.

public class SubscriptionInterceptor : StructureMap.Interceptors.TypeInterceptor
{
public object Process(object target, IContext context)
{
context.GetInstance<IEventAggregator>().Subscribe((target));
return target;
}

public bool MatchesType(Type type)
{
return type.ImplementsInterfaceTemplate(typeof(ISubscribe<>));
}
}

Mal sehen, wie es weiter geht…

Mission Qualitätssicherung in SharePoint Projekten – Testen von SharePoint mit Typemock Part 5

20.12.2010 09:31:13 | Thorsten Hans

Im fünften Teil der Serie “Mission Qualitätssicherung in SharePoint Projekten” geht es um das SharePoint spezifische Konstrukt  SPSecurity.RunWithElevatedPrivileges.

Durch den Einsatz von SPSecurity.RunWithElevatedPrivileges kann sichergestellt werden, dass der darin eingebettete Code im Kontext des Systemkontos ausgeführt wird. Typemock bietet auch für dieses Szenario eine einfache und gute Lösung um in den Tests festzustellen, ob SPSecurity.RunWithElevatedPrivileges ausgeführt wird.

 

Schaut man sich die Klasse SPSecurity an, so sieht man, dass die Klasse über einen statischen Konstruktor verfügt. Diesen Konstruktor verwendet Typemock auch als Hook um RunWithElevatedPrivileges zu faken.

Durch die Verwendung von WhenCalled wird dann noch die original Logik durch einen IgnoreCall oder einen beliebigen Delegaten ausgetauscht. Schlussendlich wird durch Isolate.Verify sichergestellt, das der Call auch im Code vollzogen wird.

Eine konkrete Testimplementierung könnte demnach wie folgt aussehen.

 

   1:  [Test,Isolated]
   2:  public void Logic_Should_Be_Executed_Within_SPSecurity_RunWithElevatedPrivileges()
   3:  {
   4:      String sampleKey = "anyKey";
   5:      String sampleValue = "anyValue";
   6:   
   7:      // Alle verwendeten Typen faken
   8:      var site = Isolate.Fake.Instance<SPSite>();
   9:      var web = Isolate.Fake.Instance<SPWeb>();
  10:      Isolate.Fake.StaticConstructor(typeof(SPSecurity));
  11:   
  12:      Isolate.WhenCalled(() =>
  13:          SPSecurity.RunWithElevatedPrivileges(() => { }))
  14:          .IgnoreCall();
  15:      var sut = new WebPropertyService();
  16:   
  17:      // ACT
  18:      sut.SavePropertyOnWeb(web, sampleKey, sampleValue);
  19:      Isolate.Verify
  20:      .WasCalledWithAnyArguments(() =>
  21:          SPSecurity.RunWithElevatedPrivileges(() => { }));
  22:  }

 

Wie man sieht ist es sehr einfach sicherzustellen, ob ein Call auf SPSecurity.RunWithElevatedPrivileges auch tatsächlich durchgeführt wurde.

 

Technorati-Markierungen: ,,,
DotNetKicks-DE Image

Frohe Weihnachten und ein erfolgreiches Jahr 2011

20.12.2010 09:08:00 | Martin Hey

Die letzen Tage im Dezember sind ja quasi prädestiniert dazu, einmal etwas intensiver als sonst und mit einem Jahreshorizont zu reflektieren und Kraft für neue und spannende Herausforderungen zu sammeln.

Alles in allem war es ein sehr ereignisreiches Jahr für mich. Zuerst einmal gab es viele spannende Projekte - viele davon mit neuen interessanten Themengebieten und eigenen Problemen, die es zu lösen galt. Technologisch ging es dabei über Visual Studio Team System, SQL Server 2008, SharePoint 2010, ASP.NET (MVC), WPF, Silverlight und ganz neu auch Silverlight für Windows Phone. Damit verbunden waren natürlich auch auch eine Menge Herausforderungen und einige davon haben auch ihren Platz hier im Blog gefunden. Alles in allem sind damit über 30 Posts zusammengekommen, die mir als Gedankenstütze und euch als meinen Bloglesern als Hilfe dienen können.

Was gab's noch? In diesem Jahr war meine Premiere als Autor in der dotnetpro mit einem Artikel zu Message Queuing, es haben mehrere Windows Phone 7 Apps an denen ich maßgeblich mit gearbeitet habe ihren Weg in den Marketplace gefunden. Ich war bei fast allen Treffen der .NET Usergroup Dresden mit dabei und habe dort entweder was spannendes erfahren oder selbst was spannendes erzählt.

Zusammengefasst: Ja, es war ein interessantes Jahr und ich möchte an dieser Stelle euch allen für euer stetiges Interesse danken. Euer Feedback in Twitter oder Facebook oder auch eure Kommentare zeigen mir, dass es sich lohnt, hier weiter zu machen. In diesem Zusammenhang freue ich mich natürlich auch über Feedback, was ich vielleicht besser machen könnte oder ob ich ein Thema etwas detaillierter behandeln sollte.

Soweit es sich bisher voraussagen lässt, wird das nächste Jahr mindestens genauso interessant wie das aktuelle. In diesen Sinne: Stay tuned, ein paar ruhige Tage und dann volle Power für 2011.

NEU: MSDN ist jetzt auf Facebook

19.12.2010 13:25:34 | Kay Giza

Unter http://www.facebook.com/MSDN.DE präsentiert MSDN Deutschland nun seine eigene Facebook-Seite oder auch Facebook Fan Page genannt. Dort präsentieren wir ab sofort Neuigkeiten und Highlights, Events und Videos rund um MSDN für Entwickler! Wir laden ganz herzlich alle Interessierten und MSDN-Benutzer ein, uns auch auf Facebook zu besuchen, wir würden uns freuen Sie dort auch begrüßen zu dürfen! MSDN auf Facebook, jetzt Fan werden: http://www.facebook.com/MSDN.DE ... [... mehr]

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

MSDN TV vom 17.12.2010: Weihnachtsspezial-Ausgabe

19.12.2010 12:29:58 | Kay Giza

MSDN TV verabschiedet sich in diesem Jahr mit der Ausgabe vom 17.12.2010, mit einer Weihnachtsspezial-Ausgabe. Bis wir Sie im neuen Jahr wieder mit neuen Folgen von MSDN TV begrüßen dürfen, möchten wir Ihnen mit dieser Ausgabe von MSDN TV eine kleine Freude bereiten und uns so für die Aufmerksamkeit und das Vertrauen bedanken, das Sie uns während des Jahres entgegengebracht haben. Danke! Jetzt die MSDN TV Folge vom 17.12.2010 anschauen... [... mehr]

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

Silverlight Tipp der Woche: Dynamisches Nachladen und Caching von XAP-Dateien

19.12.2010 11:20:00 | Stefan Lange

In diesem Tipp wird das dynamische Laden und lokale Caching von Teilen einer Silverlight-Anwendung zur Verbesserung des Ladeverhaltens vorgestellt.

Zusammenfassung

Auch sehr große Silverlight-Anwendungen sollten beim ersten Aufruf möglichst schnell starten und beim nächsten Start am besten gar keine Assemblies mehr übers Web transportieren müssen. Durch das Zwischenspeichern von Teilen der Anwendung im Isolated Storage kann dies recht einfach erreicht werden.

Überblick

Bevor eine Silverlight-Anwendung ausgeführt werden kann, muss zunächst ihre XAP-Datei vom Webserver heruntergeladen werden. Bei größeren Anwendungen kann dies schon mal unangenehm lange dauern. Mit der Projektoption „Reduce XAP size by using application library caching“ kann die Größe der XAP-Datei dadurch vermindert werden, dass bestimmte Assemblies im Browser Cache zwischengespeichert werden. Diese Methode hat jedoch zwei Nachteile: Zum einen wird der erste Start dadurch nicht beschleunigt, denn beim allerersten Mal müssen ja trotzdem alle Assemblies zunächst heruntergeladen werden. Zum anderen funktioniert das Verfahren nicht bei Out-of-Browser Anwendungen.

Ich möchte hier ein Verfahren vorstellen, bei dem die Gesamtanwendung in mehrere XAP-Dateien zerlegt und im Isolated Storage zwischengespeichert wird. Tim Heuer hat die Grundidee in zwei Blog-Artikeln hier und hier schon vor längerem beschrieben. Bevor ich dieses Verfahren jedoch in einem unserer Produkte eingesetzt habe, wollte ich bestimmte Aspekte noch genauer untersuchen.

Zum „Proof of Concept“ dient eine minimalistische Testanwendung, die die Konstellation in einem realen Projekt modelliert. In unserem echten Projekt gibt es unter anderem eine Komponente, die PDF-Dateien im Corporate Design des Kunden generieren wird. Diese Komponente kann aufgrund von eingebetteten Bildern, Grafiken, Fonts etc. so groß werden, dass ein regelmäßiges Herunterladen aufgrund der Wartezeit nicht akzeptabel wäre.

Beispiel Solution

Das vorgestellte Beispielprojekt berücksichtigt auch Versions- und Lokalisierungsaspekte und kann zum Experimentieren für eigene Lösungen als Ausgangspunkt dienen. Es besteht aus 6 Silverlight Projekten. XapLoadingAndCaching ist die eigentliche Startanwendung. GeneralLibrary steht exemplarisch für eine Assembly, die von allen Projekten referenziert wird. Die drei Projekte LargePart1 bis LargePart3 stehen für drei große Teilkomponenten, die einzeln geladen werden können, jedoch auch voneinander abhängig sind.

Wenn ein Silverlight Application Projekt compiliert wird, erzeugt Visual Studio dabei eine XAP-Datei. Diese ist ein Zip-Archiv mit allen benötigten Assemblies und sonstigen Ressourcen, die Teil dieser Anwendung sind. Das Projekt XapLoadingAndCaching referenziert die Projkete GeneralLibrary, LargePart1 und LargePart2. Allerdings ist für LargePart1 und LargePart2 die Projekt-Eigenschaft Copy Local auf False gesetzt. Durch diesen Trick werden diese beiden Assemblies nicht in die XAP-Datei der Anwendung aufgenommen, obwohl es im Code Aufrufe in beide Assemblies gibt.

XapLoadingAndCaching.xap enthält daher nur folgende Dateien:

Tipp: Wer WinZip oder ein vergleichbares Tool verwendet, kann darin „.xap“ als Dateierweiterung hinzufügen und dann XAP-Dateien einfach anklicken, um ihren Inhalt zu kontrollieren.

Durch das Weglassen von referenzierten Assemblies lassen sich also sehr kleine und damit schnell zu ladende XAP-Dateien für die Startanwendung erzeugen. Die Anwendung läuft problemlos, sofern man keine Funktionen aus noch nicht geladenen Teilen aufruft. Eine echte Anwendung kann so sehr schnell ihre Hauptseite anzeigen. Und während der Anwender sich darin umschaut, werden asynchron weitere Teile nachgeladen.

Hier im Beispiel können die Applikationsteile zum Experimentieren jeweils einzeln über die drei Load Buttons nachgeladen werden.

Mit den beiden Call Buttons werden Testfunktionen in den jeweiligen Teilen aufgerufen. Drückt man einen der Buttons, bevor der benötigte Teil geladen wurde, kommt es erwartungsgemäß zu einer Exception.

Nachladen und Caching

Mit der Klasse WebClient kann man jede Art von Dateien und somit auch Assemblies vom Server downloaden und dann über die Klasse AssemblyPart in die laufende AppDomain hinzufügen. Das ist aber recht unpraktisch. Typische Komponenten bestehen meist aus mehreren zusammengehörigen Assemblies, die auf einen Schlag geladen werden sollten. Weiterhin sind Assembly-Dateien nicht komprimiert, was die Downloadzeit im Vergleich zu einer gezippten Datei mindestens verdoppelt.

Der nächste Trick besteht nun darin, die drei LargePart Projekte nicht als Silverlight Class Libraries, sondern als Silverlight Applications anzulegen. Dadurch werden automatisch XAP-Dateien generiert, die von Visual Studio auch gleich noch nach jedem Compilieren ins ClientBin-Verzeichnis der Web-Anwendung kopiert werden.

Im Beispiel ist festgelegt worden, dass LargePart1 vor LargePart2 geladen werden muss. Daher ist die gemeinsame Assembly PartLibrary nur in LargePart1.xap enthalten. LargePart2 referenziert zwar auch PartLibaray, aber Copy Local ist hier wieder auf False gesetzt, denn diese Assembly ist ja schon im vorher geladenen Part enthalten gewesen. Dadurch wird LargePart2.xap kleiner.

Die durch die Projektvorlage generierte Datei App.xaml wird übrigens nicht benötigt und kann aus dem Projekt herausgelöscht werden, denn diese XAP-Dateien benötigen ja kein Startup-Objekt. Es stört aber auch nicht, wenn sie wie in LargePart1 einfach drin bleiben. Man könnte App.xaml aber auch drin lassen und so diese XAP-Datei beispielsweise zu Testzwecken alleinstehend startbar machen.

Der nächste Trick ist das Zwischenspeichern der XAP-Dateien im Isolated Storage. Beim nächsten Start wird zunächst einmal nachgeschaut, ob die benötigte XAP-Datei schon auf dem Client Rechner vorliegt. Im Normalfall startet so auch eine extrem große Browser-Anwendung blitzschnell.

Hier zunächst der Code zum Downloaden einer XAP-Datei. Es ist jedoch nur eine Skizze zum Verständnis des Konzepts. Fehlerbehandlung oder die Erhöhung des Isolated Storage Kontingents wurden hier weggelassen.

public static void LoadXap(string name, string version)
{
  // Do not load XAP file more than once.
  if (_loadedXaps.ContainsKey(name))
    return;
 
  using (var store = IsolatedStorageFile.GetUserStoreForSite())
  {
    string cachedFileName = GetCachedFileName(name, version);
    if (store.FileExists(cachedFileName))
    {
      // Take file from cache.
      IsolatedStorageFileStream fileStream =
        store.OpenFile(cachedFileName, FileMode.Open, FileAccess.Read);
      LoadXap(fileStream);
      _loadedXaps.Add(name, null);
    }
    else
    {
      // Clear older version of file, if any exists.
      ClearCache(store, name);
 
      // Download file from site of origin.
      var webClient = new WebClient();
      webClient.OpenReadAsync(new Uri(name, UriKind.Relative));
      webClient.OpenReadCompleted += (sender, e) =>
      {
        using (var store2 = IsolatedStorageFile.GetUserStoreForSite())
        {
          // Save copy of new file in store.
          int length = (int)e.Result.Length;
          byte[] buffer = new byte[length];
          e.Result.Read(buffer, 0, length);
          using (var fileStream = store2.CreateFile(cachedFileName))
          {
            fileStream.Write(buffer, 0, length);
          }
          LoadXap(e.Result);
          _loadedXaps.Add(name, null);
        }
      };
    }
  }
}

Die Funktion erhält neben dem XAP-Dateinamen auch noch einen Version-String. Dieser wird an den Namen der zwischengespeicherten Datei angehängt. Dadurch wird sichergestellt, dass die Datei erneut heruntergeladen wird, wenn auf dem Server eine neuere Version vorliegt. In einem realen Projekt muss man einfach bei jedem Deployment die Version hochzählen. Hier im Beispiel kann man in der Textbox eine Versionsnummer eingeben oder mit dem Clear Cache Button die Dateien manuell löschen.

Um zu sehen, welche Dateien im Cache sind, kann man im Pfad

C:\Users\CurrentUser\AppData\LocalLow\Microsoft\Silverlight\is\

nach „LargePart“ suchen. Dann findet man den Isolated Storage der Anwendung.

Nachdem die XAP-Datei auf dem Client vorliegt, werden die in ihr enthaltenen Assemblies geladen:

static void LoadXap(Stream stream)
{
  StreamResourceInfo sri = new StreamResourceInfo(stream, null);
 
  // Get a list of all assembly part names from application manifest.
  string appManifest = new StreamReader(Application.GetResourceStream(sri,
      new Uri("AppManifest.xaml", UriKind.Relative)).Stream).ReadToEnd();
  XElement deploy = XDocument.Parse(appManifest).Root;
  List<XElement> parts = (from assemblyParts in deploy.Elements().Elements()
      select assemblyParts).ToList();
 
  // Load all assembly parts.
  foreach (var source in parts.Select(element => element.Attribute("Source")))
  {
    var streamInfo = Application.GetResourceStream(sri, new Uri(source.Value, UriKind.Relative));
    new AssemblyPart().Load(streamInfo.Stream);
  }
}

Die in der XAP-Datei enthaltenen Assemblies werden über das Manifest herausgesucht und geladen.

Lokalisierung

LargePart2 enthält zwei RESX-Dateien mit einem deutschen bzw. englischen Text. Ein Blick in das für LargePart2.xap generierte Manifest zeigt, dass die deutsche Satellite Assembly LargePart2.resources.dll korrekt im Unterverzeichnis de enthalten ist:

<Deployment xmlns=http://schemas.microsoft.com/client/2007/deployment …>
  <Deployment.Parts>

    <AssemblyPart x:Name="LargePart2" Source="LargePart2.dll" />
    <AssemblyPart Source="de/LargePart2.resources.dll" />
  </Deployment.Parts>
</Deployment>

Der Testcode bestätigt, dass alles wie gewünscht funktioniert:

ResourceManager rm = new ResourceManager("LargePart2.StringResources",
    Assembly.GetExecutingAssembly());
var de = rm.GetString("String1");
var en = rm.GetString("String1", CultureInfo.InvariantCulture);

Sowohl der englische als auch der deutsche Text werden korrekt geladen.

Das Unterverzeichnis de existiert nur im Zip-Archiv der XAP-Datei. Im Isolated Storage liegt die Datei LargePart2.xap-1.00. Man braucht sich also um nichts zu kümmern, was im Vergleich mit einem Download einzelner Assemblies äußerst praktisch ist.

Es ist übrigens egal, in welcher Reihenfolge voneinander abhängige Assemblies geladen werden, da erst bei ihrer ersten Verwendung das Vorhandensein von referenzierten Assemblies überprüft wird.

Statische Ressouce-Dateien

Neben Code und lokalisierten Strings kann eine XAP-Datei natürlich auch Assemblies mit sonstigen statischen Ressourcen enthalten. LargePart3.xap enthält eine Assembly mit einem Beispiel-Font. Da XAP-Dateien Zip-Container sind, ist diese Datei signifikant kleiner als die Font-Datei selbst. Es macht also sehr viel Sinn, statische Ressourcen ebenfalls in XAP-Dateien zu verpacken.

Der folgende Code zeigt den Zugriff auf die Font Ressource:

void LoadFont(object sender, RoutedEventArgs e)
{
  var stream = Application.GetResourceStream(
    new Uri("/LargePart3;component/fonts/Early_Tickertape.ttf",
    UriKind.Relative));
  txtBlock.FontSource = new FontSource(stream.Stream);
  txtBlock.FontFamily = new FontFamily("Early Tickertape");
}

Wenn LargePart3.xap geladen wurde, ändert dieser Code den Font des angezeigten Beispieltextes.

Out-of-Browser Anwendungen

Das vorgestellte Verfahren funktioniert bei Browser und Out-of-Browser Anwendungen identisch. Bei Out-of-Browser Anwendungen muss man allerdings zwei Dinge beachten, wenn man offline arbeiten möchte: Alle XAP-Dateien müssen im Cache vorliegen und der Cache darf nicht gelöscht werden.

Managed Extensibility Framework

Der im Beispiel verwendete Trick mit dem Referenzieren von Assemblies, die nicht in der eigenen XAP-Datei vorhanden sind, sollte in Produktivcode besser nicht verwendet werden, da das Risiko eines Funktionsaufrufes in eine nicht geladene Assembly besteht. Während der Entwicklungszeit und zum Debuggen ist es allerdings praktisch.

Im echten Projekt verwenden wir das Managed Extensibility Framework. Bevor eine Komponente nicht geladen ist, steht sie im Composition-Container auch nicht zur Verfügung und kann somit auch nicht unbeabsichtigt aufgerufen werden. Unmittelbar nach Programmstart werden die XAP-Dateien in einer definierten Reihenfolge im Hintergrund heruntergeladen und in die laufende AppDomain hinzugefügt. Nach jedem Download findet ein Recomposition des Containers statt, damit die neu hinzugekommenen Teile auch verfügbar sind.

Nur durch MEF bzw. einem vergleichbaren Framework kann zuverlässig sichergestellt werden, dass man nicht doch einmal versehentlich einen Funktionsaufruf ins Leere macht.

Fazit

XAP-Dateien lassen sich auf sehr einfache Weise als universelle Zip-Container für Code und Daten verwenden. Der Verwaltungsaufwand bei der Entwicklung ist minimal. Das Nachladen und lokale Zwischenspeichern der Dateien führt zu einer spürbaren Verbesserung der Benutzererfahrung, vor allem wenn die Anwendung sehr groß geworden ist. Das Ganze ist auch keinerlei Hack, sondern einfach die konsequente Nutzung der Möglichkeiten von Silverlight.

Hier das Projekt:

XapLoadingAndCaching.zip (119 kB)

Eine ContentControl Id ist eine Id ist nicht immer die gleiche Id

17.12.2010 21:08:00 | Jan Christian Selke

Heute wäre ich fast wieder auf eine kleine, alte Nicklichkeit von Word und dem OpenXml hereingefallen…
Innerhalb von Word habe ich ein Inhaltssteuerelement angelegt und dessen interne Id ermittelt. Diese wird von der Word API als String bereitgehalten. Die MSDN Auskunft dazu ist eindeutig:
Returns a String that represents the identification for a content control. Read-only.
Diese Id wird nun intern von uns als Zahl weiterverarbeitet. – Soweit kein Problem. Aus

long id = long.Parse(contentControl.Id);

erhalte ich die Id 2857609749.

Jetzt musste ich aber anhand dieser Id das Inhaltssteuerelement in der document.xml ermitteln. Zu meiner ersten großen Überraschung war aber keines mit dieser Id zu finden?! Nach etwas Suchen stellte sich heraus, dass das Inhaltssteuerelement anscheinend unter der Id –1437357547 in dem Dokument abgelegt war.

Innerhalb der Word API wird anscheinend die Darstellung als unsigned Wert, also ohne negative Vorzeichen bevorzugt, während innerhalb der Dokumentstruktur auch negative Vorzeichen verwendet werden.

Es bleibe also nichts andere übrig, als zwischen den verschiedenen Darstellungen zu konvertieren.

In meinem Fall lag der String-Wert ohnehin schon als long vor. Daher konnte ich folgenden Aufruf nutzen, um den Word API Wert, in den zu der document.xml zu konvertieren:

long ccid = Convert.ToInt64((int)id);

Der umgekehrte Weg, von der Darstellung aus der document.xml in den von Word bevorzugten Wert erfolgt dann folgendermaßen:

long ccid = Convert.ToInt64((uint)id);

Oder mit noch etwas mehr Konvertierungsaufwand lassen sich die Werte direkt aus dem String-Wert konvertieren:

long ccid = Convert.ToInt64((uint)long.Parse(contentControl.Id));

… Das bietet sicherlich auch noch Optimierungspotential…

MSDN TV: Weihnachtsspecial 2010

17.12.2010 16:55:34 | Oliver Scheer

Weihnachten bei "msdn tv": Auch in diesem Jahr haben sich Insassen der "Developer Platform & Strategy Group" wieder viel Mühe gemacht, Ihnen mit selbstgebastelten Beiträgen eine kleine Freude zu bereiten und sich so für die Aufmerksamkeit und das Vertrauen zu bedanken, das ihnen während des Jahres entgegengebracht wurde.


Die Redaktion von MSDN Online hat versucht, sich einen Reim darauf zu machen. Es ist uns aber nicht recht gelungen:

Weihnachten bei MSDN
Ein Männlein auf dem Sofa, ganz still und stumm
es hat von lauter Purpur ein Mäntlein um,
schaut aus wie nach durchzechter Nacht,
hat sieben Elfen mitgebracht.

Elf:eins heißt Prengel Komma Frank
und holt ein Win Phone aus dem Schrank.
Er träumt, ganz ins Device verliebt,
von vielen Apps, dies schon bald gibt.

Elf:zwei – Henrike – weist drauf hin
auf E-i-n-s-e-n-d-e-s-c-h-l-u-ß-t-e-r-m-i-n
von Wettbewerb "Imagine Cup"
wo noch zwei "IT-Challenge"-Runden hat.

Wer Preis will bei Finale holen,
muss diesmal fahren nicht nach Polen,
sondern nach Nordamerika:
New York im Juli – wunderbar.

Elf:drei lobt, als eins der Besten,
das "Cloud Computing". Und zum Testen
gibt’s Frei-Accounts, die sind - famos -
für Tester völlig kostenlos.

Elf:vier hält mit gewinnendem Gegrinse
wertvolle Preise in die Linse,
die man bekommt, wenn man nicht döst,
sondern Adventskalender-Rätsel löst.

Elf:fünf preist ohne viel Gezeter
das Service Pack 1 Beta
von Visual Studio 2010 -
so schnell kann’s gehen.

Spielt außerdem mit seine Kinder
Kinect. Sein Name: Christian Binder,
und fordert selbst den Nikolaus
zu einem Xbox-Game heraus.

Den Reigen schließt zum Schluss, don’t worry,
Elf Nummer 6 – Ms. Grosland, Lori
Elf:sieben, Frau Cortessa K.,
steht sonst hinter der Kamera.

Zu guter Letzt packt Santa Claus
noch die Erziehungskeule aus
und äußert eine wüste Drohung,
als Zeichen völliger Verrohung:

"Umlaut, Zimt und Mandelstern,
haben alle Kinder gern.
Wenn nicht, dann setzt es, selbst für brave,
zum Fest 'ne Runde Prügelstrafe."

MSDN Online wünscht ein besinnliches Jahresende. Ho, ho, ho.

http://msdn-online.de/msdntv

Get Microsoft Silverlight



Open XML Dateien aufbauen und verändern (Teil 3)

17.12.2010 13:50:31 | Jens Häupel

Zeichenketten in existierende Excel-Dateien eintragen

In den ersten beiden Teilen haben wir das jeweilige Open XML Dokument neu erzeugt. Während man sich dabei darauf verlassen kann, dass die zu erzeugenden Teile noch nicht vorhanden sind, hat man es beim Einfügen in bestehende Dokumente schwerer. Es muss jedes Mal überprüft werden, ob eine Komponente nicht evtl. doch schon vorhanden ist, da jeder Bezeichner bzw. jede ID nur genau einmal vorkommen darf.

Es soll ein String in eine Zelle eingetragen werden. Der String wird als Shared String eingebettet. Als Übergabeparameter benötigen wir:

  • Name der Arbeitsmappen mit Pfadangabe
  • Name der Tabelle
  • Adresse der Zelle, z.B. “A1”
  • Die einzufügende Zeichenkette

Ausgehend von diesen Parametern könnten Tabelle, Zeile bzw. Zelle noch nicht vorhanden sein. Um das Erzeugen werden wir uns hier kümmern. Die Grundaufgabe ist allerdings das Einfügen der Zeichenkette in die Zelle.

Der Rumpf der Prozedur wäre erst mal folgender. Wir gehen nun Schritt für Schritt durch die Entscheidungen.

 

private void AddSharedStringsToExistingWorksheet(string FName, string sheetName, string cellRef, string sharedString) { using (SpreadsheetDocument xlDoc = SpreadsheetDocument.Open(FName, true)) { … } }

Das Erste, was beim Einfügen eines Shared Strings gemacht werden muss ist die Prüfung, ob die Shared Strings-Tabelle existiert, also ob ein SharedStringTablePart vorhanden ist. Wenn nicht, wird sie erzeugt.

 

SharedStringTablePart sstPart = xlDoc.WorkbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault(); if (sstPart == null) sstPart = xlDoc.WorkbookPart.AddNewPart<SharedStringTablePart>();

Dann schauen wir, ob ein Worksheet mit dem vorgegebenen Namen zu finden ist. Dazu müssen wir im Workbook.xml nachschauen, da dort alle enthaltenen Worksheets gelistet sind. Das Markup der workbook.xml kann man einer vorher erstellten Excel-Datei entnehmen:

<sheets> <sheet name="Bilanzen 1998" sheetId="1" r:id="rId1" /> <sheet name="Zusammenfassung" sheetId="2" r:id="rId2" /> <sheet name="Externe Ressourcen" sheetId="3" r:id="rId3" /> </sheets>

(Die angegebene Relationship ID (rIdx) kann jeder eindeutige String sein, z.B. auch eine GUID. Excel selbst vergibt durchnummerierte IDs, die sehr einfach zu lesen aber für uns schwierig zu verwalten sind. Das Open XML SDK verwendet deshalb auch GUID-Strukturen.)

Aus diesem Sheet-Element wird über die ID der dazugehörige WorkbookPart ermittelt (GetPartById). Dieser Part beherbergt dann auch das entsprechende Worksheet.
Wenn kein Sheet-Element in der Workbook.xml gefunden wurde, wird ein WorksheetPart eingefügt, das XML Document mit dem Root-Element Worksheet erzeugt und das SheetData-Element angehängt.

WorkbookPart wbPart = xlDoc.WorkbookPart; Workbook wb = wbPart.Workbook; Sheet sheet = (Sheet)wb.GetFirstChild<Sheets>().Elements<Sheet>() .Where(s => s.Name == sheetName).FirstOrDefault(); WorksheetPart wsPart; Worksheet ws = null; if (sheet == null) { wsPart = InsertWorksheetPart(wbPart, tbWorksheetName.Text); ws = new Worksheet(new SheetData()); } else { string rId = sheet.Id.Value; wsPart = (WorksheetPart)xlDoc.WorkbookPart.GetPartById(rId); ws = wsPart.Worksheet; } SheetData sd = ws.GetFirstChild<SheetData>();

Wichtig ist es zu wissen, dass das o.g. Sheet Element nichts mit dem worksheet Element zu tun hat. Ersteres bezieht sich auf die Auflistung der in der Arbeitsmappe enthaltenen Tabellen (also in der workbook.xml) und letzteres ist die Definition des Inhalts dieser Tabellen (worksheet.xml).

Jetzt haben wir das SheetData-Element, also die Stelle, an der die Tabellenzeilen aufgelistet sind. Die Zelladresse wird hier im Format „A1“ übergeben. Um an die Zeilennummer zu kommen, habe ich eine kleine Extensions Class geschrieben, die die Methode RemoveAllButNumbers für den Typ String bereit stellt.

UInt32Value rowIndex = (UInt32Value)cellRef.RemoveAllButNumbers();


Mit dem so gewonnenen RowIndex wird die Referenz auf die Zeile geholt. Sollte die nicht existieren, erzeugen wir eine neue Zeile. Dabei ist unbedingt zu beachten, dass die Reihenfolge stimmt (aufsteigend). Die Funktion CreateRow weiter unten erledigt das.

IEnumerable<Row> rows = sd.Elements<Row>() .Where(r => r.RowIndex.Value == rowIndex); Row row = rows.FirstOrDefault(); if (row == null) row = CreateNewRow(ref sd, rowIndex);

Dasselbe gilt für die Zelle.

Cell cell = row.Elements<Cell>() .Where(c => c.CellReference == cellRef).FirstOrDefault(); if (cell == null) cell = CreateNewCell(ref row, cellRef);

Am Ende wird nur noch der Shared String mit der Zelle verlinkt und das Worksheet gespeichert. Die Funktion dafür wurde schon in Teil 2 beschrieben.

cell.DataType = CellValues.SharedString; cell.CellReference = cellRef; cell.CellValue = new CellValue( InsertSharedStringItem(sharedString, sstPart).ToString()); ws.Save(wsPart);

Hilfsfunktionen zum Erzeugen einer neuen Zeile bzw. Zelle. Beide müssen in aufsteigender Reihenfolge im Markup erscheinen.

private Row CreateNewRow(ref SheetData sd, UInt32Value rowIndex) { Row newRow = new Row(); newRow.RowIndex = rowIndex; Row lastRow = (Row)sd.Elements<Row>() .Where(r => r.RowIndex < rowIndex).LastOrDefault(); if (lastRow != null) sd.InsertAfter(newRow, lastRow); else sd.InsertAt(newRow, 0); return newRow; } private Cell CreateNewCell(ref Row row, string cellRef) { Cell lastCell = row.Elements<Cell>().Where (c => string.Compare(c.CellReference.Value, cellRef, true) < 0) .LastOrDefault(); Cell newCell = new Cell(); if (lastCell != null) row.InsertAfter(newCell, lastCell); else row.InsertAt(newCell, 0); return newCell; }

Die Extensions Class, welche die Funktion RemoveAllButNumbers für Strings zur Verfügung stellt. Damit werden aus der Zelladresse alle Zeichen herausgenommen, die keine Ziffern darstellen. Das Ergebnis entspricht der Zeilennummer.

internal static class MyExtensions { internal static UInt32 RemoveAllButNumbers(this string s) { string res = string.Empty; char[] numbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; foreach (char c in s) { if (numbers.Contains(c)) { res += c; } } return UInt32.Parse(res); } }

[ Fortsetzung folgt ]

Test Case Attachments löschen

17.12.2010 08:44:35 | Thomas Schissler

Mit dem Microsoft Test Manager 2010 hat Microsoft sog. Rich Information Bugs eingeführt. Damit sind Bugs gemeint die automatisch mit Informationen zur Testausführung angereichert sind um dem Entwickler das reproduzieren und identifizieren von Bugs erleichtert. Dazu gehören beispielsweise Videos, IntelliTrace Logs, Systeminformationen und weitere. Diese extrem hilfreiche Funktion bringt jedoch leider auch ein Problem mit sich. Diese Informationen werden alle als Attachements and die TestCase Work Items gehängt was dazu führt, dass die TFS Datenbank schnell sehr groß werden kann. Bisher hatte der Datenbankadministrator keine effiziente Möglichkeit zur Anlayse und Bereinigung dieser Daten. Diese Lücke wird nun mit dem Test Attachement Cleaner Power Tool geschlossen.

Mit diesem Tool kann der Datenverbrauch in der Datenbank analysiert und in einerDatei ausgegeben werden. Zudem können bestimmte Löschoperationen ausgeführt werden, z.B. Videos die älter sind als ein bestimmtes Datum, Alle IntelliTrace Logs die größer sind als ein bestimmter Wert etc. Dadurch dass das Tool als Kommandozeilentool implementiert ist, können damit auch automatisierte Datenbereinigungen einfach eingestellt werden.

Live-Webcast / Webinar: Windows Phone 7 im Alltag - 29. Dezember 2010, 17:00 - 18:00 Uhr

16.12.2010 15:11:43 | Jan Schenk

Daniel Neumann, Microsoft Student Partner und Mobile Enthusiast, veranstaltet einen Live-Webcast zum Thema Windows Phone 7 (Einsteigerlevel).

Inhalt dieses Live Webcasts ist die persönliche Erfahrung von Daniel Neumann mit dem Windows Phone 7 im Alltag. Es wird auf die Vorteile sowie Nachteile im täglichen Gebrauch eingegangen. Die Tauglichkeit im Businessbereich kommt dabei auch zur Sprache.

Anmeldung auf der Student Partner Plattform stnc.de:

http://www.stnc.de/events/2010/12/15/4255-Live-Webcast-Windows-Phone-7-im-Alltag

Viel Spass zwischen den Jahren wünscht euch

jan

MSDN Subscriptions-Update: Keine Kreditkarte mehr noetig fuer Windows Azure

16.12.2010 12:31:47 | Kay Giza

Ab sofort können Sie sich auch ohne Kreditkarte die umfangreichen Windows Azure Cloud Computing-Inklusivleistungen Ihrer MSDN Subscription sichern. Ihre positiven Reaktionen haben uns gezeigt, dass das Windows Azure-Angebot für MSDN Subscriber sehr gerne angenommen wird. Die Voraussetzung einer Kreditkarte, um die kostenlosen Windows Azure-Vorteile nutzen zu können, war für viele deutsche MSDN Subscriber jedoch eine Einstiegshürde. Diese Hürde haben wir jetzt abgeschafft. Alle Informationen, Links und Anleitungen finden Sie in diesem Blogpost auf Giza-Blog.de... [... mehr]

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

Einstieg zur Workflow Foundation 4 : Activities parallel ausführen

16.12.2010 11:37:25 | Gregor Biswanger

Mit der Workflow Foundation 4 wird das Parallel Activity bereitgestellt. Womit gleichzeitig ein Satz untergeordneter Aktivitäten ausgeführt werden kann.

Jedoch werden die Activities nicht “wirklich” parallel ausgeführt, sondern werden der Reihe nach durchlaufen. Sollte sich ein Activity im Leerlauf befinden, wird sofort das zweite Activity abgespielt. Der ganze Prozess wird daher auch im selben Thread ausgeführt.

 

Beispiel: Das WorkflowParallelExample

Dazu wird Visual Studio 2010 geöffnet und ein neues Projekt angelegt. Als Template wird unter “Workflow” – “Workflow Console Application” gewählt. Als Name wird “WorkflowParallelExample” verwendet.

 

SNAGHTML394dbef

Abb.1 – Neues “Workflow Console Application” Projekt erzeugen.

 

Deklarieren der Workflow

  1. Das Parallel Activity auf den Workflow hinzufügen.
  2. Zwei Sequence Activities der Parallel Activity hinzufügen.
  3. Die Namen der Sequence Activities abändern in “Sequence 1” und “Sequence 2”.
  4. Dann erhält jede Sequence Activity drei WriteLine Activities.
  5. Dabei erhält jede WriteLine Activity passend zur jeweiligen Position folgende Expression:
    String.Format("Sequence 1 - Activity 1 - Thead: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId)

 

Wenn alles korrekt deklariert wurde, sieht der Workflow wie in Abb. 2 aus:

image

Abb. 2 – Das Parallel Activity mit zwei Sequence Activities.

 

Wenn das Projekt nun mit der Tastenkombination [Strg] + [F5] ausgeführt wird, wird sofort ersichtlich, das die Activities nicht wirklich Parallel verarbeitet werden und sich im selben Thread befinden:

SNAGHTML3aabf4b

Abb. 3 – Ausgabe des Workflows zeigt keine parallele Verarbeitung.

 

Somit wird ersichtlich wie genau das Parallel Activity die enthaltenen Activities verarbeitet:

image

Abb. 4 – So arbeitet das Parallel Activity seine Activities ab.

 

Das Parallel Activity führt nur bei einem Leerlauf das darauffolgende Activity aus. Somit kann während eines wartenden prozesses ein folge Prozess ausgeführt werden. Als Beispiel soll ein Delay Activity in der ersten Sequence direkt nach dem ersten WriteLine Activity gesetzt werden. Als Expression wird folgender Wert verwendet: TimeSpan.FromSeconds(1)

Wenn alles korrekt deklariert wurde, sieht der Workflow wie in Abb. 5 aus:

image

Abb. 5 – Sequence 1 wurde durch ein Delay Activity erweitert.

 

Wenn das Projekt nun mit der Tastenkombination [Strg] + [F5] ausgeführt wird, wird sofort ersichtlich, das bei einem Leerlauf sofort beim nächsten Activity weitergemacht wird:

SNAGHTML3c820fb

Abb. 6 - Ausgabe des Workflows zeigt die nächste Verarbeitung der enthaltenen Activities.

 

Somit wird ersichtlich wie genau das Parallel Activity die enthaltenen Activities bei einem Leerlauf verarbeitet:

image

Abb. 7 - So arbeitet das Parallel Activity seine Activities bei einem Leerlauf ab.

VSTO Performance Improvements im neuen VS SP1

16.12.2010 11:36:00 | Lars Keller

Mit dem neuen Service Pack für VS 2010 kommen einige Performance Verbesserungen bei VSTO mit:

  • VSTO Path
  • Ribbon Aware Manifests
  • VSTO Form Region discovery

-> Es gibt eine klare Verbesserung bei dem Starten von Add-Ins in Office von 60-107%. Juhu! :-)

Die detaillierte Beschreibung der einzelnen Verbesserung sind auf dem Blog des VSTO Teams erklärt.

Des Weiteren möchte ich auch noch auf einen MSDN Artikel eines MVP Kollegen Helmut Obertanner aufmerksam machen. Helmut erklärt ausführlich wie man mit den Inspector Window in Outlook umgeht. Must read! :-)

Hier ist der Link.

Erstes deutsches WP7 Entwicklerbuch erschienen

16.12.2010 08:31:16 | Peter Nowak

Endlich ist es für jedermann erhältlich: Unser Windows Phone 7 Entwicklerbuch. Geschieben wurde es zusammen mit Patrick Getzmann und Simon Hackfort, so dass hier die “3 alten Hasen”, wie ein geschätzter MS Kollege uns nennten, wieder ihr Wissen zusammengeführt haben.

Selbstlob stinkt, weswegen ich hier gerne auf ein Schnellreview von Kay Giza verweise.
Wer eine Arbeitsversion der Inhaltsübersicht haben möchte, findet diese hier.
Wem dass noch zu wenig ist und vorher ein wenig schmökern möchte, findet eine Preview aus dem September hier.

Erschienen ist das ca. 650 Seiten umfassende Buch bei der MS Press.
Bestellt werden kann es beispielsweise bei Amazon:

Bezugsquelle: Amazon.de
ISBN-10:
3866454627
ISBN-13:
978-3866454620

Preis: 39,90 €

 

Wer sich nun beeilt hat das Buch auch noch unter dem Weihnachtsbaum liegen.

Und für die ganz Tippfaulen hier noch der Tag zum Buch auf Amazon, welcher mit der unter WP7 freien Microsoft Tag Anwendung gelesen werden kann:

Deutsches_WP7_Buch_20101215231927



This posting is provided "AS IS" with no warranties, and confers no rights.

Commands als MEF Plugins einbinden

15.12.2010 16:02:00 | Jan Christian Selke

Bei der Nachlese zu meinem letzten Refactoring kam mir eine Idee: Wie wäre es denn das Ganze noch etwas generischer zu gestalten, um den Quellcode gar nicht mehr anfassen zu müssen?! Ich habe dabei daran gedacht, MEF einzusetzen und die Prozesslogik als Plugin einzubinden.
Gut, in der momentanen Form ist es eine Milchmädchenrechnung, da die Flags, anhand derer entschieden wird, sich zur Zeit auch noch im Zielprojekt befinden. Aber dass soll erst einmal nicht beachtet werden – das ist vielleicht eine spätere Baustelle.
Zuerst einmal muss das MEF von Codeplex herunter geladen werden und die Assembly System.ComponentModel.Composition.Codeplex.dll in das Projekt eingebunden werden.
Das Bereitstellen der Prozessor Klassen erfolgt über das Export Attribut. Als Export wird die Schnittstelle IItemProcessor genutzt, da auf diese Weise nur eine Referenz auf die Schnittstelle beinhaltende Assembly benötigt wird.

[Export(typeof(IItemProcessor))]
public class SimpleItemProcessor : IItemProcessor
{
public void Process(WorkItem item)
{
throw new NotImplementedException();
}
}

Der Import der Typen erfolgt über das Import Attribut. Da hier in eine Liste importiert wird, genauer genommen das ImportMany Attribut.

public class WorkItem
{
public WorkItem()
{
this.Processors = new List<IItemProcessor>();
}

[ImportMany(typeof(IItemProcessor))]
public IList<IItemProcessor> Processors { get; set; }
...
public void Process()
{
this.processorList.Where(x => x.CanProcess(this)).Each(proc => proc.Process(this));
}
}

Jetzt sind Quelle und Ziel vorbereitet, es fehlt nur noch die Konfiguration im Programmstart zum Auffinden der Plugins. Dazu werden die sogenannten Catalogs genutzt. Exporte können sich selbst in einem solchen Katalog registrieren. Dafür stehen verschiedene Typen von Catalogs zur Verfügung. Da in diesem Fall eine Assembly gesucht wird, die im selben Verzeichnis liegt, wie die auszuführende Assembly, nutze ich den DirectoryCatalog.

var catalog = new DirectoryCatalog(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
var container = new CompositionContainer(catalog);
var batch = new CompositionBatch();
batch.AddPart(this);
container.Compose(batch);

Der Aufruf der Compose Methode startet das Auffinden der Plugins in allen Assemblies des hinterlegten Verzeichnisses. Eine sehr einfache Möglichkeit solche Plugins zu nutzen…

Einstieg zur Workflow Foundation 4 : Bookmarks

15.12.2010 15:28:39 | Gregor Biswanger

Für lang laufende Workflows gebühre dem WF4 Bookmarks die Aufmerksamkeit. Denn mittels Bookmarks kann der Workflow Prozess kurzerhand gestoppt werden, so dass es im Programmcode weitergehen kann. Bei den meisten Szenarios wird hierbei auf eine Benutzereingabe gewartet. Ist die Eingabe erfolgt, wird die WF Hoster Instanz darum gebeten genau an der Workflow stelle zurückzuspringen wo als letztes ein Bookmark (Lesezeichen) gesetzt wurde.

Um das ganze kurz zu Verbildlichen habe ich eine kleine Skizze auf dem Whiteboard gezeichnet (siehe Abb.1).

 

image

Abb. 1 – Übersicht zum Bookmark Prozess

Eine kurze Erläuterung zur Skizze: Auf der Code-Ebene (Punkt 1) startet die Workflow Hoster Instanz den Workflow (Punkt 2). Der Workflow arbeitet die einzelnen Activities ab. Ein Activity erwartet Daten von einem Anwender. Es kann allerdings lange Zeit vergehen bis diese Daten zur Verfügung gestellt werden können. Daher setzt das Activity ein Bookmark (Lesezeichen) bei der allgemeinen Workflow Runtime (Punkt 3). Beim setzen des Bookmarks wird der Workflow sofort gestoppt. Wenn dann zu einem späteren Zeitpunkt die Daten zur Verfügung stehen, wird der Workflow Hoster Instanz ein Aufruf zum jeweiligen Bookmark getätigt (Punkt 4). Der Workflow wird sofort an der Stelle fortgesetzt wie es beim Bookmark hinterlegt wurde (Punkt 5).

Ein Bookmark steht natürlich nur so lange im Speicher der Workflow Hoster Instanz, so lange die Application im System läuft. Geht es darum das zu einem späteren Zeitpunkt die Anwendung erneut gestartet wird und dann die Daten vorhanden sind, ist hierbei das Thema Workflow Foundation 4 Persistenz interessant. Ein Blog-Post zu diesem Thema folgt.

Um nun das Feature Bookmarks selbst hautnah spürbar zu erleben, ist das folgende Beispiel WorkflowBookmarkExample zum Mach-Mit-Coden geradezu ideal.

 

Beispiel: WorkflowBookmarkExample

Dazu wird Visual Studio 2010 geöffnet und ein neues Projekt angelegt. Als Template wird unter “Workflow” – “Workflow Console Application” gewählt. Als Name wird “WorkflowBookmarkExample” verwendet.

 

SNAGHTMLb67f5

Abb. 2 - Neues “Workflow Console Application” Projekt erzeugen.

 

Workflow definieren

 

Folgende Schritte sollen nun dem Workflow definiert werden:

  1. Dem Workflow ein Flowchart Activity setzen.
  2. Dem Flowchart Activity ein WriteLine Activity hinzufügen und als Expression setzen:
    ”Bitte Passwort eingeben:”
  3. Direkt unter der WriteLine Activity ein FlowDecision Activity hinzufügen und zwei weitere WriteLine Activities setzen die folgende Expression bekommen:
    ”Passwort richtig!” und “Passwort falsch!”
  4. Dann alle Activities miteinander verknüpfen, so das der Workflow Ablaufprozess informiert ist in welcher Reihenfolge abgearbeitet werden soll. Bei dem WriteLine Activity das für die Ausgabe vom falschen Passwort informiert, soll der Prozess wieder zum ersten Activity zurück springen.

 

Ist alles korrekt umgesetzt worden sollte es im Designer aussehen wie unter Abb.3 veranschaulicht wird.

 

image

Abb. 3 – Passwortabfrage-Prozess.

 

Bei Abb. 3 wird verdeutlicht das ein wichtiger Prozessschritt noch fehlt. Genau jener der die Daten (das Passwort) vom Anwender vermittelt. Daher soll vorerst eine allgemeine Variable zur Verarbeitung dienen. Dem Flowchart wird eine Variable mit Password und dem Typ String gesetzt (Abb. 4).

 

 

image

Abb. 4 – Variable für das Passwort setzen.

 

Dann muss ein eigenes Activity für die Vermittlung der Passwortabfrage geschrieben werden. Dazu wird eine neue Klasse mit dem Namen GetPasswort angelegt.

Beim Blog-Post “Einstieg zur Workflow Foundation 4 : Überblick zu Activities” wurde bereits beschrieben das nur die Basisklasse NativeActivity für “Long Running Unit of Work”-Szenarien bedacht ist. Daher leiten wir direkt davon ab und geben mittels Generics-Erweiterung gleich unseren Rückgabetyp string mit an.

Als nächstes wird von unserem Activity auch erwartet das von außen der Bookmarkname gesetzt werden kann. Dazu wird ein InArgument vom Typ String mit dem Namen "Bookmarkname” angelegt.

Damit der Workflow auch in Leerlaufmodus gestoppt werden kann, muss das bool Property CanInduceIdle überschreiben werden. Das wird dann fest manipuliert, so das immer ein True-Wert zurück gegeben wird.

Bei der allgemeinen Execute-Methode wird dann auf die Workflow Runtime mittels context-Instanz zugegriffen. Hier wird die Methode CreateBookmark bereitgestellt. An dieser Stelle wird der Name des Bookmarks definiert und welche Methode beim Zurückkehren aufgerufen werden soll.

Als Methode wird ReturnPasswortCallback definiert. Das sich strickt an den delegierten Aufbau der Parameter gehalten werden muss (siehe Listing 1). Die Parameter überreichen aus der Code-Ebene die Daten (object value) die dann dem Result Property gegeben wird.

 

   1:  public class GetPasswort : NativeActivity<string>
   2:  {
   3:      public InArgument<string> Bookmarkname { get; set; }
   4:   
   5:      protected override bool CanInduceIdle
   6:      {
   7:          get { return true; }
   8:      }
   9:   
  10:      protected override void Execute(NativeActivityContext context)
  11:      {
  12:          context.CreateBookmark(Bookmarkname.Get(context), ReturnPasswortCallback);
  13:      }
  14:   
  15:      private void ReturnPasswortCallback(NativeActivityContext context, Bookmark bookmark, object value)
  16:      {
  17:          Result.Set(context, value as string);
  18:      }
  19:  }

Listing 1 – Externe XAML-Datei zur Laufzeit einlesen und ausführen.

 

Die Ausgabe dazu sieht folgendermaßen aus:

SNAGHTML4b12dac

Abb. 1 – Ausgabe vom Workflow aus der externen XAML-Datei.

Open XML Dateien aufbauen und verändern (Teil 2)

15.12.2010 12:26:06 | Jens Häupel

Der Umgang mit Inline und Shared Strings in Excel

Beim Quellcode aus Teil 1 muss noch einiges erklärt werden. Das Erste wäre das Einfügen des Worksheet Parts und das Anlegen einer Tabelle in demselben. Ich habe dort die Funktion InsertWorksheetPart aufgerufen, die jetzt noch implementiert werden muss. Der komplizierteste Teil dabei ist das Ermitteln der neuen ID für die einzufügende Tabelle. Wichtig ist, dass die neue ID nicht schon vorkommt. Dabei hilft ein wenig LINQ. Mit Hilfe einer Lambda Function kann man schnell die höchste Sheet ID herausfinden.

 

private WorksheetPart InsertWorksheetPart(WorkbookPart wbPart, string sheetName) { // Hinzufügen eines Worksheet Parts zum Workbook. WorksheetPart wsPart = wbPart.AddNewPart<WorksheetPart>(); string rId = wbPart.GetIdOfPart(wsPart); // eindeutige ID ermitteln = höchste sheetID + 1: uint sheetId = 1; Sheets sheets = wbPart.Workbook.GetFirstChild<Sheets>(); if (sheets.Elements<Sheet>().Count() > 0) sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1; // Das Worksheet mit dem Workbook verbinden: Sheet sheet = new Sheet() { Id = rId, SheetId = sheetId, Name = sheetName }; sheets.Append(sheet); wbPart.Workbook.Save(); return wsPart; }

Die Funktion ist relative praktisch, da es unerheblich ist, ob man eine neue Datei anlegt oder einfach eine neue Tabelle in eine bestehende Arbeitsmappe hängt.

Nun zum Hinzufügen von Zellen mit Strings. In Teil 1 wurde schon angedeutet, dass Tabellen zeilenweise aufgebaut sind. Wir hatten auch festgehalten, dass es Inline Strings und Shared Strings gibt.

 

private Cell CreateCellWithInlineString(string cellRef, string cellValue) { Cell c = new Cell(); c.DataType = CellValues.InlineString; c.CellReference = cellRef; InlineString istr = new InlineString( new Text(cellValue)); c.AppendChild(istr); return c; }

Die Markup-Repräsentation eines Inline Strings würde folgendermaßen aussehen:

<x:c r="A1" t="inlineStr"> <x:is> <x:t>Der Zellwert als String</x:t> </x:is> </x:c>

Shared Strings sind etwas aufwändiger zu handhaben, da immer zuerst geschaut werden muss, ob der String als solcher schon in der Shared Strings Tabelle vorhanden ist bzw. diese überhaupt da ist. Das Grundgerüst für die Zelle sieht so aus:

private Cell CreateCellWithSharedString(string cellRef, string sharedString, SharedStringTablePart sstPart) { Cell c = new Cell(); c.CellReference = cellRef; c.DataType = CellValues.SharedString; c.CellValue = new CellValue(InsertSharedStringItem(sharedString, sstPart).ToString()); return c; }

Einen String in die Shared Strings Tabelle eintragen:

private static int InsertSharedStringItem(string newString, SharedStringTablePart sstPart) { // SharedStringTable erzeugen, falls nicht vorhanden if (sstPart.SharedStringTable == null) sstPart.SharedStringTable = new SharedStringTable(); // SharedStringTable durchsuchen. Wenn String vorhanden, Index zurück geben int i = 0; foreach (SharedStringItem ssi in sstPart.SharedStringTable.Elements<SharedStringItem>()) { if (ssi.InnerText == newString) return i; i++; } // String ist nicht da ==> SharedStringItem erzeugen sstPart.SharedStringTable.AppendChild (new SharedStringItem(new Text(newString))); sstPart.SharedStringTable.Save(); return i; }

Die Markup-Repräsentation eines Shared Strings würde folgendermaßen aussehen:

<c r="D1" t="s"> <v>0</v> </c>

Der Verweis zeigt auf den String an der Position 0 in der Shared Strings Tabelle, die im Markup so aussehen könnte:

<sst xmlns="http://schemas...spreadsheetml/2006/main" count="5" uniqueCount="3"> <si> <t>Microsoft</t> </si> <si> <t>Jens Häupel</t> </si> <si> <t>Der Zellwert als String</t> </si> </sst>

[ Fortsetzung folgt ]

Heute letzter Tag der Kinect-Verlosung auf MPR

15.12.2010 11:44:19 | Peter Kirchner

kinect_smallSelbst eine Verlängerung geht einmal zu Ende. Wir freuen uns, dass so Teilnehmer in den letzten Tage noch mitgemacht haben. Das zeigt uns, dass es wohl richtig war noch einmal 10 Tage draufzulegen. Nichtsdestotrotz ist heute der letzte Tag unserer Verlosung auf MPR.

Wenn Sie also teilnehmen möchten, so ist heute die letzte Gelegenheit dafür!

  1. Registrieren Sie sich auf Microsoft Platform Ready.
  2. Tragen Sie Ihre Lösung unter "Mein MPR" ein.
  3. Bestätigen Sie für Ihre Lösung die Kompatibilität mit Windows Azure, SQL Server 2008 R2 oder SharePoint 2010.
  4. Lesen Sie die Teilnahmebedingungen.
  5. Schreiben Sie uns eine E-Mail, dass Sie an unserer Verlosung teilnehmen möchten.
    • Vergessen Sie in der E-Mail nicht, Ihren Firmennamen anzugeben, den Sie auf Microsoft Platform Ready registriert haben.

Viel Glück an alle, die bereits teilgenommen haben, und natürlich auch an alle, die auf den letzten Drücker mitmachen werden. ;-)

Refactoring: Switch durch Commands ersetzen

14.12.2010 23:56:00 | Jan Christian Selke


Vor Kurzem war es notwendig, bestehenden Quellcode zu erweitern. Eine der entscheidenden Änderungen bestand darin, Prozessablauflogik durch eine neue Variante zu erweitern. Dabei bestand die Möglichkeit eines meiner bevorzugten Refactorings durchzuführen: Das Ersetzen von Conditional Dispatch durch Commands.
Bei meinen Arbeiten bin ich auf ein Konstrukt gestoßen, das ich als nicht besonders hübsch und elegant erachte; Viel entscheidender aber, es fördert weder die Wartbarkeit noch die Erweiterbarkeit. Es handelte sich um einen switch-Block, der stark vereinfacht etwa dem Folgenden entsprach.
public class WorkItem
{
private ItemSubType itemType;
public ItemSubType SubType { get; private set; }

public void Process()
{
switch(this.itemType)
{
case ItemSubType.Simple:
// do something simple
break;
case ItemSubType.Complex:
// do something complex
break;
default:
// just do something
}
}
}

Nicht nur, dass die Klasse bei jeder Erweiterung aufs Neue angefasst werden muss und damit dem OCP widerspricht, die Methode Process erfüllt damit auch noch mehrere Aufgaben. Also nutzte ich die Möglichkeit, um hier ein wenig zu entkoppeln. Zuerst war die Frage zu klären, spezialisierte WorkItem Klassen anlegen oder einfach die Prozesslogik auslagern. Da sich die Änderungen ausschließlich auf den switch-Block beschränkten, entschied ich mich für die Auslagerung.

Für jeden SubTyp wurde eine Prozessor Klasse angelegt, die die Schnittstelle IItemProcessor implementiert.

public interface IItemProcessor
{
void Process(WorkItem item);
}

public class SimpleTypeProcessor : IItemProcessor
{
public void Process(WorkItem item)
{}
}

public class ComplexTypeProcessor : IItemProcessor
{
public void Process(WorkItem item)
{}
}

public class NulloProcessor : IItemProcessor
{
public void Process(WorkItem item)
{}
}

Der NulloProcessor entspricht hierbei der Implementierung des Null-Object-Patterns. Der nächste Schritt wäre das Zuweisen des richtigen Processors zur richtigen Zeit. Dazu wird in der Regel eine Factory Klasse genutzt.

public void Process()
{
var processor = ProcessorFactory.GetProcessor(this.subType);
processor.Process(this);
}

So hätte ich die Bedingungen zwar aus dem WorkItem heraus genommen, aber nur in die Factory ausgelagert und dort den switch-Block, der immer wieder erweitert werden müsste.

Wie wäre es also, der WorkItem Klasse die Prozessoren von außen herein zu geben und jeden Processor für sich selbst entscheiden lassen, ob er etwas zu tun hat?!

public class WorkItem
{
IList<IItemProcessor> processorList;
public WorkItem(IList<IItemProcessor processors, ...)
{
this.processorList = processors;
// something more
}
...
public void Process()
{
this.processorList.Where(x => x.CanProcess(this)).Each(proc => proc.Process(this));
}
}

public class SimpleTypeProcessor : IItemProcessor
{
public bool CanProcess(WorkItem item)
{
return item.SubType == ItemSubType.Simple;
}

public void Process(WorkItem item)
{
// Do something simple
}
}

Die Abfrage auf CanProcess empfand ich noch als zu viel Rauschen. Die einzelnen Prozessoren können doch bei Aufruf ihre Zuständigkeit selbst überprüfen.

public class SimpleTypeProcessor : IItemProcessor
{
public void Process(WorkItem item)
{
if(item.SubType != ItemSubType.Simple) return;
// Do something simple
}
}

Innerhalb der WorkItem Klasse wird dann einfach an alle Prozessoren “ge-broadcastet”…

public void Process()
{
processorList.Each(processor => processor.Process(this));
}

Auf diese Weise habe ich meine Anpassungen letztlich durchgeführt und bin (noch?) recht zufrieden damit.

Open XML Dateien aufbauen und verändern (Teil 1)

14.12.2010 16:28:28 | Jens Häupel

Der Umgang mit Strings in Excel

Nach längerer Zeit der Funkstille, begründet durch emsiges Herumreisen, gemeinsames Herumsitzen in eingeschneiten Fliegern auf dem Rollfeld sowie sonstiger allgemeiner vorweihnachtliche Hatz, will ich mir wieder etwas Zeit für die Technologie nehmen. Gerade in letzter Zeit wurde an einigen Stellen – wohl im Zuge der Erneuerung – die Frage in Richtung Open XML gelenkt. Oftmals sollten Dateien (Reports) aufgebaut oder ergänzt werden. Diesem Thema will ich mich in den nächsten Wochen widmen.

Da Excel-Dateien eine Art dreidimensionaler Struktur aufweisen – Zeilen, Spalten und Tabellen), verkompliziert sich deren Aufbau im Vergleich zu Word etwas. Um Speicherplatz zu sparen, wird eine Shared Strings-Tabelle verwendet, die für alle in einer Arbeitsmappe enthaltenen Tabellen zuständig ist. Der gesamte Inhalt einer Zelle innerhalb einer Tabelle entspricht einem Shared String, sofern er nicht eine Formel oder Zahl darstellt. In der Reihenfolge des Anlegens werden die Strings in der Shared Strings-Tabelle indiziert und über den Indexwert in der Zelle verlinkt.

Daneben gibt es noch Inline Strings, also Zeichenketten, die direkt innerhalb der Zelle in deren Markup gespeichert werden. Inline Strings werden von Excel allerdings automatisch in Einträge in der Shared Strings-Tabelle umgewandelt. Welchen Sinn haben sie dann? Nun, sie stellen einen einfachen Weg dar, Tabellen aufzubauen, ohne sich um die Komplexität der (externen) Shared Strings-Tabelle kümmern zu müssen.

Neben der WindowsBase Assembly wird die Bibliothek für das Open XML SDK 2.0 benötigt. Diese liefert zum einen eine höhere Abstraktion als die Methoden von System.IO.Packaging und zum anderen werden die Elemente des Markups (WordML, SpreadsheetML, etc.) als Objekte zur Verfügung gestellt. Damit werden viele Fehler (sofern es denn Leute gibt, die welche machen…) in die Compiletime verlagert (statt sie zur Laufzeit zu bekommen).

clip_image002

Wir unterscheiden zwischen den Parts, die eine logische Einheit innerhalb eines Open XML Files darstellen (Workbook, Worksheet) und dem XML, das die Repräsentation des eigentlichen Inhalts der Tabellen ist. Beides muss angelegt werden. Das grobe Gerüst ist hier zu sehen:

private void CreateExcelFile(string FName)
{

  using (SpreadsheetDocument sDoc = 
    
SpreadsheetDocument.Create(FName, SpreadsheetDocumentType.Workbook))

  {
    WorkbookPart partWB = sDoc.AddWorkbookPart();

   // Formatvorlagen hinzufügen:
   WorkbookStylesPart partStyles = …

   // Basisdokument Workbook.xml anlegen:
   Workbook wb = new Workbook(new Sheets());
   wb.Save(partWB);

   // Basis-WorksheetPart hinzufügen:
   WorksheetPart partWS = 
     
InsertWorksheetPart(partWB, "Open XML SDK Samples");

   // SharedStringTable hinzufügen:
   SharedStringTablePart partSharedStrings = 
     
partWB.AddNewPart<SharedStringTablePart>();

   // worksheet.xml erzeugen:
   Worksheet ws = new Worksheet();
   SheetData sd = new SheetData();
   ws.AppendChild(sd);

   // Zeilenweise Zellen hinzufügen:
   Row r1 = new Row();
   r1.RowIndex = 1;
   r1.AppendChild( +++ );

   Row r3 = new Row();
   r3.RowIndex = 3;
   r3.AppendChild( +++ );
   
  
sd.AppendChild(r1);
   sd.AppendChild(r3);
   ws.Save(partWS);

}
}

Excel verlangt nach einer Datei, in der die Formatvorlagen definiert sind, dem WorkbookStylesPart. Ich gehe davon, dass keiner diesen Part von Anfang an erzeugt, sondern Excel als Templating Tool verwendet. Man nehme einfach eine Excel-Arbeitsmappe, die die gewünschte Formatierung enthält (bzw. formatiert Teile der Tabelle wie gewünscht). Das kann auf zwei Arten in unser Programm integriert werden:

Möglichkeit 1:

Man öffnet diese Excel-Datei mit dem Open XML SDK 2.0 Productivity Tool und lässt vom Reflector den Code erzeugen.

clip_image004

Der Aufruf sieht dann folgendermaßen aus:

WorkbookStylesPart partStyles = partWB.AddNewPart<WorkbookStylesPart>();
partStyles.Stylesheet = GenerateStylesSheet();
partStyles.Stylesheet.Save(partStyles);


Möglichkeit 2:

Man gibt der Excel-Datei den Suffix .zip und öffnet den Container. Im Ordner \xl befindet sich die Datei styles.xml. Diese wird in die Ressourcen des eigenen Programms aufgenommen.

image

Der Aufruf sieht dann folgendermaßen aus:

WorkbookStylesPart partStyles = partWB.AddNewPart<WorkbookStylesPart>();
XmlDocument stylesXML = new XmlDocument();
stylesXML.LoadXml(Properties.Resources.styles);
using (StreamWriter streamStylesXML = 
new StreamWriter(partStyles.GetStream(FileMode.Create, FileAccess.Write)))
{
   stylesXML.Save(streamStylesXML);
}

Die weitere Vorgehensweise ist schnell erklärt: Das Workbook.xml enthält Informationen über in der Arbeitsmappe enthaltene Tabellen (Worksheets). Gespeichert wird sie im Workbook Part. Danach muss mindestens eine Tabelle (Worksheet.xml) angelegt und im Worksheet Part gespeichert werden.

Wichtig in der worksheet.xml ist das sheetdata Element. An dieses werden die Zeilen angehängt, die wiederum die Zellen enthalten.

Die Shared Strings-Tabelle wird ebenfalls schon hier angelegt, wir benötigen sie erst später.

[ Fortsetzung folgt ]

Windows Phone recipes – Open source projects

14.12.2010 15:23:00 | Patric Schouler

Windows Phone recipes are open source (MSPL) projects aimed at helping Windows Phone developers with their Windows Phone applications. Recipes are usually common patterns for topics that require some attention. The idea is to provide a sample with some reusable code that can be reused later and modified to fit other similar scenarios. Developers are more than welcome to use them as is, or to change them as they see fit.

Windows Phone Recipes – Helping the Community

Free ebook: Moving to Microsoft Visual Studio 2010

14.12.2010 13:38:23 | Christian Binder

Das Buch Thematisiert den Umstieg von älteren Visual Studio Versionen nach Visual Studio 2010.

Hierbei fokussiert Teil 1 den Umstieg von Visual Studio 2003 nach Visual Studio 2010.
Teil 2  von Visual Studio 2005 nach Visual Studio 2010.
Teil 3  von Visual Studio 2008 nach Visual Studio 2010.

Und passend zur Weihnachtszeit ist der Download kostenfrei.

Viel Spass
Chris

Mission Qualitätssicherung in SharePoint Projekten – Testen von SharePoint mit Typemock Part 4

14.12.2010 00:45:12 | Thorsten Hans

Im vierten Teil der Artikelserie möchte ich mich der Call-Verification widmen. Gerade in der SharePoint Entwicklung muss man beim Thema Unittesting etwas differenzieren. In SharePoint Projekten entwickelt man meistens sehr hart gegen die SharePoint API. Oftmals besteht die Herausforderung darin, die vorhandene SharePoint API richtig zu steuern, anstatt alles in CustomCode selbst zu realisieren.

SearchInsbesondere das Mocking und Testing gestaltet sich in solchen Lösungen nicht einfach, denn man muss an sehr vielen Stellen darauf vertrauen, dass der eigene Code ab einem bestimmten Level die SharePoint API richtig steuert.

Falls man dennoch eine gewisse Sicherheit haben möchte, kann man mit Typemock Annahmen treffen, die spezifizieren ob eine Methode X aufgerufen wurde, oder eben nicht.

 

Validieren ob eine Methode aufgerufen wurde

Anhand dem wohl simpelsten SharePoint Coding Beispiel kann man recht einfach verstehen was gemeint ist. Wenn man den Titel der aktuellen Seite anpasst, werden durch einen Call der Methode SPWeb.Update()  die Changes an den SharePoint Server gesendet und persistiert.

Der Test für dieses einfache Szenario könnte wie folgt aussehen

   1:  [TestFixture]
   2:  public class When_SetWebCaption_Is_Called
   3:  {
   4:   
   5:      [Test, Isolated]
   6:      public void SPWeb_Update_Should_Be_Called()
   7:      {
   8:          Isolate.Fake.StaticMethods<SPContext>(Members.ReturnRecursiveFakes);
   9:   
  10:          var sysUnderTest = new WebTitleChanger();
  11:          sysUnderTest.SetWebCaption("My new web");
  12:   
  13:          Isolate.Verify.WasCalledWithAnyArguments(() => SPContext.Current.Web.Update());
  14:      }
  15:  }

 

Interessant ist hierbei in Zeile 13 der Call auf Isolate.Verify.WasCalledWithAnyArguments Typemock validiert demnach zur Testlaufzeit ob ein Call – egal mit welchen Argumenten – auf die Methode Update der SPContext.Current.Web Instanz gemacht wurde.

Analog dazu gibt es natürlich auch noch weitere Methoden um Call-Verification durchzuführen. So kann mittels

Isolate.Verify.WasCalledWithExactArguments()

sichergestellt werden dass genau die gewünschten Parameter an die Methode beim Call übergeben wurden.

   1:  [Test,Isolated]
   2:  public void AddList_Should_Be_Called_With_Correct_Parameters()
   3:  {
   4:      string title = "MyNewList";
   5:      string desc = "My new list";
   6:      SPListTemplateType templateType = SPListTemplateType.Links;
   7:      Isolate.Swap.AllInstances<SPContext>().With(
   8:           Isolate.Fake.Instance<SPContext>(Members.ReturnRecursiveFakes));
   9:   
  10:      Isolate.WhenCalled(() => SPContext.Current.Web.Lists[title]).WillReturn(null);
  11:      Isolate.WhenCalled(() => SPContext.Current.Web.Lists.Add(title,desc, templateType))
  12:          .WillReturn(Guid.NewGuid());
  13:   
  14:      var sut = new ListCreator();
  15:      sut.CreateList(title,desc,templateType);
  16:   
  17:      Isolate.Verify.WasCalledWithExactArguments(() => 
  18:          SPContext.Current.Web.Lists.Add(title, desc, templateType));
  19:  }

Hierbei wird in Zeile 17 definiert, dass der Test erst erfolgreich ist wenn SPContext.Current.Web.Lists.Add mit entsprechenden Argumenten aufgerufen wurde. Auch für den Fall, dass nur bestimmte Parameter der Methode von Interesse sind, bietet Typemock hier eine Lösung an. Die Methode WasCalledWithArguments stellt hier die korrekte Wahl dar.

Wenn der UnitTest AddList_Should_Be_Called_With_Correct_Parameters() zum Beispiel nur auf den Parameter title überprüfen sollte, würde der Test so aussehen

   1:  [Test,Isolated]
   2:  public void AddList_Should_Be_Called_With_Correct_Parameters()
   3:  {
   4:      string title = "MyNewList";
   5:      string desc = "My new list";
   6:      SPListTemplateType templateType = SPListTemplateType.Links;
   7:      Isolate.Swap.AllInstances<SPContext>().With(
   8:           Isolate.Fake.Instance<SPContext>(Members.ReturnRecursiveFakes));
   9:   
  10:      Isolate.WhenCalled(() => SPContext.Current.Web.Lists[title]).WillReturn(null);
  11:      Isolate.WhenCalled(() => SPContext.Current.Web.Lists.Add(title,desc, templateType))
  12:          .WillReturn(Guid.NewGuid());
  13:   
  14:      var sut = new ListCreator();
  15:      sut.CreateList(title,desc,templateType);
  16:   
  17:      var lists = SPContext.Current.Web.Lists;
  18:      Isolate.Verify.WasCalledWithArguments(() =>
  19:          lists.Add(title, desc, templateType))
  20:          .Matching(arguments=> arguments[0].Equals(title));
  21:  }

 

Bei dieser Call-Verification wird lediglich auf das erste Argument (Zeile 20) durch Verwendung der Matching Methode geschaut. Sobald die Methode mit dem gleichen Parameter an der Stelle 1 aufgerufen wurde gilt der Test als erfolgreich.

Achtung: Die Typemock API unterstützt für den Fall WasCalledWithArguments das Chaining des SUT nicht, daher wird die SPListCollection in Zeile 17 zwischengespeichert. Den entsprechenden Post findet Ihr hier im Typemock Forum.

 

Schlussendlich gibt es noch die Validierung ob eine Methode nicht aufgerufen wurde. Hierbei geht's wieder zurück zum ersten Beispiel. Ich möchte in diesem Fall einfach sicherstellen das SPWeb.Update nicht aufgerufen wird, wenn der übergebene Titel leer ist.

   1:  [Test, Isolated]
   2:  public void SPWeb_Update_Was_Not_If_Title_Is_Null_Or_Empty()
   3:  {
   4:      Isolate.Fake.StaticMethods<SPContext>(Members.ReturnRecursiveFakes);
   5:   
   6:      var sysUnderTest = new WebTitleChanger();
   7:      sysUnderTest.SetWebCaption(null);
   8:      sysUnderTest.SetWebCaption(String.Empty);
   9:      Isolate.Verify.WasNotCalled(() => SPContext.Current.Web.Update());
  10:  }

 

Call-Verification als nützliches Helferlein

Die Call-Verifications von Typemock bieten gerade im SharePoint Kontext eine sehr gute Unterstützung an um UnitTests zu schreiben. Drei einfache Methoden werden hierzu von Typemock bereitgestellt, welche es zu lernen gilt. Einzig der kleine Workaround für den WasCalledWithArguments Fall ist etwas unschön, aber dennoch ein coole Feature.

 

Technorati-Markierungen: ,,,
DotNetKicks-DE Image

Buch: Zeitmanagement mit Microsoft Outlook

13.12.2010 13:35:00 | Oliver Scheer

Weihnachtszeit im Griff : „Zeitmanagement mit Microsoft Outlook“ kostenlos herunterladen.

Nur noch bis 15.12. unter http://zeit.microsoft-press.de

image



Windows Phone 7: Grid style listbox

11.12.2010 11:16:00 | Patric Schouler

If you want to implement a grid for your Windows Phone 7 app you have to use a Listbox control because of the missing DataGrid at the Windows Phone 7 platform. A first idea for contsructing a Grid then could be to use the WrapPanel control in your ItemTemplate of the Listbox control. But if you do this, the data virtualization of the ListBox will be disabled (Virtualizing Data in Windows Phone 7 Silverlight Applications - Peter Torr's Blog - Site Home - MSDN Blogs). This will increase the loading time of your ListBox and results in a very poor UX handling. The problem is, that you can not use any complex data structures in the ItemTemplate at a Listbox for Windows Phone 7. Every line in the Listbox should be one data line. So a solution for developing a grid styled Listbox is to implement a RowAdapter class for your bounded data.

Here a implementation of a RowAdapter, I used in one of my projects:

public class RowAdapter<TItemType> : IList<IEnumerable<TItemType>>, INotifyCollectionChanged
    {
        private readonly IList<TItemType> _sourceList;
        private readonly int _columns;
 
        private class RowObject : IEnumerable<TItemType>
        {
            internal readonly RowAdapter<TItemType> Parent;
            internal readonly int StartIndex;
 
            public RowObject(RowAdapter<TItemType> parent, int startIndex)
            {
                Parent = parent;
                StartIndex = startIndex;
            }
 
            #region IEnumerable<TItemType> Members
 
            public IEnumerator<TItemType> GetEnumerator()
            {
                int limit = Parent._sourceList.Count;
                int end = Math.Min(StartIndex + Parent._columns, limit);
 
                for (int pos = StartIndex; pos < end; ++pos)
                {
                    yield return Parent._sourceList[pos];
                }
            }
 
            #endregion
 
            #region IEnumerable Members
 
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
 
            #endregion
        }
 
        public RowAdapter(IList<TItemType> sourceList, int columns)
        {
            if (null == sourceList)
                throw new ArgumentNullException("sourceList", Resource.RowAdapter_RowAdapter_sourceList_is_null);
            if (columns <= 0)
                throw new ArgumentOutOfRangeException("columns", Resource.RowAdapter_RowAdapter_ColumnsGreaterOne);
 
            // We require the source list to implement IList because we
            // need to know how many item there are
            _sourceList = sourceList;
            _columns = columns;
 
            var sourceNotify = sourceList as INotifyCollectionChanged;
            if (null != sourceNotify)
            {
                sourceNotify.CollectionChanged += OnSourceCollectionChanged;
            }
        }
 
        #region IList<IEnumerable<TItemType>> Members
 
        public int IndexOf(IEnumerable<TItemType> item)
        {
            var realItem = item as RowObject;
            if (null == realItem || !ReferenceEquals(realItem.Parent, this))
                return -1;          // It does not belong to this collection
 
            Debug.Assert(0 == realItem.StartIndex % _columns, "RowObject item has a wierd index");
            return realItem.StartIndex / _columns;
        }
 
        public void Insert(int index, IEnumerable<TItemType> item)
        {
            throw new NotSupportedException();
        }
 
        public IEnumerable<TItemType> this[int index]
        {
            get
            {
                if (index < 0 || index > Count)
                    return null;
 
                return InternalGetRow(index);
            }
            set
            {
                throw new NotSupportedException();
            }
        }
 
        public void RemoveAt(int index)
        {
            throw new NotSupportedException();
        }
 
        #endregion
 
        #region ICollection<IEnumerable<TItemType>> Members
 
        public void Add(IEnumerable<TItemType> item)
        {
            throw new NotSupportedException();
        }
 
        public bool Contains(IEnumerable<TItemType> item)
        {
            var realItem = item as RowObject;
            return null != realItem && object.ReferenceEquals(realItem.Parent, this);
        }
 
        public void CopyTo(IEnumerable<TItemType>[] array, int arrayIndex)
        {
            // I haven't implemented this. It is easy to implement if you need it
            throw new NotImplementedException();
        }
 
        public bool Remove(IEnumerable<TItemType> item)
        {
            throw new NotSupportedException();
        }
        public void Clear()
        {
            throw new NotSupportedException();
        }
 
        public int Count
        {
            get
            {
                return (_sourceList.Count + (_columns - 1)) / _columns;
            }
        }
 
        public bool IsReadOnly
        {
            get { return true; }
        }
 
        #endregion
 
        #region IEnumerable<IEnumerable<TItemType>> Members
 
        public IEnumerator<IEnumerable<TItemType>> GetEnumerator()
        {
            for (int i = 0; i < Count; ++i)
            {
                yield return InternalGetRow(i);
            }
        }
 
        #endregion
 
        #region IEnumerable Members
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
 
        #endregion
 
        #region INotifyCollectionChanged Members
 
        public event NotifyCollectionChangedEventHandler CollectionChanged;
 
        private void FireCollectionChanged()
        {
            
            var handler = CollectionChanged;
            if (null != handler)
            {
                handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            }
        }
 
        private void OnSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            FireCollectionChanged();
        }
 
        #endregion
 
        private RowObject InternalGetRow(int index)
        {
           return new RowObject(this, index * _columns);
        }
    }

Join the dark side – May the source be with you

11.12.2010 00:57:03 | Rainer Schuster

I’m a dark theme user since 2007. I really can’t imagine having used a light theme *sigh*. Please stop! Its all about customization on my desktops DEV tools. VIM, Visual Studio 2008 and 2010, WING, Eclipse, SharpDevelop, Notepad++ … There are plenty of options to tweak the colors to your liking.

Basics

Color theory is really helpfull for getting started with color customizing your tools. The color wheel did a great job in reflecting my knowledge on colors. My themes are currently build upon 4 colors and 5 gray scales, currently using 2 to 3 of theme having a total of 7 different tones.

 image image

Have a look at the color table where I’m using the colors:

image

 

You can find the kuler color profiles from the pictures above at http://kuler.adobe.com/#themes/search?term=schuster-rainer and the color schemes at https://github.com/schuster-rainer/themes

 

Screenshots

VS2010

XAML, HTML (XML looks like the others)

image image

C#, IronPython

image image

F#

image 

Import for color scheme “Tools->Import and Export Settings …”

 

Import for Expression Dark Like VS2010 Theme - Theme AddIn needed “Theme –> Customize Colors –> Import Theme”

VIM

Boo,Clojure

image image

Python, Ruby

image image 

Installation according to your configuration - %userprofile%\vimfiles\colors - syntax files needed for the different languages

SharpDevelop 3

Boo

image

Installation: %userprofile%\AppData\Roaming\ICSharpCode\SharpDevelop3.0\modes\

WING, Powershell

image image

Future enhancements:

  • more languages for SharpDevelop 3 and 4
  • VS2008 and VS2010 (some tweaks, especially VB settings)
  • a scheme for Aptana
  • uhh I totally forgot Notepad++
DotNetKicks-DE Image

Microsoft Web Platform Installer mal anders erklärt

10.12.2010 16:47:29 | Peter Kirchner

Mit dem kostenfrei von uns angebotenen Web Platform Installer (Web PI) bleiben Sie immer auf dem Laufenden. Er hilft Ihnen, immer die aktuellen Komponenten unserer Web Plattform herunterzuladen und einzusetzen. Dazu gehören Internet Information Services (IIS), SQL Server Express, das .NET Framework und Visual Web Developer. Zusätzlich installieren Sie damit weit verbreitete, beliebte Open Source-, ASP.NET- und PHP-Webanwendungen.

Was gehört dazu?

clip_image001 Populäre Webanwendungen: Installieren Sie kostenfreie, beliebte und weit verbreitete ASP.NET- und PHP-Webanwendungen wie DotNetNuke und WordPress.

clip_image002         Das .NET Framework: Mit der aktuellen Version des .NET Framework erhalten Sie alle notwendigen Bestandteile für Ihre ASP.NET-Entwicklung.

clip_image003             Internet Information Services und Erweiterungen: Setzen Sie die neuste Version inklusive den IIS-Weberweiterungen wie den IIS-Mediaservices ein.

clip_image004                  SQL Server: Verwenden Sie SQL Server 2008 Express mit der Datenbank-Engine und den dazu gehörenden Datenbankwerkzeugen.

clip_image006              Visual Web Developer: Visual Web Developer Express ist eine kostenfreie, mit allen notwendigen Funktionen für Ihre Webentwicklung versehen Anwendung.

clip_image007         Extras und Zugaben: Ergänzend zu den oben genannten Produkten erhalten Sie mit dem Web PI die aktuelle Community-Version von PHP für Windows.

Video: Visual Studio 2010 mal etwas anders erklärt …

10.12.2010 15:11:11 | Oliver Scheer

Einstieg zur Workflow Foundation 4 : Überblick zu Activities

10.12.2010 11:49:00 | Gregor Biswanger

Bei diesem Blog-Post geht es darum einen groben Überblick von Activities zu gewinnen. Activities sind die Bausteine von Workflows. Somit spielen Sie eine zentrale Rolle. Ein Activity steht als Adapter für eigene Komponenten. Die anschließend wie Puzzleteile grafisch verwendet werden. Activities erwarten auch einen Datenstrom indem Daten hineinfließen (IN) und verarbeitet wieder herausfließen (OUT).

Trotzdem können Activities sich vom äußerlichen Verhalten enorm Unterscheiden. So dass man Sie in unterschiedliche Kategorien einordnen kann:

  • Atomic Unit of Work
  • Asynchronous Unit of Work
  • Long Running Unit of Work
  • Control Flow Activities
  • Infrastructure

 

Atomic Unit of Work

Diese Art von Activities führt die Logik im Workflow Thread synchron aus. Diese ist gegenüber anderen Activities gekapselt.

Eine solche Activity wird von der Basisklasse CodeActivity bereitgestellt.

Asynchronous Unit of Work

Diese Art von Activity ist dem “Atomic Unit of Work” sehr ähnlich. Er unterscheidet sich lediglich mit einer asynchronen Ausführung in einem getrennten Workflow Thread. Diese werden oft für Datenbankabfragen oder Datenzugriffe verwendet. Es ist für kurze Verarbeitungszeiten gedacht. Längere Verarbeitungszeiten die Tagelang andauern sollten vermieden werden.

Eine solche Activity wird von der Basisklasse AsyncCodeActivity bereitgestellt.

Long Running Unit of Work

Diese Activity ist für längere Zeiträume konzeptioniert. Oft spielt hierbei eine Abhängichkeit zu einer menschlichen Interaktion, die Tage andauern kann. Das kann zum Beispiel eine Fortsetzung der Bestellung sein. Dieses Activity wartet diesen Zeitraum ab und besetzt nicht den bestehenden Workflow Thread. Somit können in der Zwischenzeit auch andere Activities weiter agieren.

Eine solche Activity wird von der Basisklasse NativeActivity bereitgestellt.

Control Flow Activities

Diese Art von Activities kümmert sich um das Ausführen und Verwaltung von anderen Activities die in ihnen als Kinderelemente enthalten sind. Das von der WF4 bereitgestellte Sequence Activity ist eines von Ihnen. Die Verwaltung läuft zudem mit einem integrierten Zeitplan (schedule).

Eine solche Activity wird von der Basisklasse NativeActivity bereitgestellt.

 

Die Daten für Activities

Es gibt unterschiedliche Arten um Daten für Activities bereitzustellen und damit zu arbeiten. Für den Informationsaustausch unter einem Workflow werden Argumente (Arguments) und Variablen (Variables) verwendet.

 

Arguments

Argumente dienen als Input und Output für Activities und dienen als öffentliche Schnittstelle für deren Informationsaustausch. Input Argumente bestehen oft aus Parameter die beim starten der Workflow überreicht werden, oder Sie werden für eine Kommunikation unter den Activities selbst verwendet. Die generische Klasse InArgument<T> definiert Input Argumente.

Der Output steht für das verarbeitete Ergebnis das vom Activity geliefert wird. Der Output kann dann für eine weitere Verarbeitung an das nächste Activity überreicht werden oder durch den Workflow-Host den Wert an den Source-Code zurück geben. Die generische Klasse OutArgument<T> definiert Output Argumente.

 

(Beispiel zu Arguments: Einstieg zur Workflow Foundation 4 : Parameter übergeben)

 

Variables

Variablen dienen für Activities als interner Speicher. Daher können Variablen nur für Activities gesetzt werden. Bei “Control Flow Activities” können Variablen dann auch für Ihre Kinderelemente, dem nach für alle enthaltenen Activities dienen. Oft reicht allerdings bei der Implementierung ein Feld aus (bsp.: private _variable;). Die generische Klasse Variable<T> definiert eine Variable im Workflow-Thread.

(Beispiel mit der Verwendung von Variablen: Einstieg zur Workflow Foundation 4 : Activity selbst schreiben)

Windows Phone 7: Some links

10.12.2010 10:26:00 | Patric Schouler

App-Tipp: Windows Phone 7 eBook: Erste Schritte mit dem Phone

10.12.2010 08:39:29 | Kay Giza

Das kostenlose Windows Phone 7 eBook 'Erste Schritte mit dem Phone' ist ab sofort als Windows Phone 7-App erhältlich - kostenlos: Erste Schritte mit dem Phone. Das Online-Handbuch für Ihr Windows 7: Die ersten Schritte, die Einrichtung von Dienstkonten und Internetzugang, die Grundzüge von Kalender, Kontakten, Nachrichten und Internet Explorer, alles in Ihrer Handfläche als Windows Phone 7 App. In diesem Blogposting stelle ich diese App vor und gebe weiterführende Informationen.... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

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

Was ist eigentlich der Microsoft Web Platform Installer?

10.12.2010 08:09:10 | Oliver Scheer

In diesem Video erklären wir, wie Webentwickler mit Hilfe des Microsoft Web Platform Installers ihre Arbeitsumgebung mit wenigen Klicks in kurzer Zeit automatisch konfigurieren und installieren können -- unabhängig davon, ob sie ASP.NET oder php-Webseiten erstellen möchten, basierend auf einer Vielzahl von Open Source Frameworks wie Wordpress, Drupal, DotNetNuke und viele weitere mehr.
Weitere Informationen zum Microsoft WebPI und zur Microsoft Web Plattform sowie den Download-Link finden Sie unter www.microsoft.com/web

clip_image001

Link zum Video: http://www.youtube.com/watch?v=Qczzwpuz9OM

Mit dem kostenfrei von uns angebotenen Web Platform Installer (Web PI) bleiben Sie immer auf dem Laufenden. Er hilft Ihnen, immer die aktuellen Komponenten unserer Web Plattform herunterzuladen und einzusetzen. Dazu gehören Internet Information Services (IIS), SQL Server Express, das .NET Framework und Visual Web Developer. Zusätzlich installieren Sie damit weit verbreitete, beliebte Open Source-, ASP.NET- und PHP-Webanwendungen.

Was gehört dazu?

clip_image001

Populäre Webanwendungen: Installieren Sie kostenfreie, beliebte und weit verbreitete ASP.NET- und PHP-Webanwendungen wie DotNetNuke und WordPress.

clip_image002      

Das .NET Framework: Mit der aktuellen Version des .NET Framework erhalten Sie alle notwendigen Bestandteile für Ihre ASP.NET-Entwicklung.

clip_image003            

Internet Information Services und Erweiterungen: Setzen Sie die neuste Version inklusive den IIS-Weberweiterungen wie den IIS-Mediaservices ein.

clip_image004                 

SQL Server: Verwenden Sie SQL Server 2008 Express mit der Datenbank-Engine und den dazu gehörenden Datenbankwerkzeugen.

clip_image006             

Visual Web Developer: Visual Web Developer Express ist eine kostenfreie, mit allen notwendigen Funktionen für Ihre Webentwicklung versehen Anwendung.

clip_image007         Extras und Zugaben: Ergänzend zu den oben genannten Produkten erhalten Sie mit dem Web PI die aktuelle Community-Version von PHP für Windows.



Video: Wir erklaeren den kostenlosen Microsoft Web Platform Installer (Web PI)

10.12.2010 07:45:14 | Kay Giza

Video: Wir erklären den Microsoft Web Platform Installer. In diesem Video wird erklärt, wie Webentwickler und Interessierte mit Hilfe des Microsoft Web Platform Installers ihre Arbeitsumgebung mit wenigen Klicks in kurzer Zeit automatisch konfigurieren und installieren können, unabhängig davon, ob sie ASP.NET oder PHP-Webseiten erstellen möchten, basierend auf einer Vielzahl von Open Source Frameworks wie Wordpress, Drupal, DotNetNuke und viele weitere mehr... [... jetzt das Video auf Giza-Blog.de anschauen...]

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

Privat: Ein Englischer Garten

09.12.2010 18:12:42 | Oliver Scheer

“Der Englische Garten in München, einer der weltgrößten Stadtparks, ist durch eine Stadtautobahn zweigeteilt. Das Projekt “ein EnglischerGarten” hat das Ziel, die Stadtautobahn in einen Tunnel zu legen und so die beiden Teile wieder zusammenzufügen. Werde Teil einer Community von Menschen, die sich zu EINEM Englischen Garten bekennen. Als Befürworter dieses Projekts kannst Du dich jetzt mit deinem Namen auf dem virtuellen Denkmal verewigen und so das Projekt unterstützen.

Wird das Projekt realisiert, wird auch das Denkmal real. Es wird im neu entstandenen Verbindungsteil des Englischen Gartens errichtet und dort für immer an Dich und alle diejenigen erinnern, die mit ihrem Commitment die Wiedervereinigung des Englischen Gartens unterstützt haben.” (Quelle: www.einenglischergarten.de)



Online: Das kostenlose Windows Phone 7 eBook "Erste Schritte mit dem Phone" als WP7 App

09.12.2010 18:09:20 | Peter Nowak

Das kostenlose Windows Phone 7 eBook "Erste Schritte mit dem Phone" von Andreas Erle, meinem geschätzten Windows Phone MVP Kollegen, kann ab sofort (wenn auch noch nicht in der Suche zu finden) unter diesem Link heruntergeladen werden: zune://navigate/?appID=528ed186-a6fe-df11-9264-00237de2db9e

Wieso ist dies erwähnenswert, wo es doch so viele Apps gibt, die erscheinen?
Nicht nur der Inhalt ist Klasse, sondern es ist einfach Fakt, dass es so gesehen “meine” erste App ist, die entwickelt wurde. Dabei ist klar, dass es noch Verbesserungspotential gibt, aber für die Zeit, in welcher es entwickelt wurde ist es super.
Vielen Dank nochmal an Patrick Getzmann, Tim Schmitz und Sebastian Jäger, die hierbei unterstützt haben.



This posting is provided "AS IS" with no warranties, and confers no rights.

Buch: Entwickeln fuer Windows Phone 7, Architektur, Frameworks, APIs

09.12.2010 13:12:37 | Kay Giza

Das Buch 'Entwickeln für Windows Phone 7: Architektur, Frameworks, APIs' von Patrick Getzmann (MVP), Simon Hackfort und Peter Nowak (MVP) halte ich druckfrisch in meinen Händen. Es liefert auf 600 Seiten geballtes Know-how rund um die Software-Entwicklung für das Windows Phone 7. Das Buch zeigt Ihnen, wie Sie attraktive Anwendungen und Spiele für Windows Phone 7 erstellen und diese auf dem Marketplace bereitstellen. Auch die Migration bestehender XNA-Spiele und Silverlight- oder Windows Mobile-Anwendungen wird behandelt. In diesem Blogeintrag gibt es eine kurze Vorstellung des Buch sowie weiterführende Informationen... [... mehr]

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

Event: Beyond Tellerrand

09.12.2010 09:44:36 | Oliver Scheer

beyond tellerrand // mobileDer Faszination mobiler Geräte und mobiler Anwendungen kann sich kaum jemand entziehen. Mit allen Vor- und Nachteilen... Doch die Auswahl ist mit Air über Android und iOS bis hin zu Windows Phone 7 groß. Und welche Plattform ist da dann auch langfristig die Richtige? Welche Gemeinsamkeiten gibt es und welche Unterschiede?

Das sind die Themen die vermutlich nicht nur uns (die Veranstalter der beyondtellerrand) bewegen und darum starten die Veranstalter mit beyond tellerrand – mobile ihre erste Konferenz rund um das Thema mobile Anwendungsentwicklung. Diese Veranstaltung stellt nicht nur alle wichtigen Plattformen und den Entwicklungsprozess dafür vor, sondern führt auch übergreifend in die gestalterischen und technischen Konzepte ein. Ganz klar, an Inspiration darf es dabei auch nicht mangeln. Wer also diesen Zug nicht verpassen möchte, der sollte dabei sein.

Wann: 7. Februar 2011 in Köln

Mehr Informationen: http://www.beyondtellerrand.com/



Neue Inhalte : Visual Studio 2010 ALM Pivot

09.12.2010 08:41:00 | Christian Binder

Das Visual Studio ALM Pivot soll die erste Orientierung vereinfachen, Inhalte rund um das Thema zentral zu finden.

Visual Studio ALM Pivot

Dazu gekommen sind Webacasts als auch die Guidance Projekte der TFS Rangers:

Visual Studio 2010 Modellierung mit UML
Visual Studio 2010 Testing aus der Perspektive des Entwicklers
Team Foundation Server 2010 Installation (Single Server)
Lizenzgrundlagen von Visual Studio 2010 mit MSDN
Visual Studio 2010 TFS Upgrade Guide
Visual Studio TFS Branching Guide 2010
Visual Studio 2010 Architecture Guidance
Visual Studio 2010 Database Projects Guidance
Visual Studio 2010 TFS Requirements Management Guidance

Zudem habe ich Euer Feedback umgesetzt, dass das Pivot in der Breite nicht mehr durch mein Blog Layout limitiert ist.
Über zusätzliches Feedback würde ich mich freuen :-)

Viel Spass
Chris

Die Videos der Woche KW 48

08.12.2010 21:41:39 | Oliver Scheer

Mission Qualitätssicherung in SharePoint Projekten – Testen von SharePoint mit Typemock Part 3

08.12.2010 17:49:45 | Thorsten Hans

Ein alltägliches Szenario bei der Entwicklung ist die Verwendung von Indexern. Indexer bieten schnellen und einfachen Zugriff auf Elemente einer Liste.

   1:  var list = SPContext.Current.Web.Lists["Kontakte"]

Auch an dieser Stelle kann man dies in Unittests dank Typemock sehr einfach faken und dadurch sich auf die Tests der eigenen Implementierung kümmern. Analog zum ersten Beispiel werden hierzu zunächst die gewünschten Typen gefaket, bevor es an den Indexer selbst geht. Als Anwendungsszenario soll auch hier eine einfache UserStory dienen.

Als Mitarbeiter der Contoso IT-Abteilung möchte ich eine neue generische Liste ueber ein WebPart erstellen, sofern keine Liste mit dieser Bezeichnung existiert.

Demnach lassen sich folgende Test-Cases ableiten

   1:  [TestFixture]
   2:  class When_CreateList_On_ListCreator_Is_Called
   3:  {
   4:      [Test]
   5:      [Isolated]
   6:      public void It_Should_Create_A_List_When_A_Name_Is_Passed()
   7:      {
   8:         //..        
   9:      }
  10:   
  11:      [Test]
  12:      [Isolated]
  13:      public void It_Should_Raise_An_Argument_Exception_When_An_Existing_Name_Is_Passed()
  14:      {
  15:         //..  
  16:      }
  17:  }

Da bei diesem einfachen Szenario in beiden Methoden Fakeobjekte von Typemock benoetigt werden, bietet es sich an sowohl auf TestFixtureSetUp als auch auf TestFixtureTearDown zurückzugreifen.

Daher sollte die Testklasse wie folgt angepasst werden

   1:  [TestFixture]
   2:  class When_CreateList_On_ListCreator_Is_Called
   3:  {
   4:   
   5:      [TestFixtureSetUp]
   6:      public void Setup()
   7:      {
   8:   
   9:      }
  10:   
  11:      [Test]
  12:      [Isolated]
  13:      public void It_Should_Create_A_List_When_A_Name_Is_Passed()
  14:      {
  15:          
  16:      }
  17:   
  18:      [Test]
  19:      [Isolated]
  20:      public void It_Should_Raise_An_Argument_Exception_When_An_Existing_Name_Is_Passed()
  21:      {
  22:          
  23:      }
  24:   
  25:      [TestFixtureTearDown]
  26:      public void Teardown()
  27:      {
  28:   
  29:      }       
  30:  }

 

Da in den beiden Testmethoden unterschiedliche verhalten vom Indexer auf SPContext.Current.Web.Lists[] erwartet werden, sollte man sich bemühen, den Standardfall im Setup zu implementieren und nur die Ausnahmefälle dann nochmals in den einzelnen Tests zu definieren.

   1:  [TestFixture]
   2:  class When_CreateList_On_ListCreator_Is_Called
   3:  {
   4:      String listName = "MyNewList";
   5:      [TestFixtureSetUp]
   6:      public void Setup()
   7:      {
   8:          Isolate.Swap.AllInstances<SPContext>().With(
   9:           Isolate.Fake.Instance<SPContext>(Members.ReturnRecursiveFakes));
  10:   
  11:          Isolate.WhenCalled(() => SPContext.Current.Web.Lists[listName]).WillReturn(null);
  12:          Isolate.WhenCalled(() => SPContext.Current.Web.Lists.Add(listName, "", 
  13:              SPListTemplateType.GenericList)).WillReturn(Guid.NewGuid());
  14:      }
  15:  }

 

In Zeile 8 wird wie im letzten Beispiel zunächst der SPContext gemockt, bevor in den Zeilen 11 und 12 sowohl das Indexer-Verhalten, als auch das Methoden-Verhalten von SPListCollection definiert wird.

Zeile 11 besagt, dass sobald der Indexer der von SPContext.Current.Web.Lists mit dem Wert aus der Variable listName (Zeile 4) aufgerufen wird null – Also quasi keine List – zurück gibt.

Somit kann der erste Test wie folgt implementiert werden

 

   1:  [Test]
   2:  [Isolated]
   3:  public void It_Should_Create_A_List_When_A_Name_Is_Passed()
   4:  {
   5:      var sut = new ListCreator();
   6:      sut.CreateList(listName);
   7:      var lists = SPContext.Current.Web.Lists;
   8:      Isolate.Verify.WasCalledWithArguments(() => lists.Add(listName, "",
   9:             SPListTemplateType.GenericList)).Matching((a) => (String)a[0] == listName);
  10:  }

 

Um diesen Test grün zu bekommen, muss mindestens folgendes innerhalb der Klasse ListCreator vorgenommen werden.

   1:  public void CreateList(String listName)
   2:  {
   3:     SPContext.Current
   4:      .Web
   5:      .Lists
   6:      .Add(listName, String.Empty, SPListTemplateType.GenericList);
   7:  }

 

Schauen wir uns nun aber den zweiten Test an, so kommen wir an die Stelle, wo auf den Indexer der SPListCollection Klasse zugegriffen wird. Um wie in diesem Testcase gefordert, sicherzustellen dass bereits eine Liste mit dem gefordertem Namen existent ist, muss das Fake-Verhalten für den Indexer in diesem konkreten Test angepasst werden.

   1:  [Test]
   2:  [Isolated]
   3:  public void It_Should_Raise_An_Argument_Exception_When_An_Existing_Name_Is_Passed()
   4:  {
   5:      var sut = new ListCreator();
   6:      String fakeListName = "ExistingListName";
   7:      var fakeList = Isolate.Fake.Instance<SPList>(Members.ReturnRecursiveFakes);
   8:      Isolate.WhenCalled(() => SPContext.Current.Web.Lists[fakeListName])
   9:          .WithExactArguments()
  10:          .WillReturn(fakeList);
  11:   
  12:      var lists = SPContext.Current.Web.Lists;
  13:   
  14:      Assert.Throws<ArgumentException>(() => sut.CreateList(fakeListName));
  15:  }

Zunaechst wird hierbei in Zeile 7 eine FakeInstanz von einer SharePoint Liste SPList erstellt, welche danach in Zeile 8 als Rückgabewert für einen Indexerzugriff mit dem Parameter fakeListItem (Zeile 8) angegeben wird.

Um auch den zweiten Test grün zu bekommen, muss die Implementierung der Methode CreateList() ein wenig angepasst werden.

   1:  public void CreateList(String listName)
   2:  {
   3:      if (SPContext.Current.Web.Lists[listName] != null)
   4:          throw new ArgumentException("List already exists.");
   5:      SPContext.Current
   6:        .Web
   7:        .Lists
   8:        .Add(listName, String.Empty, SPListTemplateType.GenericList);
   9:  }

 

Schlussendlich fehlt noch die Implementierung der Methode Teardown in der Testklasse. Im Teardown sollte die CleanUp Methode der Isolate Klasse von Typemock aufgerufen werden, um sicherzustellen, dass sämtliche gefakten Resourcen freigegeben werden.

 

   1:  [TestFixtureTearDown]
   2:  public void Teardown()
   3:  {
   4:      Isolate.CleanUp();
   5:  }       

 

Dieses einfache Beispiel zeigt, wie man Indexer im SharePoint Context mocken kann und deren Verhalten aus unterschiedlichen Testkontexten heraus beeinflussen kann.

Zum Schluss hier noch das Bildchen auf das alle TDD’ler immer warten

2

Demnach viel Spaß beim Testen von SharePoint Code… und… Fortsetzung folgt!

 

Technorati-Markierungen: ,,,
DotNetKicks-DE Image

Nach VS/TFS Sp1 Beta ist jetzt auch das TFS 2010 und Project Server Integration Feature Pack Beta verfügbar

08.12.2010 10:47:43 | Christian Binder


Alle Downloads sind in der MSDN Subscription bereits verfügbar. VS/TFS Beta Sp1 werden bis Ende der Woche als Public Download unter folgenden links verfügbar sein:

VS 2010 SP1 Beta (Es gibt einen neuen Client für die VS Hilfe :-) )
TFS 2010 SP1 Beta

Wer nach einer Liste der TFS Sp1 Beta Bugs sucht wird in Brian’s Blog hier fündig, wobei die Liste nicht komplett ist. Da uns das Feedback zur Beta wichtig ist, gibt es eine SP1 Beta Umfrage. Bitte nutzen, es hilft dem Team :-)

Die TFS 2010 und Project Server Integration war als CTP bisher nur als VM verfügbar. Der Grund hierfür war, dass im TFS einige Änderungen notwendig waren, die jetzt im TFS SP1 Beta enthalten sind. Details zur Team Foundation Server 2010 und Project Server Integration Feature Pack Beta gibt’s hier. Wer die Project Server Integration Live sehen möchte, empfehle ich die Session von der TechEd 2010. Aaron und Christophe zeigen in zwei Szenarien, wie die Integration für agil und formal arbeitende Teams funktionieren kann. Fragen zur Beta kann man direkt im Team Foundation Server and Project Server Integration Forum platzieren, die PM’s wie Siddharth oder Christophe sind auch im Forum.

Hinweis: Zwei potentielle Setup Probleme mit der VS 2010 Sp1 Beta:
1) Das Setup prüft nicht korrekt, ob genügend Speicherplatzt für die Installation vorhanden ist. Ist aber einfach zu erkennen, da Windows sich über zu wenig Speicher beschwert.
2) Falls die Installation im Schritt VS10sp1-KB983509 abbricht und ein Rollback durchgeführt wird, lohnt es sich zu überprüfen, ob SQL 2008 SP1 (KB968369) installiert ist.

Chris

Download: Visual Studio 2010 Service Pack 1 (SP1)-Beta fuer VS Express, Professional, Premium und Ultimate

08.12.2010 08:59:12 | Kay Giza

VS2010 SP1 Beta: Das Service Pack 1 (SP1) für Visual Studio 2010 (für die Editionen Express, Professional, Premium und Ultimate) und .NET Framework 4 steht seit 7. Dezember 2010 in englischsprachigen Vorabversion zur Verfügung. Die Betaversion steht ab sofort allen Inhabern einer MSDN Subscription zum kostenlosen Download bereit, die ab Donnerstagabend, 09.12.2010, auch als öffentlicher Download aus dem Microsoft Downloadcenter heruntergeladen werden kann. Die VS2010 SP1 Beta ist mit einer sogenannten "Go Live-Lizenz" ausgestattet und darf somit lizenzrechtlich betrachtet bis zum 30. Juni 2011 bereits für den Produktionseinsatz verwendet werden. Fast heimlich veröffentlicht wurden zudem Visual Studio Team Foundation Server 2010 und Project Server Integration Feature Pack Beta. In diesem Blogeintrag erfahren Sie alle Neuigkeiten, Informationen, Download-Links und eine Übersicht aller verfügbaren Downloads vom 07.12.2010... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

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

Mission Qualitätssicherung in SharePoint Projekten–SPContext faken

08.12.2010 00:26:28 | Thorsten Hans

Sehr viele Lösungsansätze in SharePoint basieren auf dem SPContext Objekt, welches von der Microsoft.SharePoint Assembly im Namespace Microsoft.SharePoint bereitgestellt wird. Desto wichtiger ist es, dass man SPContext gut durch ein Mockobjekt faken kann, um dadurch keine Abhängigkeit im UnitTest zu haben.

Als Beispiel fungiert folgende einfache Anforderung

Als Mitarbeiter der Contoso IT-Abteilung möchte ich den Titel der aktuellen SharePoint-Seite über ein WebPart anpassen können, um nicht die SiteSettings aufrufen zu müssen.

Environment Settings

In allen Posts werde ich folgendes Setup verwenden

  • Visual Studio 2010
  • Typemock Isolator for SharePoint 6.0.5
  • nUnit 2.5.8
  • SharePoint 2010

Assembly-Verweise

Um das folgende Beispiel nachstellen zu können,  müssen im Testprojekt Assemblyverweise hinzugefügt werden

  • nunit.framework.dll
  • TypeMock.dll
  • Typemock.ArrangeActAssert.dll
  • Microsoft.SharePoint.dll

Test-First

Ausgehend von der oben genannten UserStory lässt sich folgender Test ableiten

   1:  [TestFixture]
   2:  class When_WebTitleChanger_ChangeButton_Is_Pressed
   3:  {
   4:       
   5:    [Test]
   6:    public void And_Title_Is_Passed_The_Webs_Title_Should_Be_Updated()
   7:    {
   8:        //..
   9:    }

Damit Typemock funktioniert, muss die Testmethode zusätzlich mit dem IsolatedAttribute von Typemock dekoriert werden. Demnach sehen Klassen- und Methodensignatur wie folgt aus

   1:  [TestFixture]
   2:  class When_WebTitleChanger_ChangeButton_Is_Pressed
   3:  {
   4:   
   5:      [Test]
   6:      [Isolated]
   7:      public void And_Title_Is_Passed_The_Webs_Title_Should_Be_Updated()
   8:      {
   9:        //..
  10:      }
  11:  }

 

Die Testimplementierung

Die Testimplementierung mit Typemock sieht für diese einfache UserStory auch recht überschaubar aus

   1:  [Test]
   2:  [Isolated]
   3:  public void And_Title_Is_Passed_The_Webs_Title_Should_Be_Updated()
   4:  {
   5:      // Arrange
   6:      String newTitle = "My new Title";
   7:      Isolate.Swap
   8:          .AllInstances<SPContext>()
   9:          .With(Isolate.Fake
  10:          .Instance<SPContext>(Members.ReturnRecursiveFakes));
  11:       
  12:      Isolate.WhenCalled(()=>SPContext.Current.Web.Title)
  13:          .WillReturn(newTitle);
  14:      
  15:      var sut = new WebTitleChanger();
  16:      
  17:      // Act
  18:      sut.SetWebCaption(newTitle);
  19:   
  20:      // Assert
  21:      Assert.AreEqual(newTitle,SPContext.Current.Web.Title);
  22:       
  23:  }

 

In Zeile 7 wird veranlasst, dass alle kommenden Zugriffe auf eine Instanz der Klasse SPContext auf die FakeImplementierung umgeleitet werden. Durch die Angabe von Members.ReturnRecursiveFakes kann sichergestellt werden, dass Objekte die innerhalb einer jeden SPContext Instanz verwendet werden (SPWeb, SPSite,…) ebenfalls gemocket werden.

In Zeile 12 wird Typemock angewiesen, bei jedem Zugriff auf die Property Title der SPWeb Instanz der neue Titel zurückgegeben wird. Diese Anweisung ist wichtig, weil die eigentliche Speicherung und Aktualisierung nicht in das Aufgabengebiet der o.g. UserStory, sondern in das Aufgabengebiet von SharePoint fallen.

Die aus dem Test resultierende Implementierung

Die minimalste – meiner Meinung nach auch sauberste - Implementierung der Anforderung sieht wie folgt aus

   1:  public class WebTitleChanger : WebPart
   2:  {
   3:      public void SetWebCaption(String newTitle)
   4:      {
   5:          SPContext.Current.Web.Title = newTitle;
   6:          SPContext.Current.Web.Update();
   7:          
   8:      }
   9:  }

Wie dieses einfache Beispiel zeigt, kann man mit Typemock sehr einfach UnitTests für SharePoint-Lösungen erstellen.

 

Technorati-Markierungen: ,,
DotNetKicks-DE Image

Typemock Isolator for SharePoint

07.12.2010 23:28:53 | Thorsten Hans

In den letzten Jahren gewinnen SharePoint Lösungen immer mehr an Bedeutung. Ein regelrechter Hype steht uns Entwicklern dank SharePoint 2010, hier in Deutschland, noch bevor. Gerade weil immer mehr Problemstellungen mit SharePoint realisiert werden sollen, ist es enorm wichtig die Codequalität mittels UnitTest von Begin an zu garantieren.

Da die API von SharePoint nicht gerade “testfreundlich” ist, muss man beim Schreiben von UnitTests für SharePoint, oder gar bei der Entwicklung nach TDD darauf achten, dass UnitTests automatisiert und isoliert laufen sollen. Damit dies in SharePoint möglich ist, muss ein MockFramework eingesetzt werden, dass Mocking ohne die Existenz von Interfaces unterstützt.

 

TypeMockMicrosoft bietet an dieser Stelle mit PEX und Moles, meiner Meinung nach, die wohl schlechteste Lösung an. Ganz anders sieht es hier beim Typemock Isolator for SharePoint aus. Typemock ist in der Lage sämtliche SharePoint Typen zu faken, wodurch man sich beim Testen nicht um die Abhängigkeit “SharePoint” kümmern muss.

Integration

Typemock Isolater integriert sich nahtlos in VisualStudio und kann somit in der gewohnten Umgebung genutzt werden.Neben der Integration zur Entwicklungszeit bietet Typemock sowohl MSBuild Integration als auch TeamBuild Integration an, wodurch sich die UnitTests auch auf dem Buildserver ausführen lassen.

Fluent API

Typemock bietet genau wie das “Nicht-SharePoint-Framework” RhinoMocks eine Fluent API an, welche die Verwendung dank der sprechenden Syntax sehr verständlich macht. So kann man zum Beispiel alle, der Definition folgenden, Instanzen von SPWeb einfach durch eine Fake-Instanz austauschen

   1:  var fakeWeb = Isolate
   2:     .Fake
   3:     .Instance<SPWeb>(Members.ReturnRecursiveFakes);
   4:  Isolate
   5:     .Swap
   6:     .AllInstances<SPWeb>()
   7:     .With(fakeWeb);

Damit die folgenden UnitTests auf den Fake-Titel des Webs zugreifen können, muss dies dem Isolation-Framework mitgeteilt werden.

   1:  Isolate
   2:       .WhenCalled(()=>fakeWeb.Title)
   3:       .WillReturn("Faked Web");

 

Pricing

Das Pricing von Typemock Isolator for SharePoint ist sehr interessant wenn man lediglich SharePoint damit mocken möchte. Die reine SharePoint Lizenz kostet 249 Euro pro Jahr und Entwickler. Sobald man jedoch auch normale Web-Projekte oder Desktop-Anwendungen damit testen möchte kostet die Typemock Lizenz 799 Euro pro Jahr und Entwickler.

Den größten, aber wohl auch nutzvollsten, Teil der Lizenzkosten macht wohl die separate BuildServer Lizenz mit 2499 Euro aus. Wer sich den Typemock Isolator einmal anschauen möchte, kann sich auf der WebSeite eine kostenlose Demoversion downloaden.

Weitere Demos

Ich möchte diesen Post lediglich als Einleitung in die Thematik “Mission Qualitätssicherung in SharePoint Projekten” nutzen, die eigentlichen Beispiele folgen dann in den hierauf folgenden Posts.

 

Technorati-Markierungen: ,,
DotNetKicks-DE Image

Review Collaboration Days Luzern

07.12.2010 17:29:51 | Thorsten Hans

Letzte Woche fanden in Luzern die Collaboration Days statt. Die von der HLMC und der SharePoint Community Schweiz ausgerichtete Konferenz versorgte alle Teilnehmer an zwei Konferenz- und einem Workshop-Tag mit allen Informationen rund um Microsofts Collaboration Produkt SharePoint 2010.

CollabDaysMein Vortrag Data please, Mr.SharePoint richtete sich an SharePoint Entwickler. Im Rahmen meines Vortrages habe ich die unterschiedlichen Varianten des Datenzugriffs von SharePoint 2010 aufgezeigt und anhand von einigen Beispielen verschiedene Situationen erläutert.

Hier findet Ihr die Samples zu meinem Vortrag.

Am zweiten Konferenztag haben Nicki Borell und ich noch eine Backup-Session für TheVoiceOfSharePoint gehalten. Hierbei haben wir sowohl die IT-Pro Sicht auf BCS als auch die Möglichkeiten die Entwickler mit BCS haben aufgezeigt.

Alles in allem waren die Collaboration Days eine sehr schön und professionell ausgerichtete Konferenz rund um SharePoint.

 

Technorati-Markierungen: ,,
DotNetKicks-DE Image

Software Legende Juval Löwy am 8. Dezember in Koblenz

07.12.2010 11:54:01 | Andre Kraemer

Am 8. Dezember hat unsere User Group in Koblenz mit Juval Löwy nach Tony Lombardo den zweiten internationalen Sprecher zu Gast.

Juval wird bei uns seinen Vortrag “The Architect” halten, der für alle Software Architekten sowie Entwickler interessant ist.

Da wir dieses Mal die Kapazitäten ein wenig besser planen müssen, bitten wir um eine formlose, kurze Anmeldung unter dnug@konzeptum.de.

Das Treffen wird dieses Mal übrigens nicht bei Konzeptum, sondern ausnahmsweise bei der Görlitz AG statt finden.

Weite Details zum Treffen gibt es auf der Homepage der DNUG-Koblenz. Eine Anfahrtsbeschreibung zu Görlitz findet ihr hier.

Software Legende Juval Löwy am 8. Dezember in Koblenz

07.12.2010 09:54:10 | Andre Kraemer

Am 8. Dezember hat unsere User Group in Koblenz mit Juval Löwy nach Tony Lombardo den zweiten internationalen Sprecher zu Gast.

Juval wird bei uns seinen Vortrag “The Architect” halten, der für alle Software Architekten sowie Entwickler interessant ist.

Da wir dieses Mal die Kapazitäten ein wenig besser planen müssen, bitten wir um eine formlose, kurze Anmeldung unter dnug@konzeptum.de.

Das Treffen wird dieses Mal übrigens nicht bei Konzeptum, sondern ausnahmsweise bei der Görlitz AG statt finden.

Weite Details zum Treffen gibt es auf der Homepage der DNUG-Koblenz. Eine Anfahrtsbeschreibung zu Görlitz findet ihr hier.



blog.codemurai.de © André Krämer |Impressum | Abonieren

Windows Phone 7 Trainings zum Nulltarif

06.12.2010 18:12:09 | Peter Nowak

Unter dem Motto "Windows Phone 7 Quickstart für Entwickler" veranstaltet Microsoft im Januar und Februar 2011 eine Reihe von kostenlosen Tages-Workshops in seinen Regionalniederlassungen. Mobile Developer erfahren dabei alles Notwendige zur neuen Softwareplattform und den Werkzeugen von Windows Phone 7, um sofort mit der Entwicklung eigener Anwendungen beginnen zu können, um sie zu testen und über den Windows Phone Marketplace zu vertreiben. Trainer bei den Workshops ist Karsten Samaschke. Es lohnt sich somit!
Orte & Termine:
25.1.2011 - Bad Homburg
10.2.2011 - Köln
17.2.2011 - Hamburg
22.2.2011 - Unterschleißheim
24.2.2011 - Berlin

Weiterführende Informationen: Windows Phone 7 Trainings zum Nulltarif



This posting is provided "AS IS" with no warranties, and confers no rights.

Teil 1: Umkehrung der Kontrolle erklärt, oder: Von der Fabrikmethode zum DI-Container

05.12.2010 14:47:00 | Peter Bucher

Dies ist der Beginn der Artikelserie "Umkehrung der Kontrolle erkärt, oder: Von der Fabrikmethode zum DI-ContainerUmkehrung der Kontrolle erkärt, oder: Von der Fabrikmethode zum DI-Container" mit folgenden Teilen:

LightCore gibt es schon seit längerer Zeit, andere DI-Container noch länger.
In dieser Blogpostreihe geht es aber nicht primär um LightCore, auch nicht um die anderen DI-Container.

Ich möchte mit diesem Blogpost versuchen zu erkären, wie denn die ganze Geschichte funktioniert.

Vom Ursprung bis zu einer implementierten Komponente.

Das Feedback zur LightCore-Webseite und LightCore selber hat auf alle Richtungen ausgeschlagen.

Von: Wow, cool. Brauche ich!, zu: Was ist das denn?, bis zu: Braucht man sowas?, über: Sowas braucht man nicht!, bis zu: Mache ich von Hand oder in 10 Zeilen!.

An dieser Stelle sei gesagt: Ich würde die Fragen nach dem "brauchen" in jedem Fall mit "Ja" beantworten, je nach Kontext wo denn etwas eingesetzt werden soll.

Die Grundprobleme:

  1. Abhängigkeit zu konkreten Typen
  2. Redundanz bei der Konstruktion von Typen jeglicher Art
  3. Keine einfache Möglichkeit der Austauschbarkeit von Typen
  4. Keine einfache Möglichkeit der Erweiterbarkeit über Typen

Wieso überhaupt "Abhängigkeit lösen"?

Um die Probleme 2, 3 bis 4 zu lösen. Das heisst, die möglichen Redundanzen - also bspw. doppelten Instanziierungen von Klassen - zu vermeiden. Durch das Lösen der Abhänigigkeit von einem konkreten zu einem abstrakten Typen können die Typen ausgetauscht werden und eine Erweiterung ist mit weniger Aufwand möglich.

Die Abhängigkeit wird nicht "verbannt", sondern gelöst. Lösen heisst in diesem Fall, dass die Abhängigkeit nicht mehr auf _einen_  _konkreten_ Typen besteht, sondern auf _eine_ Abstraktion, die _mehrere_ unterschiedliche Implementationen beinhalten kann.

Anstelle dass nur "World" genutzt werden kann, kann dann mithilfe der Abstraktion "WorldBase", "SecondWorld", "IrgendwasWorld", etc... benutzt werden.

Diese Grundprobleme können auf verschiedene Arten gelöst werden. Vorerst die einfachsten Möglichkeiten.

Eine einfache Abhängigkeit zu konkreten Typen kann folgendermassen aussehen:

World world = new World();
world.SayHello();

 

In diesem Beispiel ist die Methode "SayHello" von der konkreten Klasse "World" abhängig.

Wollen wir diese Abhängigkeit lockern / lösen, brauchen wir eine Abstraktion irgend einer Art.
Das kann ein Interface sein, eine Abstrakte Klasse oder auch eine einfache konkrete Oberklasse.

Am Beispiel einer abstrakten Klasse:

WorldBase world = new World();
world.SayHello();

 

Ja, das war erst der erste Schritt. Das Problem besteht immer noch, es liegt in "new World();". Wir referenzieren den Konstruktur der konkreten Klasse.
Die einfachste Lösung hierfür ist eine Fabrikmethode (Factory Method), womit die Konstruktion der Instanz ausgelagert wird.

Dies könnte so aussehen:

public static WorldBase ConstructMyWorld()
{
                return new World();
}

WorldBase world = ConstructMyWorld();
world.SayHello();

 

So ist das Problem auf einfachste Art gelöst.

Zusammenfassung:
Das Problem war die Abhängigkeit auf die konkrete Klasse "World".
Wenn wir anstelle von der Klasse "World", "SecondWorld" benutzen wollen, brauchen wir das jetzt nur noch an der Stelle "return new World" zu ändern, in "return new SecondWorld();"

Wie häufig wir die Fabrikmethode "ConstructMyWorld" benutzen, bleibt uns überlassen.
Die Stelle bleibt, ein Ort der Änderung.

Das wird möglich indem wir eine Abstraktion benutzen, in unserem Falle "WorldBase".
Die konkreten Klassen "World", "SecondWorld" müssen von aussen gleich aussehen (Implementieren die gleiche Abstraktion), können allerdings anders implementiert sein.

Die Angabe des Typs "WorldBase" braucht bei der Zuweisung am Ort des Benutzens angegeben werden, sowie auch als Rückgabetyp der Fabrikmethode.

Das war die einfachste Möglichkeit der Umkehrung per Fabrikmethode.

Die Frage bleibt evt. noch: Wieso Umkehrung?

Am Anfang hatte die Zuweisung am Ort des Benutzens die Kontrolle über den konkreten Typen, sie gab also an, was sie möchte.

Jetzt liegt die Kontrolle _in_ der Fabrikmethode. Der Ort des Benutzens weiss nur, das da ein Typ zurückkommt, der aussieht wie "WorldBase", nicht mehr und nicht weniger.

Am Schluss noch der vollständige (vermutlich nicht sofort lauffähige = Pseudo) Code:

public class ConsoleApplication
{
                public static void Main()
                {
                                WorldBase world = ConstructMyWorld();
                                world.SayHello();
                }

                public static WorldBase ConstructMyWorld()
                {
                                return new World();
                }
}

public abstract class WorldBase
{
                public abstract void SayHello();
}

public class World : WorldBase
{
                public void SayHello()
                {
                               Console.WriteLine("Hello World");
                }
}

public class SecondWorld : WorldBase
{
                public void SayHello()
                {
                               Console.WriteLine("Hello SecondWorld");
                }
}

Vereinfachte Lokalisierung eines ViewModels in ASP.NET MVC

05.12.2010 14:08:13 | Albert Weinert

Ich arbeite gerade an einer Anwendung die ich auch mehrsprachig anbieten möchte. Dabei sind mir ein paar Sachen aufgefallen die unhandlich sind. Hier dazu meine Lösungen

Display-Name von Properties in ViewModels

In ASP.NET MVC 3 kann ich mit der leichten Syntax

  [Display(ResourceType=typeof(SpeakertNetStrings), Name="Speaker_Session")] 
  public string Fullname { get; set; } 

  [Display(ResourceType=typeof(SpeakertNetStrings), Name="Speaker_Session")] 
  public int SessionCount { get; set; } 

die passenden Resource-Strings angeben, dieser wird dann mit dem Label- bzw. LabelFor-HtmlHelper dargestellt. Da dies jedoch ein .NET 4 Attribute ist, funktioniert es unter .NET 3.5 nicht. Auch ist es unpraktisch in der Anwendung. Das unter ASP.NET MVC 2 verwendetet DisplayNameAttribute funktioniert zwar auch unter MVC 3, jedoch kann ich da nur einen String direkt angegeben, von Lokalisierung keine Spur.

Also habe ich mir folgendes Attribute gebastelt, was nur noch entsprechend der Anwendung angepasst werden muss.

public class LabelAttribute : DisplayNameAttribute 
  { 
  public LabelAttribute(string resourceName) 
      : base(GetDisplayName(resourceName)) 
  { 
  } 

  private static string GetDisplayName(string resourceName) 
  { 
     var displayName = SpeakertNetStrings.ResourceManager.GetString(resourceName, SpeakertNetStrings.Culture); 
     return displayName ?? "Missing: " + resourceName; 
  } 
} 

Hiermit ist die Auszeichnung der Properties mit ResourceS-trings viel einfacher. Man muss nur noch den Resource-String angeben.

  [Label("Speaker_Session")] 
  public string Fullname { get; set; } 

  [Label("Speaker_Session")]
  public int SessionCount { get; set; } 

  

Dies funktioniert unter ASP.NET MVC 2 und 3, dass DisplayAttribute ist sealed und davon ist eine Ableitung nicht möglich. Die notwendige Anpassung besteht darin auf die eigenen Resourcen zu verweisen.

Darstellung des Display-Namens

Um den übersetzten Namen der Property anzuzeigen gibt es die Label- und LabeFor-HtmlHelper. Jedoch funktionieren die nicht an allen Stellen in einem View und manchmal muss man sich die Resource-Strings dann manuell holen. Desweiteren will man auch nicht überall ein Label-Tag drum herum haben und einfach mal nur den Namen anzeigen.

Dies geht, aber ist etwas unpraktisch sobald man z.B. den Resource-Namen umbenennt.  Dann muss ich dies in allen Views auch anpassen und nicht nur an einer Stelle am ViewModel.

Jedoch liegen die notwendige Information in den Meta-Daten vor, also müssten Sie nur noch rausgepult werden. Dazu habe ich mir mal zwei Extensionmethoden gebaut.

public static class MetadataExtensions 
  { 
  public static string GetDisplayName(this Type type, string propertyName) 
  {
    return ModelMetadataProviders.Current
	       .GetMetadataForProperty(() => null, type, propertyName).GetDisplayName(); 
  } 

  public static string GetDisplayName(this T instance, string propertyName) 
  {
    return ModelMetadataProviders.Current
	       .GetMetadataForProperty(() => instance, typeof(T), propertyName).GetDisplayName(); 
  } 
}

Diese Variante ist hier bewusst einfach gehalten, sie kann den Anwendungsanforderungen entsprechend einfach ergänzt werden um z.B. typisierten Zugriff auf die PropertyNamen zu erhalten.

Die Anwendung ist sehr einfach gezeigt, ein Bespiel in der Razor-Syntax

<th>@Model.GetDisplayName("Fullname")</th> 
<th>@typeof(SpeakerSessionListModel).GetDisplayName("SessionCount")</th>

Ich hoffe dies hilft weiter

Windows Phone 7 Quickstart für Entwickler

03.12.2010 14:00:31 | Peter Kirchner

clip_image002

Sie sind Softwareentwickler und möchten mit Ihren Produkten auf dem Windows Phone 7 Marketplace präsent sein? Wir machen Ihnen den Einstieg leicht! In diesem Tagesworkshop erfahren Sie alles Notwendige zur neuen Softwareplattform und den Werkzeugen von Windows Phone 7, um sofort mit der Entwicklung eigener Anwendungen beginnen zu können. Sie lernen, wie auf Basis bewährter Technologien wie .NET und Silverlight mit der populären Sprache C# und dem hochproduktiven Werkzeug Visual Studio 2010 Apps für den privaten und Businesseinsatz entstehen.

Sie erfahren, wie Sie Ihre Software im Emulator oder auf Geräten testen und schließlich im Windows Phone Marketplace vertreiben können. Und Sie haben die Möglichkeit, von unserem erfahrenen Trainer Antworten auf Ihre Fragen zu erhalten. Diese Veranstaltung vermittelt die Inhalte durch Vorträge und Demos.

Agenda

  • Begrüßung und allgemeine Informationen
  • Windows Phone 7 – Plattformüberblick
  • Grundlagen der WP7-Entwicklung mit Silverlight
  • Fortgeschrittene Silverlight-Themen
  • Datenspeicherung und –zugriff
  • Lebenszyklus einer Anwendung
  • Zugriff auf Sensoren & Nutzerdaten
  • Web Services & the Cloud
  • Softwarevertrieb

Preis:             kostenlos
Referent :      Karsten Samaschke

Datum, Veranstaltungsort und Anmeldung

Traps of Windows Azure Development

03.12.2010 10:10:00 | Patric Schouler

My personal traps of Windows Azure development for this week are:

  • Problems with long project names (longer 248) for the temporary name of my delivery package for running at the Windows Azure emulator
    • Use _CSRUN_STATE_DIRECTORY as environment variable to shorten the path
  • Remove PlatformTarget from an existing Web project file to avoid compile error
  • Strange CommunicationObjectFaultedException error if you use a Source Safe tool and your web.config is read only
  • If you use assemblies that are not content of a normal Windows Server 2008 SP2 installation (for example RIA Services), you have to set the properties “Copy Local” to true of the assemblies involved – otherwise you get a never ending “busy” state of your web role at Windows Azure Management Tools

Windows Azure: CommunicationObjectFaultedException

03.12.2010 10:02:00 | Patric Schouler

If your web.config is read only you get maybe the following strange error message in a Windows Azure project at runtime. It costs my half a day to find out, that this has nothing to do with my web service configuration or web service usage.

image

Windows 7: Project Hilo für C++ Entwickler

03.12.2010 09:10:00 | Oliver Scheer

Project Hilo ist eine Trainingsanwendung für C++ Entwickler. Darin enthalten ist eine sehr ansprechende Anwendung für die Betrachtung und Veröffentlichung von Bildern. Es werden Animationen und Überblendeffekte demonstriert. Zusätzlich enthalten sind dort auch Anleitungen unden Beispielcode für die Verwendung in eigenen Anwendungen.

Get Microsoft Silverlight

Project Hilo kann unter http://code.msdn.microsoft.com/Hilo herunter geladen werden.



Einstieg zur Workflow Foundation 4 : Debugging von Workflows

02.12.2010 15:27:41 | Gregor Biswanger

Sehr angenehm ist die unterstützte Debugging-Funktion der Workflow Foundation. Zur Demonstration wird der Workflow Rechner aus dem Beispiel vom letzten Blog-Beitrag “Activity selbst schreiben” verwendet.

Im Source Code des selbst geschriebenen Activities kann jederzeit ein Debugging stattfinden. Das besondere gilt in diesem Fall die Debugging Unterstützung im Designer. Dazu wird der “Rechner Workflow” im Designer geöffnet. Die [F9]-Taste setzt dann im entsprechend ausgewählten Activity ein Breakpoint. Auch mittels Rechtsklick und dem Menüreiter Breakpoint vom Kontextmenü kann ein Breakpoint gesetzt werden.

SNAGHTML676bb25

Abb. 1 – Breakpoint im Designer setzen.

 

Beim Ausführen der Anwendung im Debbug-Modus [F5] wird im laufenden Beispiel 5 + 5 eingegeben. Hält die Anwendung beim entsprechenden Verarbeitungspunkt, wird dies schön übersichtlich im Designer dargestellt. Der Arguments- und Variablen-Wert wird schön übersichtlich im Locals-Window angezeigt.

 

image

Abb. 2 – Designer zur Debugging Laufzeit.

Einstieg zur Workflow Foundation 4 : Externe XAML-Dateien zur Laufzeit ausführen

02.12.2010 14:47:54 | Gregor Biswanger

Es kann zu bestimmten Situationen kommen wo externe XAML-Dateien während der Laufzeit eingelesen und als Workflow ausgeführt werden sollen. Dazu behilft die ActivityXamlServices-Klasse. Wichtig dabei ist das eine Reference zu System.Xaml dem Projekt hinzugefügt wird.

Anschließend ist nur folgender Code dafür nötig:

 

   1:  class Program
   2:  {
   3:      static void Main(string[] args)
   4:      {
   5:          string filePath = @"..\..\..\WorkflowAsyncExample\DemoWorkflow.xaml";
   6:   
   7:          Activity activity = ActivityXamlServices.Load(filePath);
   8:          WorkflowInvoker.Invoke(activity);
   9:   
  10:          Console.ReadLine();
  11:      }
  12:  }

Listing 2 – Source-Code für den Taschenrechner in der Console.

Beim starten der Anwendung kann der Anwender nun die Rechenaufgaben eingeben. Wichtig dabei ist das die Eingaben korrekt durch ein Leerzeichen getrennt eingegeben werden.

SNAGHTML5f380d1

Abb. 9 – Fertige Workflow Rechner Anwendung.

Small Talk: Liebe Fans von JavaScript und Ajax

02.12.2010 12:56:04 | Oliver Scheer

Eins vorne weg, ich bin ein großer Webfan. Ohne das Internet kann ich quasi nicht mehr leben. Ich arbeite seit 1995 mit Webtechnologien. Ich spreche fliesend HTML, JavaScript und noch so einige andere Websprachen. Silverlight ist Super, Flash .. naja … ist auch nicht schlecht.

Wir befinden uns (noch) im Jahr 2010. Web 2.0 ist überall. Dienstleistungen werden über das Internet verkauft, wie früher Obst und Gemüse im Supermarkt. Inzwischen kann man seine Einkäufe auch Online tätigen und sich nach Hause liefern lassen oder aber auf dem Heimweg vom Büro am Supermarkt abholen.

Man kann Termine mit Freunden absprechen ohne sie anzurufen. Man erstellt einfach eine Online-Umfrage und schon kriegt man seine Buddies zusammen zu echten Glühwein trinken.

Es gibt inzwischen eine unzählbare Anzahl von Berufsbezeichnungen rund um das Thema User Experience, Design und Benutzerfreundlichkeit.

Allerdings stelle ich mir immer wieder die Frage, warum in aller Welt es bis heute kein Online-Reisebuchungssystem schafft eine ansatzweise benutzbare Oberfläche zu bauen. Jedes Mal wenn ich versuche Online eine Reise zu buchen, privat wie auch beruflich, benötige ich eine Packung Valium um nicht durchzudrehen. Was dort geboten wird ist eine … FRECHHEIT, und das ist schon eine freundlich, positive Aussage.

Gestern wollte ich eine Reise buchen, die meiste Zeit davon hing ich vor einem “Lade-Bildschirm” in dem mir gesagt wurde, wie toll diese Webseite ist und von welchen angeblichen Fachmagazinen diese Webseite zur tollsten Reisebuchungsseite gewählt wurde. Eigentlich sollte es dort heißen “Diese Seite ist die am wenigsten schlechte Implementierung eines Versuchs Reisen online zu buchen”.

Es ist schön zu sehen, das die Entwickler begriffen haben, das es AJAX gibt. Gibt es übrigens schon seit über 10 Jahren. Traurig nur, das man es so sehr übertreibt mit Ladekringeln hier und aufpoppenden Kalendern die fast unbedienbar sind, das die Webseite bald dar nieder kniet und kapituliert.

Mein Tipp: Weniger ist mehr. Wenn man schon neue Web 2.0 Technologien anwenden will, sollte man sich vorher fragen, ob sie dem Benutzer was bringen. Bitte nicht die Technik, der Technik wegen anwenden. Ich will nicht wissen, das es 32.012 Ergebnisse zu meiner Suchanfrage gibt, die ich dann eh nicht ordentlich filtern geschweige denn ordentlich durchstöbern kann. Ich will Urlaub machen und nicht drei Tage und Nächte mit Buchen verbringen. Macht es mir leichter, nicht schwer.

Es geht doch echt nichts über einen Besuch im Reisebüro, da muss man zumindest das grauenhafte System nicht selber bedienen und man kann mit einem netten Menschen sprechen. Und man bekommt auch noch einen Kaffee angeboten.

Der Oliver



Back for good!

02.12.2010 11:49:53 | Damir Tomicic

Im Vorfeld zweier wichtigen Erreignisse dachte ich, es sei die höchste Zeit die Blog Engine aus dem Schlafmodus zu holen. Ein besonderer Gruß gilt dem Kay G. :-)

Nächste Woche, soweit die Schneemassen meine Reise erlauben, werde ich mich auf dem Weg nach Paris zur LeWeb 2010 Konferenz machen. Wir stellen in diesem Jahr gemeinsam mit Microsoft Corporation dort aus und bereiten auch gleich zwei Neuigkeiten vor, die kurz in diesem Video erwähnt worden sind. In einem separaten Blog-Posting werde ich näher darauf eingehen, jetzt aber zum wichtigsten Teil der Ankündigung - es gibt auch was tolles zu gewinnen - eine brandneue Xbox 360 mit Kinect Controller! Wie und was findet man auf folgender Seite:

[1] http://bit.ly/AxCMS10

PhotoSynth: Photoshop Plug-In veröffentlicht

02.12.2010 09:42:47 | Oliver Scheer

Gestern wurde von Microsoft Research ein neues Plug-In für Photoshop veröffentlicht. Mit diesem Plug-In kann man Panorama-Bilder aus Photoshop direkt nach Photosynth exportieren und in Top-Performance und –Qualität betrachten.

Weitere Informationen dazu finden sich unter den folgenden Adressen:

Download: http://research.microsoft.com/en-us/downloads/39e3bd90-7b2f-4f85-b32f-3a3d5cd04e36/

Dokumentation: http://hdview.wordpress.com/2010/11/26/panorama-uploads-from-photoshop/

Weitere Informationen: http://blogs.msdn.com/b/photosynth/archive/2010/11/30/photoshop-to-photosynth.aspx

clip_image002

Das Video dazu:

Get Microsoft Silverlight



Windows 7: Theming mit WPF

02.12.2010 09:16:00 | Oliver Scheer

WPF bietet die Möglichkeit, das man seine Anwendung nahezu beliebig Skinnen kann. Auf der Codeplex befindet sich ein Projekt mit über 10 verschiedenen Skins, die man frei in eigene Anwendungen integrieren kann. Der Link und die diversen Skins werden in diesem Video vorgestellt.

Get Microsoft Silverlight



Windows 7: FishEyeEffect mit WPF

02.12.2010 09:08:00 | Oliver Scheer

Dieses Video zeigt, wie leicht man mit einem selbstgeschriebenen Behavior, spannende Effekte in seine eigene Anwendungen integrieren kann. Mit dem FishEyeBehavior kann man Elemente auf der Oberfläche abhängig von der Position der Maus skalieren. Dadurch entsteht ein sogenannter Fischaugeneffekt.

Get Microsoft Silverlight

Das verwendete Behavior befindet sich in Win7ToGo-Codeplex-Projekt frei zum Download unter http://win7togo.codeplex.com



Das grosse MSDN Weihnachtsgewinnspiel 2010 ist gestartet!

01.12.2010 18:49:42 | Kay Giza

Gewinnen Sie mit MSDN eine Xbox 360 mit Kinect, ein Windows Phone 7 und viele weitere attraktive Preise! Ab sofort gilt auf MSDN jeden Tag bis einschließlich Heiligabend: Mitmachen beim MSDN Adventskalender und Preise gewinnen bis der Weihnachtsmann kommt! Alle Details und Informationen in diesem Blogeintrag auf Giza-Blog.de... [... mehr]

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

MSDN TV vom 30.11.2010 mit Mark Russinovich im Interview

01.12.2010 18:19:18 | Kay Giza

Eine neue MSDN T-Folge mit der Ausgabe vom 30. November 2010 ist veröffentlicht worden. Dieses Mal im Interview Mark Russinovich! Für alle, die unsere aktuelle Konferenz-Berichterstattung Anfang November zur TechEd Europe in Berlin nicht regelmäßig verfolgen konnten, hat Lori Grosland zuvor außerdem noch ein paar interessante Nachrichten mit Infos zu einer neuen... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

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

Erst eins, dann zwei, dann drei, dann vier….

01.12.2010 17:59:54 | Oliver Scheer

Warten kann so schön sein! Wir versüßen Ihnen das Warten auf Weihnachten dieses Jahr mit demimg_ie9_advent_367x242_ihnen

Internet Explorer 9 Beta-Adventskalender

In dem Adventskalender warten jeden Tag Preise wie Windows Phone 7, Xbox 360 mit Kinect und Netbooks auf Sie. Zur Teilnahme müssen Sie einfach nur fünf versteckte Features des Internet Explorer 9 Beta im Adventskalender aufdecken. Schon nehmen Sie an der Verlosung des Tagespreises teil. Welcher Preis sich hinter welchem Türchen versteckt, das weiß nur der Weihnachtsmann J. Das Beste: Sie können jeden Tag neu mitmachen und Ihr Glück versuchen!

Link



Windows 7: Spaß am Programmieren–SoundPanel oder wie baut man eine Furz-App ohne Code.

01.12.2010 17:52:55 | Oliver Scheer

Dieses Video beschreibt wie man ganz einfach Anwendungen wie die unsägliche Furz-App, MooBoxen und "Drück Knopf kommt Sound"-Anwendungen schreiben kann, ohne das man dafür Coden muss. Nur mit Behavioren lassen sich SoundPanels erstellen. Viel Spaß ... und bitte nicht zuviele Furz-Apps ....

Get Microsoft Silverlight



Neue Folge von Silverlight-Expertise: “Daten bei Datenbindung formatieren”, “XAP-Datei vor Hijacking schützen”, “Page Navigation”

01.12.2010 16:07:36 | Gregor Biswanger

dotnet-magazin-logo

In der aktuellen Ausgabe vom dot.net magazin gibt es eine neue Folge von meiner Silverlight-Kolumne “Silverlight-Expertise”:  

Silverlight-Expertise - Die Crème de la Crème des Monats
Die Serie „Silverlight Expertise“ des dot.NET Magazins präsentiert monatlich zwei leckere Top-How-Tos zum Thema Silverlight von Gregor Biswanger (www.dotnet-blog.net), sodass Einsteiger und fortgeschrittene Silverlight-Experten durch geballtes Wissen gesättigt werden. Heute stehen auf der Menükarte „Daten bei Datenbindung formatieren“ und „XAP-Datei vor Hijacking schützen“. Viel Spaß und einen guten Appetit.

 

 

Windows_Phone_Logo_Horizont

Neu! Mit dabei ist jeweils ein How-To zum Thema Windows Phone 7. Hier steht auf der Menükarte: “Page Navigation”.

 

 

dotnetmagazin-01-2011

Zu lesen sind die How-To´s beim dot.net magazin, Ausgabe 01/2011

Einstieg zur Workflow Foundation 4 : WorkflowApplication als erweiterter Workflow Hoster

01.12.2010 15:45:57 | Gregor Biswanger

Das die Klasse WorkflowInvoker als Workflow Hoster fungiert ist bereits bekannt. Jedoch handelt es sich hierbei um einen leichtgewichtigen Workflow Hoster, womit Workflows Synchron und Asynchron ausgeführt werden können. Was jedoch wenn man direkten Einfluss außerhalb auf Workflows ausüben möchte? oder auf bestimmte Situationen dementsprechend Logik hinterlegen möchte?

Dazu dient die Klasse WorkflowApplication. Die einen etwas umfangreicheren Workflow Hoster entspricht. Diese kann zum Gegenteil der abgespeckten WorkflowInvoker Version:

 

  1. Erstellen einer neuen Workflowinstanz oder Laden einer Workflowinstanz aus einem Instanzspeicher
  2. Bereitstellen von Erweiterungen für Aktivitäten in einer Workflowinstanz
  3. Steuern der Ausführung einer Workflowinstanz
  4. Wiederaufnahme eines von einer Aktivität erstellten Lesezeichens in einer Workflowinstanz
  5. Ablegen im Persistenzspeicher/Entladen einer Workflowinstanz
  6. Aktivieren von Benachrichtigungen bei Ereignissen im Workflowinstanzlebenszyklus

 

Zur Demonstration wird das gleiche Beispiel vom Blog-Post “Einstieg zur Workflow Foundation 4 : Workflows asynchron aufrufen” verwendet. Der Source-Code der Program.cs-Datei wird wie unter Listing 1 geändert.

 

   1:   class Program
   2:      {
   3:          private static readonly AutoResetEvent WaitEvent = new AutoResetEvent(false);
   4:   
   5:          static void Main(string[] args)
   6:          {
   7:              Console.WriteLine("Host: Ich starte DemoWorkflow - Thread: {0}", Thread.CurrentThread.ManagedThreadId);
   8:   
   9:              WorkflowApplication workflowApplication = new WorkflowApplication(new DemoWorkflow());
  10:   
  11:   
  12:              workflowApplication.Completed = (e) =>
  13:                                                  {
  14:                                                      switch (e.CompletionState)
  15:                                                      {
  16:                                                          case ActivityInstanceState.Closed:
  17:                                                              Console.WriteLine("Host: Closed - Thread: {0}", Thread.CurrentThread.ManagedThreadId);
  18:                                                              break;
  19:                                                          case ActivityInstanceState.Canceled:
  20:                                                              Console.WriteLine("Host: Canceled - Thread: {0}", Thread.CurrentThread.ManagedThreadId);
  21:                                                              break;
  22:                                                          case ActivityInstanceState.Executing:
  23:                                                              Console.WriteLine("Host: Executing - Thread: {0}", Thread.CurrentThread.ManagedThreadId);
  24:                                                              break;
  25:                                                          case ActivityInstanceState.Faulted:
  26:                                                              Console.WriteLine("Host: Faulted - Thread: {0} - {1}:{2}", Thread.CurrentThread.ManagedThreadId,
  27:                                                                                                                                                          e.TerminationException.GetType(),
  28:                                                                                                                                                          e.TerminationException.Message);
  29:                                                              break;
  30:                                                      }
  31:   
  32:                                                      WaitEvent.Set();
  33:                                                  };
  34:   
  35:              workflowApplication.OnUnhandledException = (e) =>
  36:                                                             {
  37:                                                                 Console.WriteLine("Host: OnUnhandledException - Thread: {0} - {1}", Thread.CurrentThread.ManagedThreadId,
  38:                                                                                                                                                                              e.UnhandledException.Message);
  39:   
  40:                                                                 WaitEvent.Set();
  41:   
  42:                                                                 return UnhandledExceptionAction.Cancel;
  43:                                                             };
  44:   
  45:   
  46:              workflowApplication.Aborted = (e) =>
  47:              {
  48:                  Console.WriteLine("Host: Aborted - Thread: {0} - {1}", Thread.CurrentThread.ManagedThreadId,
  49:                                                                                                                               e.Reason.Message);
  50:   
  51:                  WaitEvent.Set();
  52:              };
  53:   
  54:              workflowApplication.Idle = (e) =>
  55:              {
  56:                  Console.WriteLine("Host: Idle - Thread: {0}", Thread.CurrentThread.ManagedThreadId);
  57:              };
  58:   
  59:              workflowApplication.PersistableIdle = (e) =>
  60:              {
  61:                  Console.WriteLine("Host: PersistableIdle - Thread: {0}", Thread.CurrentThread.ManagedThreadId);
  62:   
  63:                  return PersistableIdleAction.Unload;
  64:              };
  65:   
  66:              workflowApplication.Unloaded = (e) =>
  67:              {
  68:                  Console.WriteLine("Host: Unloaded - Thread: {0}", Thread.CurrentThread.ManagedThreadId);
  69:              };
  70:   
  71:              try
  72:              {
  73:                  workflowApplication.Run();
  74:   
  75:                  Console.WriteLine("Host: DemoWorkflow gestartet... - Thread: {0}", Thread.CurrentThread.ManagedThreadId);
  76:                  WaitEvent.WaitOne();
  77:              }
  78:              catch (Exception exception)
  79:              {
  80:                  Console.WriteLine("Host: Exception - {0}", exception.Message);
  81:              }
  82:   
  83:              Console.ReadLine();
  84:          }
  85:      }

Listing 2 – Source-Code der Program.cs-Datei

 

Jetzt kann wie gewohnt die Anwendung mittels [F5]-Tastendruck ausgeführt werden.

 

SNAGHTML156b503

Abb. 6 – Ausgabe des Workflows.

 

Fazit

Dieses erste “Hallo Workflow”-Beispiel sollte auf einfache Art und weise Demonstrieren wie grundlegend mit der WF 4 gearbeitet wird. Es folgen weitere Blog-Einträge die jeweils tiefer in die Thematik einsteigen werden.

Hosting Silverlight Application with RIA Services as Cloud Service

01.12.2010 13:43:00 | Patric Schouler

We have an existing web project (Silverlight 4, WCF RIA Services) that we wanted to bring to the cloud using Windows Azure.  We added a new project, Windows Azure Cloud Service and added a new Web Role.  After this you can connect your existing web project to this web role. The isolated web project compiles fine, but our new solution brings the following compile error:

    “Error      1             The "CreateRiaClientFilesTask" task failed unexpectedly.System.Web.HttpException (0x80004005): Could not load file or assembly 'msshrtmi' or one of its dependencies. An attempt was made to load a program with an incorrect format. ---> System.Configuration.ConfigurationErrorsException: Could not load file or assembly 'msshrtmi' or one of its dependencies. An attempt was made to load a program with an incorrect format. ---> System.BadImageFormatException: Could not load file or assembly 'msshrtmi' or one of its dependencies. An attempt was made to load a program with an incorrect format.”

Strange, what happens and what can we do?

The solution is very easy, but hard to find out: You have to unload your .web project (which hosts the Silverlight application) and edit it the project file.  If you now remove the tags

    <PlatformTarget>AnyCPU</PlatformTarget>
from the project file, your solution can be compiled !

msdn tv: TechEd Spezial 2010/11

01.12.2010 12:46:10 | Oliver Scheer

clip_image001"msdn tv" meldet sich heute mit einem Tech·Ed Special aus Berlin. Im Fokus steht dabei ein Interview, das Microsoft Student Partner Sebastian Schütze mit Mark Russinovich geführt hat, seines Zeichens "Technical Fellow" in der Platform & Services Division von Microsoft.
Für alle, die unsere aktuelle Konferenz-Berichterstattung Anfang November nicht regelmäßig verfolgt haben, gibt’s zuvor außerdem noch ein paar interessante "Fast Facts" mit Infos zu einer neuen Microsoft-Lösung für die ‘Private Cloud’, die das Hyper-V Cloud-Programm und das System Center integriert sowie Meldungen zu WebMatrix Beta 3, zur dritten Version des ASP.NET MVC Release Candidate, dem Tech·Ed Videoarchiv mit rund 350 Vortragsaufzeichnungen aus Berlin und den Tech·Ed-Aktivitäten der Microsoft Student Partners.

http://msdn-online.de/msdntv

Get Microsoft Silverlight



Konferenz: App-Entwicklerkonferenz der Deutschen Telekom (Nachtrag)

01.12.2010 11:48:46 | Oliver Scheer

Wo zwei Wochen war ich als Sprecher auf der App-Entwicklerkonferenz der Deutschen Telekom. Dort habe ich zwei mal zwei Vorträge gehalten. Die Vorträge gingen leider jeweils nur 30 Minuten, daher sind auch die Slides etwas “dünn”.

Die Slides (ohne Demos) habe ich auf Docs.com zum Ansehen und Downloaden bereit gestellt:

  • Apps für Windows Phone 7 – Plattform, Tools & Dienste – Download
  • Design & Code für Windows Phone 7 – Silverlight UI & Phone Apis – Download


Windows 7: Spaß am Programmieren–Simon

01.12.2010 09:05:00 | Oliver Scheer

Selten hab ich mich so gefreut, einen alten Bekannten aus meiner Jugend wieder zu sehen. Zu dieser Anwendung in Silverlight oder WPF oder Surface braucht man nicht mehr wirklich viel sagen.

Get Microsoft Silverlight

Die Anwendung kann unter der folgenden Adresse Live getestet werden: http://www.hackingsilverlight.net/simon.html



Windows 7: Spaß beim Programmieren - Follow The Mouse

01.12.2010 00:12:07 | Oliver Scheer

Diese kleine Beispielanwendung beweist, das man nicht immer nur ernsthafte Anwendungen entwickeln muss. Dieses Beispiel demonstriert, wie man ganz einfach Augen designt, die der Maus auf Schritt und Tritt folgen. Dabei wird die Windows 7 Glass Oberfläche genutzt und der Fensterrahmen auf ein Minimum reduziert.

Get Microsoft Silverlight

Fühlen Sie sich beobachtet? Smiley



WPF Forum | ASP.NET Forum | ASP.NET MVC Forum | Silverlight Forum | Windows Phone 7 Forum | SharePoint Forum | Dotnet Jobs | Dotnet Termine | Developer Blogs | Dotnet News

Das Team | Regeln | Impressum