So, der schriftliche Prüfungskram ist dann nun endlich durch. Jetzt nur noch die mündliche Prüfung und ich habe fertig!

 

flattr this!

Wenn ich ehrlich bin passt mir das Thema mit der Abschlussprojektarbeit irgendwie nicht in meine Planung für dieses Jahr. Aber viel schlimmer ist, das beim übertragen meiner Posts einfach zu viel schief gegangen ist, somit fehlen Bilder und Texte wurden versaut.

flattr this!

Zend_Controller Erweiterung mit Parameterübergabe in den Actions

<?php
 
abstract class Smart_Controller_Action_Abstract extends Zend_Controller_Action {
 
	public function returnJson($object) {
		$this->getHelper('json')->sendJson($object);
	}
 
	public function dispatch($action) {
		$returnValue = null;
		// Notify helpers of action preDispatch state
		$this->_helper->notifyPreDispatch();
 
		$this->preDispatch();
		if ($this->getRequest()->isDispatched()) {
			if (null === $this->_classMethods) {
				$this->_classMethods = get_class_methods($this);
			}
 
			if (!($this->getResponse()->isRedirect())) {
				// preDispatch() didn't change the action, so we can continue
				if ($this->getInvokeArg('useCaseSensitiveActions') || in_array($action, $this->_classMethods)) {
					if ($this->getInvokeArg('useCaseSensitiveActions')) {
						trigger_error('Using case sensitive actions without word separators is deprecated; please do not rely on this "feature"');
					}
					$invoker = new ReflectionMethod($this, $action);
					$params = $invoker->getParameters();
					$invokeParams = array();
					$requestParams = $this->getRequest()->getParams();
					/** @var ReflectionParameter $param */
					foreach ($params as $param) {
						if (array_key_exists($param->name, $requestParams)) {
							$invokeParams[] = $requestParams[$param->name];
						} else {
							if (!$param->isOptional()) {
								throw new Exception("Param $param->name is missing!");
							}
							$invokeParams[] = $param->getDefaultValue();
						}
					}
					if ($invokeParams == array())
						$returnValue = $this->$action();
					else
						$returnValue = $invoker->invokeArgs($this, $invokeParams);
				} else {
					$returnValue = $this->__call($action, array());
				}
			}
 
			if ($returnValue !== null) {
				/** @var Smart_Result_JSON $returnValue */
				$this->returnJson($returnValue->getObject());
			}
 
			$this->postDispatch();
		}
 
		// whats actually important here is that this action controller is
		// shutting down, regardless of dispatching; notify the helpers of this
		// state
		$this->_helper->notifyPostDispatch();
	}
 
 
}

flattr this!

Leave a Comment

Filed under

Späte Einsicht ist besser als gar keine

In den letzen Wochen habe ich mich eher halbherzig damit beschäftigt ein eigenes Blogsystem für mich aufzubauen. Denn es kann ja schon nicht so schwer sein!

Die Realität lehrte mich dann eines besseren. Denn die Ausgabe des Blogs ist nicht einmal die halbe Miete. Letztendlich es das Backend das ein Blogsystem wirklich ausmacht. Und das ist auch nicht durch irgendwelchen Frontend-Javascript-AJAX krams zu ersetzen.

Von daher ziehe ich für mich mein persönliches Fazit:

  • Wechsle das Blogsystem erst, wenn es einem Funktionsumfang entspricht, der sinn macht
  • Beim nächsten mal etwas etwas länger darüber nachdenken, denn WordPress ist nunmal doch “DAS” Blogsystem.

flattr this!

Leave a Comment

Filed under Allgemein

Jetzt habt ihr mich so weit.. Ich bau mir mein eigenes Blogsystem — oO oder etwa doch nicht?!

Es macht zwar keinen sinn. Dennoch Baue ich diese Seite von Grund auf neu. Das einzige das ich dabei nutze ist VS 2010 Pro, Resharper 5.1 und SQL-Server Express. Kein fertiges Blogsystem.. Nunja vielleicht wird noch das ein oder andere NuGet Paket mit in die Seite einfließen.. Das sollte es aber dann sein. Mal schauen, wie schnell es hier Vorwärts geht.

Edit 15.05.2011:

  • Das Frontend hat immer noch keine Kommentierfunktion. Dafür habe ich Caching eingebaut. Die Seite rennt eh wie blöd aber man kann ja nie wissen.
  • Permalinks bzw. Blogpostaliase hinzugefügt.
  • Mit dem Template der Seite bin ich erstmal insoweit zufrieden, dass ich mich wieder im die Funtionalität kümmern kann bis ich mich letzlich um das Layout kümmern werd.
  • Kommentarfunktion eingebaut.
    • Whitelist für EMail/Alias kombinationen fehlt noch
  • Meine letzten tweets meiner beiden Twitterkonten sind eingebunden #OMG.. Performancefresser :(

Edit 18.05.2011:

  • FIXED: Tweet Performance. Tweets werden nun via jQuery nachgeladen.

Edit 20.05.2011:

  • Blogposts werden nun, soweit Javascript vorhanden ist mit Ajax nachgeladen.
  • Kleine Usabilityfixes

Edit 06.05.2011:

  • Finally, I´m comming home

 

flattr this!

Leave a Comment

Filed under Allgemein

Das “Interface”, ein unbekanntes Wesen..

Dies ist der erste Artikel meiner Reihe “Objektorientierte Programmierung”. Ziel soll es sein, das Thema Objektorientierung verständlich, und an wirklichen Problemen praktisch angewendet, darzustellen. Sollten sich Fehler einschleichen scheut euch nicht davor diese in den Kommentaren anzusprechen. Dieses ist jedoch nicht als Einführung in das Thema Objektorientierung gedacht. Also ein Grundverständniss für OOP sollte schon vorhanden sein.

Mit erschrecken muss ich immer wieder feststellen das in Unterrichten zum Thema Programmieren und OOP das Thema Interfaces und abstrakte Methoden großräumig umfahren wird. Lieber stürzen sich Lehrer stundenlang auf das Thema Vererbung und machen an ihr die Wartbarkeit und Flexibilität des Codes aus. Und dabei sind es doch gerade die Interfaces, die das Programmieren in Programmiersprachen wie C# oder JAVA so Spannend und Flexibel gestallten. Im deutschen Wikipedia steht zu Interfaces:

Eine Schnittstelle (engl. interface) dient in der objektorientierten Programmierung der Vereinbarung gemeinsamer Signaturen von Methoden, welche in unterschiedlichenKlassen implementiert werden. Die Schnittstelle gibt dabei an, welche Methoden vorhanden sind oder vorhanden sein müssen.

Was bedeutet das für uns als Programmierer? Wir erstellen also mit einem Interface eine Art Vertag den ein Objekt, dass dieses Interface implementiert, erfüllen muss. Wie genau das in der Realität aussieht kann man am folgenden Codebeispiel sehen.

/// &amp;lt;summary&amp;gt;
/// Stellt Methoden bereit, um Objekte Persistent abzulegen
/// &amp;lt;/summary&amp;gt;
public interface IDataStorage
{
/// &amp;lt;summary&amp;gt;
/// Speichert ein Object
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="o"&amp;gt;das zu speichernde Objekt&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;gibt "true" zurück, wenn die Speicherung erfolgreich war&amp;lt;/returns&amp;gt;
bool StoreObject(object o);
 
/// &amp;lt;summary&amp;gt;
/// Gibt ein Objekt zurück
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="i"&amp;gt;Index des Zurückzugebenen Objektes&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;das Objekt an der Indexposition(i), null wenn am Index (i) kein Objekt ist&amp;lt;/returns&amp;gt;
object GetObject(int i);
 
/// &amp;lt;summary&amp;gt;
/// Übergibt ein IEnumerable mit allen Objekten wieder
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
IEnumerable&amp;lt;object&amp;gt; GetAllObjects();
 
/// &amp;lt;summary&amp;gt;
/// Gibt die Anzahl der gespeicherten Objekte zurück
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
int Count();
}

und eine konkrete Implementation dieses Interfaces:

class FilesystemDataStorage : IDataStorage
{
#region fields
 
/// &amp;lt;summary&amp;gt;
/// Ort, an dem die Dateien gespeichert werden
/// &amp;lt;/summary&amp;gt;
private readonly string _storingPath;
 
#endregion
 
#region Constructors
 
/// &amp;lt;summary&amp;gt;
/// Standardconstruktor der Klasse
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="storingPath"&amp;gt;Pfad in dem die Dateien gespeichert weren&amp;lt;/param&amp;gt;
public FilesystemDataStorage(string storingPath)
{
_storingPath = storingPath;
}
 
#endregion
 
#region Helpermethods
 
/// &amp;lt;summary&amp;gt;
/// Gibt die Speichernummer des ersten Freien speichers wieder
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
public int GetFirstFreeSpace()
{
var files = GetDirectory();
var number = files.OrderByDescending(i =&amp;gt; i).First().AsInteger();
return ++number;
}
 
/// &amp;lt;summary&amp;gt;
/// Gibt alle Dateien in der Directory zurück
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
public string[] GetDirectory()
{
return Directory.GetFiles(_storingPath);
}
 
/// &amp;lt;summary&amp;gt;
/// Gibt die Datei am angegeben Pfad als Object zurück
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="path"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
public object GetFile(string path)
{
var r = File.ReadAllBytes(path);
return r;
}
 
#endregion
 
#region Implementation of IDataStorage
 
/// &amp;lt;summary&amp;gt;
/// Speichert ein Object
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="o"&amp;gt;das zu speichernde Objekt&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;gibt "true" zurück, wenn die Speicherung erfolgreich war&amp;lt;/returns&amp;gt;
public bool StoreObject(object o)
{
try
{
File.WriteAllBytes(_storingPath + "\" + GetFirstFreeSpace() + ".obj", o.AsByteArray());
return true;
} catch
{
return false;
}
 
}
 
/// &amp;lt;summary&amp;gt;
/// Gibt ein Objekt zurück
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="i"&amp;gt;Index des Zurückzugebenen Objektes&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;das Objekt an der Indexposition(i), null wenn am Index (i) kein Objekt ist&amp;lt;/returns&amp;gt;
public object GetObject(int i)
{
try
{
return GetFile(_storingPath + "\" + i + ".obj");
} catch
{
return null;
}
}
 
/// &amp;lt;summary&amp;gt;
/// Übergibt ein IEnumerable mit allen Objekten wieder
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
public IEnumerable&amp;lt;object&amp;gt; GetAllObjects()
{
var files = GetDirectory();
foreach (var file in files)
{
yield return GetFile(_storingPath+"\"+file);
}
}
 
/// &amp;lt;summary&amp;gt;
/// Gibt die Anzahl der gespeicherten Objekte zurück
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
public int Count()
{
var files = GetDirectory();
return files.Count();
}
 
#endregion
}

Auf den ersten blick erschließt sich hier für den Laien noch kein wirklicher Sinn, warum wir für die Klasse ein Interface Konstruiert haben. Dieser wird aber bei der Nutzung dieses Interfaces klar.

public class StorageUser
{
#region Fields
 
/// &amp;lt;summary&amp;gt;
/// Privated Feld, dass die Datastorage enthält
/// &amp;lt;/summary&amp;gt;
private IDataStorage _dataStorage;
 
#endregion
 
/// &amp;lt;summary&amp;gt;
/// Constructor der eine DataStorage verlangt
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="dataStorageHandler"&amp;gt;Object welches IDataStorage implementiert&amp;lt;/param&amp;gt;
public StorageUser(IDataStorage dataStorageHandler)
{
_dataStorage = dataStorageHandler;
}
 
/// &amp;lt;summary&amp;gt;
/// KonsumerMethode für die DataStorage
/// &amp;lt;/summary&amp;gt;
public void Consumer()
{
var e = "String für die Datastorage";
_dataStorage.StoreObject(e);
 
Debug.WriteLine("Anzahl der Datensätze in der DataStorage: "+_dataStorage.Count());
}
}

In diesem Beispiel haben wir anstelle der konkreten Klasse “ObjectFileStorageHandler” das nur Interface “IDataStorage” angegeben. Und da die Klasse “ObjectFileStorageHandler” unser Interface implementiert, ist es dank der Polymorphie, die wir bereits aus der Vererbung von Klassen kennen, möglich dem Datentyp “IDataStorage” unsere Instanz der konkreten Klasse zuzuordnen.

Die Vorteile die sich durch das Interface ergeben sollten jetzt klarer sein. Wir haben durch die Definition des Interfaces eine Abstraktionsschicht geschaffen, mit der es im ausführenden Programm egal wird, wie das Interface durch eine konkrete Klasse implementiert wird. Wenn also im laufe der Entwicklung der Art der Speicherung geändert werden sollte z.B. von der Dateiebene auf einen SQL-Server oder sogar in irgend einen cloudbasierten Dienst ist dieses nur noch eine Frage der Implementation des Interfaces, der Programmcode muss dahingehend nicht angepasst werden.

Warum kann ich den Quellcode nicht kompilieren?

Um die Lesbarkeit des Quellcodes zu erhöhen habe ich Erweiterungsfunktionen genutzt (AsByteArray(), AsInteger()), auf diese werde ich in einem weiteren Post eingehen.

Wie geht es Weiter?

In weiteren Teilen werde ich unter anderem noch die Themen:

  • Dependency Injection (mit Ninject)
  • Arbeiten mit Generischen Interfaces
  • Refactoring mit Interfaces
  • Bessere UnitTests durch Interfaces

 

flattr this!

Leave a Comment

Filed under Allgemein

Hier werdet ihr eure Dreamspark-Keys los

Da ich keine Lust hatte jedem eine Erklärung in die Mail zu schrieben hier alles als BlogPost zusammengefasst. Für die Registrierung benötigt ihr eine “Windows Live ID”, wenn ihr über einen Account für Hotmail, den Windows Live Messenger oder XBOX-Live verfügt könnt ihr natürlich auch diesen nutzen.
Öffnet in einem Browser die Seite https://www.dreamspark.com und folgt diesen einfachen Schritten: Continue reading

flattr this!

Leave a Comment

Filed under Allgemein

Automatisches Deployscript mit PowerShell

Um Updates für meine Programme automatisiert auszuführen habe ich mich ein wenig in Powershell eingelesen und folgendes Script zusammengesbastelt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
function Deploy-MeinTool {
$srcPath = "D:TeamProjekteMeinToolMeinToolbinRelease"
$deployPath = "\PrServerToolsMeinTool"
 
# Neuste Revision des Backups ermitteln
$version = Get-ChildItem -Path "$deployPathold" | Sort-Object $_.name -Descending | Select-Object -First 1
[double] $versionNumber = $version.name
$versionNumber += 0.001
$version = "{0:0..000}" -f $versionNumber
$version = $version -replace ",","."
 
Write-Output ""
Write-Output "Deploypfad der neuen Revision: $deployPath"
Write-Output ""
[IO.Directory]::CreateDirectory("$deployPathold$version") &gt; null
 
Write-Output " Verschiebe die alten Dateien "
Write-Output "------------------------------"
Get-ChildItem -Path $deployPath |
Where-Object {$_.name -like "*.exe" -or $_.name -like "*.dll" -or $_.name -like "*.config"} |
ForEach-Object {
$name = $_.name
[System.IO.File]::Move($_.fullname,"$deployPathold$version$name");
Write-Output "$name -&gt; ...old$version$name"
}
 
Write-Output ""
Write-Output "Deploypfad der neuen Revision: $deployPath"
Write-Output ""
 
Write-Output " Kopiere die benötigten Dateien "
Write-Output "--------------------------------"
# Zu Kopierende Dateien Ermitteln
Get-ChildItem -Path "$srcPath" |
Where-Object {$_.name -like "*.exe" -or $_.name -like "*.dll" -or $_.name -like "*.config"} |
ForEach-Object {
$name = $_.name
[System.IO.File]::Copy($_.fullname,"$deployPath$name");
Write-Output "$name -&gt; ...$name"
}
 
Write-Output ""
Write-Output "Fertig.."
 
}

Dieses Script erstellt ein neues PowerShell CmdLet mit dem Namen “Deploy-MeinTool”, welches Automatisch alle *.EXE / *.DLL / *.Config Files in ein fortlaufend nummeriertes Backupverzeichnis sichert um bei Fehlern zu den letzen Punkten zurückkehren zu können. Danach werden alle benötigten Dateien aus dem “Release”-Verzeichnis von VisualStudio in den Ausführungspfad kopiert.

Durch dieses Skript spare ich mir eine menge Zeit für das Deployment von neuen Versionen und schließe so ziemlich jeden Fehler aus, der beim händischen Kopieren eintreten könnte.

TODO´s:

  • Automatischer Buildvorgang des Tools vor dem Deployment, um sicher zu gehen dass sich die neuste Version im ReleasePfad befindet
  • Einstellung für verzögertes Deployment, um ausschließen zu können, das das Tool zur Zeit des Deployments bereits läuft.

flattr this!

Leave a Comment

Filed under Allgemein

MediaWiki als Supporttool für Admins und Programmierer

Als Administrator und Programmierer bin ich von Hause aus ziemlich faul, daher benötigte ich irgendein Tool um meinen Kollegen die wunderbare Softwarewelt zu erklären. Und das am besten nur einmal. Dafür eignet sich ein Tool wieMediawiki bestens. Man kann alles schön strukturiert sortieren und von überall in der Firma bearbeiten. Als weiteres Plus bekommt man durch ein Wiki die Möglichkeit innerhalb der Firma gemeinsam das Wissen zu nutzen und Abläufe zu erleichtern. Das einzige Problem dabei ist nur, wie bekommt man seine Kollegen dazu selbst Inhalte ins Wiki zu schreiben oder sogar sich mit Wikicode auseinanderzusetzen um dann auch wirklich sinnvollen Inhalt ins Wiki zu bringen. Um meinen Chef zu wiederholen: “Super Sache. Aber wahrscheinlich Perlen für die Säue” Letztendlich ist mit der Einrichtung eines Wiki´s nur Vorteile verbunden, ganz egal ob es von allen mit Informationen gefüttert wird oder nicht.

Mediawiki ist wirklich einfach zu Installieren. Man benötigt nur eine Funktionierende PHP Umgebung mit Webserver z.B. Apache oder IIS6/7 und ein wenig Festplattenplatz auf dem Server. Das ist alles!!

Wer etwas mehr Performance benötigt verwendet noch einen Datenbankserver wie MySql für Mediawiki.

 

flattr this!

Leave a Comment

Filed under Allgemein

MeinPaket.de XML-Schnittstelle

Entgegen der aktuellen Trends nutzt die deutsche “Amazon” Kopie, MeinPaket von DHL, keine SOAP Schnittstelle sondern setzt auf eine eigene XML-Schnittstelle mit Http-Post Übermittlung. Somit wird mal wieder von den Entwicklern unsinnige Arbeit gefordert, um diese API für den automatisierten Ablauf einzubinden.

Irgendwie gelang es mir auch nicht für die mitgegebenen “.xsd”-Dateien mit dem .NET Tool xsd.exe einen Proxy zu generieren. Also bedeutet das dieses mal wieder den Proxy selbst schreiben.

using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
 
namespace MeinPaketDataAccessLayer.APIVerbindungen
{
    [XmlRoot(ElementName = "uploadRequest", Namespace = "http://www.meinpaket.de/xsd/dietmar/1.0/products")]
    public class UploadRequest
    {
        [XmlAttribute(AttributeName = "version")]
        public string Version { get; set; }
 
        [XmlElement(ElementName = "header", Namespace = "http://www.meinpaket.de/xsd/dietmar/1.0/common")]
        public Header Header { get; set; }
 
        [XmlArray(ElementName = "deletions")]
        public List&lt;Deletion&gt; Deletions { get; set; }
 
        [XmlArray(ElementName = "categories")]
        public List&lt;Category&gt; Categories { get; set; }
 
        [XmlArray(ElementName = "descriptions")]
        [XmlArrayItem(ElementName = "productDescription")]
        public List&lt;ProductDescription&gt; Descriptions { get; set; }
 
        [XmlArray(ElementName = "offers")]
        [XmlArrayItem(ElementName = "productOffer")]
        public List&lt;Offer&gt; Offers { get; set; }
 
        public string Serialize()
        {
            var serializer = new XmlSerializer(typeof (UploadRequest));
            var stringWriter = new StringWriter();
            var ns = new XmlSerializerNamespaces();
            ns.Add("common", "http://www.meinpaket.de/xsd/dietmar/1.0/common");
            serializer.Serialize(stringWriter, this, ns);
            var e = stringWriter.ToString().Replace("utf-16","utf-8");
            return e;
        }
    }
}

Und die OfferKlasse:

using System;

using System.IO;
using System.Xml.Serialization;
 
namespace MeinPaketDataAccessLayer.APIVerbindungen
{
    [XmlRoot (ElementName = "offer")]
    public class Offer : ProductIdGroup
    {
        /// <summary>
        /// Einzelpreis incl. der gesetzlichen MwSt. mit maximal zwei Nachkommastellen und einem Punkt als Dezimaltrennzeichen.
        /// (Pflichtfeld)
        /// </summary>
        [XmlElement(ElementName = "price")]
        public decimal? Verkaufspreis { get; set; }
 
        /// <summary>
        /// Die im Verkaufspreis enthaltene Mehrwertsteuer. „Standard“ (aktuell 19%) und „Reduced“ (aktuell  7%),
        /// für Artikel ohne Mehrwertsteuer kann „Free“ angegeben werden.
        /// Wird dieses Feld nicht befüllt so wird „Standard“ gesetzt.
        /// </summary>
        [XmlElement(ElementName = "taxGroup")]
        public string SteuerKlassifikation { get; set; }
 
        /// <summary>
        /// Verfügbare Stückzahl (Zahl ohne Nachkommastelle und größer 0) für dieses Produkt.
        /// Die Stückzahl wird bei jedem Verkauf automatisch nach unten gezählt.
        /// Ist die Stückzahl 0 so wird das Produkt nicht mehr als verfügbar angezeigt.
        /// (Pflichtfeld)
        /// </summary>
        [XmlElement(ElementName = "availability")]
        public int Verfügbarkeit { get; set; }
 
        /// <summary>
        /// Datum, ab dem das Produkt für eine Kundenbestellung zur Verfügung steht,
        /// d.h. auf dem Marktplatz zu diesem Händler sichtbar wird.
        /// Das Datum muss in folgendem Format geliefert werden: YYYY-MM-DDThh:mm:ss *
        /// </summary>
        [XmlElement(ElementName = "startDate")]
        public DateTime StartDatum { get; set; }
 
        /// <summary>
        /// Datum, ab dem das Produkt nicht mehr zur Verfügung steht,
        /// d.h. es ist weder sichtbar, noch kann es für eine Bestellung ausgewählt werden.
        /// Das Datum muss in folgendem Format geliefert werden: YYYY-MM-DDThh:mm:ss *
        /// </summary>
        [XmlElement(ElementName = "endDate")]
        public DateTime EndeDatum { get; set; }
 
        /// <summary>
        /// Lieferzeit des Produktes an den Kunden in Tagen, die Lieferzeit muss größer gleich 1
        /// und kleiner gleich 30 sein. Wird die Lieferzeit nicht angegeben, so wird 1, also ein Tag, hinterlegt.
        /// </summary>
        [XmlElement(ElementName = "deliverytime")]
        public int Lieferzeit { get; set; }
 
        /// <summary>
        /// Zuordnung in eine Produktkategorie des eigenen Händler-Shops**
        /// </summary>
        [XmlIgnore]
        [XmlElement(ElementName = "shopCategory")]
        public string HändlerShopKategorie { get; set; }
 
    }
}

Vielleicht nicht die sinnigste Lösung, jedoch war sie schnell und einfach.

EDIT: Mittlerweile muss ich Feststellen, das MeinPaket die wohl Langsamste WebApi hat die ich kenne, ob das am Apache Tomcat oder Java liegt kann ich nicht sagen.

 

flattr this!

Leave a Comment

Filed under Allgemein