Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von TiloS
Thema: XSD-Daten in WSDL
Am im Forum: Netzwerktechnologien

Hallo,

ich möchte eine WSDL Dokumentationen für einen SOAP-Webservice erstellen, in der XSDs korrekt dargestellt werden.
Die WSDL kann ich erstellen. Der WSDL-Analyser zeigt dann aber an, dass XSDs importiert werden müssen. Es werden also XSD Imports verwendet.
Wie bekomme ich es hin, dass diese korrekt in der Doku dargestellt werden?

Gruß
Tilo

Thema: Privaten Schlüssel zur Signierung in MessageSignature verwenden
Am im Forum: Web-Technologien

Die Fehlermeldung lautet:

Fehler
"Cannot find the requested object"

Auch das Einlesen in eine Collection bringt den selben Fehler.


    X509Certificate2Collection collection = new X509Certificate2Collection();
    collection.Import(pfxFilename, pfxAndCertPassword, X509KeyStorageFlags.PersistKeySet);

Thema: Privaten Schlüssel zur Signierung in MessageSignature verwenden
Am im Forum: Web-Technologien

Ich versuche jetzt das Zertifikat (inklusive dem privaten Schlüssel) aus dem Keystore zu lesen und dann mit WSE 3.0-Objekten (anstatt WSE 2.0) weiter zu machen. Das verspricht mehr Erfolg. Vorallem, weil ich dabei direkt das X509Certificate2 (was den privaten Schlüssel beinhaltet) nutzen kann.

Nun wirft mir aber das Erzeugen des X509Certificate2 einen merkwürdigen Fehler auf, und zwar:

Fehler
System.Security.Cryptography.CryptographicException: "Das angeforderte Objekt wurde nicht gefunden."

Mein Code dazu:


    string pfxFilename = @"C:\Cert\keystore.pfx";
    string pfxAndCertPassword = "pass";

    X509Certificate2 certFromKeystore = new X509Certificate2(pfxFilename, pfxAndCertPassword);
Es ist nicht so, dass die Datei nicht gefunden wird. Das würde eine andere Fehlermeldung liefern (getestet), sondern irgend ein Objekt wird nicht gefunden.

In dem keystore.pfx sind auch korrekte und gültige Daten enthalten. Im SoapUI-Testcase bin ich damit erfolgreich.

Hat jemand dazu eine Idee?

Thema: Privaten Schlüssel zur Signierung in MessageSignature verwenden
Am im Forum: Web-Technologien

Vielen Dank bis hierher.

Hier ist mal mein Code, damit man sieht, was ich wie vorhabe. Evtl. kann ich das je grundsätzlich so nicht machen?


        //unsigniertes Request
        string request = "<?xml version='1.0' encoding='UTF-8'?>...";

        //SoapClient-Klasse nutzen
        EndpointReference destination = new EndpointReference(uri);
        TcpClient tokenservice = new TcpClient(destination);

        //Request in SoapEnvelope einlesen
        SoapEnvelope envelope = new SoapEnvelope();
        envelope.LoadXml(request);

        //Token erzeugen (public key)
        Microsoft.Web.Services2.Security.X509.X509Certificate certX509 = new Microsoft.Web.Services2.Security.X509.X509Certificate(certByte);
        Microsoft.Web.Services2.Security.Tokens.SecurityToken certToken = new Microsoft.Web.Services2.Security.Tokens.X509SecurityToken(certX509);
        certToken.Id = "b";

        //MessageSignature-Objekt erzeugen
        MessageSignature messageSignature = new MessageSignature(certToken);        //oder XmlDocument?
        messageSignature.Document = envelope;

        //private key
        String privatekey_rsa_format = "<RSAKeyValue><Modulus>00G2um/iUiNi...";
        RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
        rsaCryptoServiceProvider.FromXmlString(privatekey_rsa_format);

        //Zuweisung des private key zum MessageSignatur-Objekt
        messageSignature.SigningKey = ?
        //oder
        messageSignature.SigningToken = ?

        //zu signierende Teile referenzieren und Signierung durchführen
        SignatureReference soapRef1 = new SignatureReference("#t");
        soapRef1.AddTransform(new Microsoft.Web.Services2.Security.Xml.XmlDsigExcC14NTransform());

        SignatureReference soapRef2 = new SignatureReference("#b");
        soapRef2.AddTransform(new Microsoft.Web.Services2.Security.Xml.XmlDsigExcC14NTransform());

        SignatureReference soapRef3 = new SignatureReference("#n");
        soapRef3.AddTransform(new Microsoft.Web.Services2.Security.Xml.XmlDsigExcC14NTransform());

        messageSignature.AddReference(soapRef1);
        messageSignature.AddReference(soapRef2);
        messageSignature.AddReference(soapRef3);

        messageSignature.ComputeSignature();

        //to do: Signatur in das Request einbauen

        //Request absenden
        SoapEnvelope returnEnvelope = tokenservice.RequestResponseMethod(envelope);

Thema: Privaten Schlüssel zur Signierung in MessageSignature verwenden
Am im Forum: Web-Technologien

So unterschiedlich sind m.E. die Typen gar nicht. Der Provider ist auch eine Art Key, er lässt sich z.B. dem PrivateKey des X509Certificate2-Zertifikat zuweisen:


    X509Certificate2 cert2 = new X509Certificate2(certByte);
    cert2.PrivateKey = rsaCryptoServiceProvider;
Das geht.
Der cert2.PrivateKey ist allerdings ein anderer Typ als der SigningKey:
System.Security.Cryptography.AsymetricAlgorithm
vs.
Microsoft.Web.Services2.Security.Security.Cryptography.KeyAlgorithm

Aber Du hast recht, ein X509 Zertifikat aktzeptiert er. Und der SoapClient bekommt natürlich auch ein X509 Zertifikat. Das ist aber der öffentliche Schlüssel, und den hat er schon.
Vielleicht habe ich noch ein Verständnisproblem.

Es geht ja zuerst mal um das MessageSignatur-Objekt, das brauche ich ja für die Signierung. Und für die Signierung brauche ich den privaten Schlüssel. Die erzeugte Signatur würde ich dann in das Request des SoapClient einfügen.
Dem MessageSignatur-Objekt kann ich nebenbei auch noch einen SecurityToken (öff. Schlüssel) mitgeben, aber ich muss ja irgendwo auch den privaten Schlüssel mitgeben, mit dem das MessageSignatur-Objekt die Teile signieren soll.
Oder sehe ich das nicht richtig?

Thema: Privaten Schlüssel zur Signierung in MessageSignature verwenden
Am im Forum: Web-Technologien

Ich habe noch einen Tipp bekommen, den Private Key evtl. im RSA-Format zu nutzen. Mit OpenSSL habe ich mir den in RSA-XML umgewandelt und versuche ihn mit dem RSACryptoServiceProvider zu nutzen. Das sieht dann so aus:


    string privatekey_rsa_format = "<RSAKeyValue><Modulus>00G2um/iUiNip…";
    RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
    rsaCryptoServiceProvider.FromXmlString(privatekey_rsa_format);
Den bekomme ich allerdings nicht in das MessageSignatur-Objekt. Die Zuweisung ist nicht möglich:


    messageSignature.SigningKey = rsaCryptoServiceProvider;
Auch der Umweg über X509Certificate2, bei dem man an das Zertifikat (public key) den PrivateKey mitgeben kann, funktioniert nicht.

Es sieht so aus, als könnte man die Typen nicht ineinander umwandeln. Falls doch wäre ich für jede Hilfe dankbar.

Ich denke, das MessageSignatur-Objekt ist genau für solche Sachen da, also um ein Request mit der Angabe von
- dem öffentlichen Schlüssel (als SecurityToken)
- den Referenzen der zu signierenden Teile und
- dem privaten Schlüssel mit dem das Objekt die entsprechenden Teile signieren soll
zu signieren.

Dann muss es doch auch damit möglich sein. Gibt es da eine Möglichkeit?

Gruß
Tilo

Thema: Privaten Schlüssel zur Signierung in MessageSignature verwenden
Am im Forum: Web-Technologien

Hallo,

ich versuche ein Request eines SoapClient-Objekts mit Hilfe eines MessageSignatur-Objekts mit meinem privaten Schlüssel zu signieren. Der private Schlüssel liegt als String "MIIE6jAc..." oder als .pkcs8-Datei vor.
Das MessageSignatur-Objekt hat einen SecurityToken, in den das X509Zertifikat (öffentlicher Schlüssel) als Token gehört, das sollte passen. Die Signatur-Referenzen habe ich angegeben. Weiterhin hat das Objekt einen SigningToken und einen SigningKey, der meiner Auffassung nach für den privaten Schlüssel vorgesehen ist. Damit sollten die entsprechenden Teile des Requests signiert werden.

Wie mache ich aus dem privaten Schlüssel einen SigningToken oder einen SigningKey? Ich habe dazu leider noch nichts konkretes gefunden.

Den privaten Token wie den öffentlichen Token über ein Microsoft.Web.Services2.Security.X509.X509Certificate zu erstellen, funktioniert nicht. Das ist wohl auch nicht so vorgesehen.


    messageSignature.SigningToken = privateKeyToken;
    //messageSignature.SigningKey =

Hat jemand dazu eine Idee?

Gruß
Tilo

Thema: Wie authentifiziere ich mich an einem Webservice mit einem X509-Zertifikat?
Am im Forum: Netzwerktechnologien

Für die Einbindung der "Microsoft.Web.Services3" sollte man die Web Services Enhancemants (WSE) 3.0 installieren. Das habe ich gemacht und den Verweis auf die Microsoft.Web.Services3.dll hinzugefügt. Beim Debuggen werden die using-Direktiven Microsoft.Web... trotzdem nicht erkannt.
Ich benutze Visual Studio 2013. Hat jemand eine Idee, woran das liegen könnte?

Thema: Wie authentifiziere ich mich an einem Webservice mit einem X509-Zertifikat?
Am im Forum: Netzwerktechnologien

Alles Klar, danke.

gibt es dafür auch ein Tool? Ich möchte erstmal ein Request per SoapUI abschicken.

Thema: Wie authentifiziere ich mich an einem Webservice mit einem X509-Zertifikat?
Am im Forum: Netzwerktechnologien

Hallo,

ich möchte mich an einem Webservice mit einem X509-Zertifikat authentifizieren. Das SOAP Request soll dazu signiert werden. Ich habe bereits ein Schlüsselpaar erzeugt und der öffentliche Schlüssel ist beim Webservice-Anbieter hinterlegt. Im Request gebe ich den öffentlichen Schlüssel und eine Signatur des privaten Schlüssels mit.

Dazu lautet meine Frage: Wie erstelle ich eine Signatur des privaten Schlüssels?
Da tappe ich noch im Dunkeln. Kann man die mit einem Tool und/oder programmatisch beim Aufbau des Requests erstellen? Wenn ja, mit welchem Tool bzw. wie in C#?

Viele Grüße
TiloS

Thema: Dateiname von angezeigtem PDF vorbelegen
Am im Forum: Web-Technologien

Zitat von Abt
Das beeinflusst meines Wissens nach nicht die Serverapplikation, sondern kommt auf das Plugin an, das der Client installiert hat um PDFs anzuzeigen bzw. das Plugin, das der Browser nutzt (Chrome hat sein eigenes).
Heißt dass, ich kann es gar nicht beeinflussen?

Für was wäre dann der Ausdruck "inline; filename=Test.pdf" gut?

Thema: Dateiname von angezeigtem PDF vorbelegen
Am im Forum: Web-Technologien

Hallo zusammen,

ich rufe in einer ASPX-Seite die Anzeige eines PDF-Dokuments auf und möchte, dass dieses PDF zum einen im Browser angezeigt wird und zum anderen, dass das PDF bei einer möglichen Abspeicherung durch einen Benutzer mit einem bestimmten Dateinamen vorbelegt wird.
Ist das möglich?

Ich habe bisher folgendes versucht:


Response.Clear();
Response.ContentType = "application/pdf";
Response.Headers.Add("Content-Disposition", "inline; filename=Test.pdf");
Response.BinaryWrite(arrPdf);
Response.Flush();

Damit wird das PDF im Browser angezeigt, der Dateiname ist aber mit dem Name der ASPX-Seite vorbelegt und nicht mit dem gewünschten.
Gibt es noch andere Möglichkeiten?

Gruß
Tilo

Thema: Namespace-Informationen in Klasse für XML
Am im Forum: Datentechnologien

Hallo,

ich möchte eine XML-Datei für Sepa-Einzüge erstellen. Die Haupt-Klasse der Struktur sieht so aus:


    [XmlRoot("Document")]
    public class Document
    {
        ...
    }
Jetzt sollen aber noch die Namespace-Informationen in das Document-Element integriert werden, so dass es nach dem Serialisieren im XML dann so aussieht:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.002.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.008.002.02 pain.008.002.02.xsd">

Wie bekomme ich das in der obigen Klasse hin?

Gruß
Tilo

Thema: Zugriff auf "Öffentlicher Ordner" - Kontakte von Outlook
Am im Forum: Office-Technologien

Ich hab es jetzt hinbekommen. Man muss sich nur richtig durch die Ordnerstruktur hangeln.


    var outlookApplication = new Microsoft.Office.Interop.Outlook.Application();
    NameSpace mapiNamespace = outlookApplication.GetNamespace("MAPI");
    Folders folders = mapiNamespace.Folders;

    MAPIFolder contacts = null;

    foreach (Folder folder in folders)
    {
        if (folder.Name == "Öffentlicher Ordner")
        {
            foreach (Folder pFolder in folder.Folders)
            {
                if (pFolder.Name == "Kontakte Öffentlich")
                {
                    contacts = pFolder;
                }
            }
        }
    }
Gruß
Tilo

Thema: Zugriff auf "Öffentlicher Ordner" - Kontakte von Outlook
Am im Forum: Office-Technologien

Hallo,

ich möchte die Kontakte des Öffentlichen Ordners auslesen.

Sollte man damit nicht Zugriff bekommen?


    var outlookApplication = new Microsoft.Office.Interop.Outlook.Application();
    NameSpace mapiNamespace = outlookApplication.GetNamespace("MAPI");
    MAPIFolder contacts = mapiNamespace.GetDefaultFolder(OlDefaultFolders.olPublicFoldersAllPublicFolders);
    //MAPIFolder contacts = mapiNamespace.GetDefaultFolder(OlDefaultFolders.olFolderContacts);

Beim Zugriff auf den Ordner erscheint aber eine COMException: "Der versuchte Vorgang konnte nicht ausgeführt werden. Ein Objekt wurde nicht gefunden".

Auf den normalen Outlook Kontakte-Ordner bekomme ich Zugriff, aber nicht auf den öffenlichen. Die pst-Datei des öffentlichen Ordners befindet sich im Netzwerk (auch lokal getestet) und ist im geöffneten Outlook eingebunden.

Wie kann ich darauf Zugriff bekommen?

Gruß
Tilo

Thema: WCF: Asynchrone Webservice-Methoden erzeugen
Am im Forum: Netzwerktechnologien

Hallo nochmal,

nachdem alles so wunderbar funktioniert hat, gibt es jetzt noch ein Problem. Innerhalb meines Webservices (WS1) möchte ich einen weiteren Webservice (WS2) meines Kollegen für spezielle Berechnungen aufrufen. Der Webserviceaufruf soll erstmal nur intern erfolgen. Also ich habe die entsprechende DLL eingebunden und (Korrektur:) einen direkten Zugriff realisiert.

Rufe ich meinen WS1 synchron auf, kann ich innerhalb dieses den WS2 problemlos aufrufen, und er liefert mir das gewünschte Ergebnis.
Beim asynchronen Aufruf des WS1 dagegen liefert er mir beim Aufruf einer WS2-Methode eine Fehlermeldung "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."

Dazu muss man sagen, dass der WS2 ein Settings-Objekt benötigt, welches normalerweise beim Start einer "normalen" WS2-Anwendung in die Session geschrieben wird. Diese Zuweisung mache ich nun auch beim Start meiner WS1-Anwendung, damit das Settings-Objekt dann für den WS2 bereitsteht.
Wie es aussieht, geht aber diese Session im asynchronen WS1 beim Aufruf des WS2 verloren. Im synchronen WS1, bei dem sonst alles gleich ist, funktioniert es wie gesagt.

Gibt es dafür Ideen, wie man das lösen kann?

Gruß
Tilo

Thema: WCF: Asynchrone Webservice-Methoden erzeugen
Am im Forum: Netzwerktechnologien

Hallo Gü,

Zitat
Nimm an dass auf dem Server die BeginOrder- und EndOrder-Methoden vorhanden sind, aber keine Order-Methode.
Das war das erste Problem, ich hatte nämlich noch eine Order-Methode auf dem Server, zu Testzwecken das Ganze komplett synchron. Ok, verstanden.
Zitat
Weiters nimm an dass auf dem Client nur die Order-Methode vorhanden ist.
Wenn nun der Client die (synchrone) Order-Methode aufruft, so verarbeitet der Server die Order asynchron.
Das Prinzip habe ich jetzt auch verstanden. Damit würde es gehen.
Zitat
Nicht unbedingt, denn Client und Server sind unabhängig. Lies dir die Posts dieses Threads nochmals durch - ich weiß es ist schwierig zu verstehen, aber sobald du das Aha-Erlebnis hast wird es einfach.
Der dürfte jetzt eingetreten sein :)
Zitat
Wenn du am Client auf das IAsyncResult angewiesen bist, so muss dieser asynchron arbeiten.
...was nicht ersichtlich ist (ProxyBase, Bindings, endpointAddress).
Lad dir den Anhang herunter, dort ist das zu sehen.
Ok, man muss halt ein bischen weiter lesen. Jetzt ergibt sich ein komplettes Bild.

Das einzige, was mich noch wundert, ist, dass da am Client noch so viel Code zu schreiben ist.

Und da ist mir noch ein Geistesblitz gekommen. Ich habe es ohne den vielen Client-Code jetzt an einer Stelle anders gelöst, was aber genau meine Anforderung erfüllt:
    1. Client holt sich (synchron) die ID vom Server ab.
    2. Server startet (asynchron) den langen Vorgang am Server. (das ist der Witz)
    3. Client prüft (synchron) ob das Ergebnis fertig ist.
    4. Client holt sich (synchron) das Ergebnis vom Server.
Dazu habe ich am Server einfach eine neue synchrone Methode StartOrder, die die BeginOrder asynchron startet und gleichzeitig die gewünschte ID zurückgibt.


public string StartOrder(string input)
{
    OrderAsyncResult res = BeginOrder(input, null, null) as OrderAsyncResult;
    return res.orderID;
}
Damit komme ich zwar nicht automatisch das Ergebnis geleifert, aber die Berechnungen laufen im Hintergrund asynchron. Und die zusätzliche synchrone Abfrage ist für meine Zwecke ausreichend.
Und wenn ich es doch noch machen muss, weiß ich jetzt wie es geht.

Danke und Gruß
Tilo

Thema: WCF: Asynchrone Webservice-Methoden erzeugen
Am im Forum: Netzwerktechnologien

Hallo Gü,

Zitat von gfoidl
Eine elegantere Lösung wäre den ServiceContract in ein eigenes Projekt auszulagern (samt allem dazu benötigten wie das OrderAsyncResult) und dieses vom Server und Client zu referenzieren.
Das ist eine super Idee. Damit müsste es gehen.
Zitat
Der Client will die Order-Methode aufrufen und ob der Server die asynchron od. synchron macht ist dem Client wurscht. Der Client selbst kann asynchron sein und der Server synchron (siehe 1. Antwort). Daher wäre es nicht zielführend das in der WSDL zu manifestieren, man würde sich die Möglichkeiten verbauen und daher ist es besser das nicht explizit anzugeben.
Das ist jetzt wieder die Client-asynchron-Methode?
Zitat
Bei deiner vorigen Lösung reicht 1 Aufruf und daher ist das eher die bessere Lösung.
Bei der Server-asynchron-Methode stehe ich noch auf dem Schlauch. Muss ich dabei die Order oder die Begin-Order-Methode aufrufen?
Die Order-Methode bringt mir doch nicht viel, die ist ja auf dem Server nicht asynchron und die liefert auch kein AsynResult.


MyServiceClient srv = new MyServiceClient();
//OrderAsyncResult res = srv.BeginOrder(input, null, null) as OrderAsyncResult;
//geht nicht, da BeginOrder nicht bekannt
//bzw.
string res = srv.Order(input);
MyServiceClient ist dabei eine bei "Add Service Reference" automatisch erzeugte Klasse.

Oder gibt es irgendwo ein Beispiel, wie ich am Client durch Aufruf der Order-Methode die BeginOrder auf dem Server anstoße und auch das AsyncResult zurückbekomme?
Zitat
Da ich den Client-Code auch selbst schreibe weiß ich jetzt nicht wie svcutil dann damit umgeht bzw. ob es korrekt erkennt dass dieser Typ bereits vorhanden ist. Aber den Client-Code zu erstellen ist recht trivial - schau dir einfach mal an nach welchem Prinzip die generierten Klassen aufgebaut sind, wichtig ist dabei v.a. ClientBase<T>. Du kannst dich auch an WCF: Basisklasse für einen Proxy orientieren.
In deinem Beispiel WCF: Basisklasse für einen Proxy für den Code im Client scheint auch noch was in "Contracts" bzw. "gfoidl.Service.Utils" drin zu sein, was nicht ersichtlich ist (ProxyBase, Bindings, endpointAddress).

Gruß
Tilo

Thema: WCF: Asynchrone Webservice-Methoden erzeugen
Am im Forum: Netzwerktechnologien

Zitat von gfoidl
Was macht bei dir die GetOrderID-Methode?
Die erzeugt nur einen TimeStamp.

private string GetOrderID()
{
    return DateTime.Now.ToString("yyyyMMddHHmmssffff");
}
Die ist also direkt da und ich übergebe sie dem AsyncResult. Das AsyncResult wird dann mit der OrderID zurückgegeben. Jetzt habe ich sie schonmal im Client lange befor ich das eigentliche Ergebnis bekomme. Das hab ich auch so schon am Laufen.
Die OrderID wird dann weiterhin im Server dazu verwendet, den langen Prozess zustarten. Ich gebe sie also dem State mit.
Auf diesen State kann ich dann synchron mit der OrderID zugreifen.
So habe ich momentan im Client den Vorteil, dass ich weiterarbeiten kann, während im Hintergrund die Berechnung läuft.

Mein Problem ist momentan, dass das Ganze nur intern läuft, also aspx-Seite und Webservice auf dem selben Server mit Zugriff auf die entsprechenden DLL's. Von Extern hat der Client keinen Zugriff auf OderAsyncResult. Könnte man das lösen, indem man das OrderAsyncResult nochmal im Client anlegt. Es wiederstebt mir zwar Sachen doppelt zu machen, aber wenn es helfen würde?
Zitat
Diese müsse nicht sichtbar sein, denn - wie bereits öfters erwähnt - ist es dem Client egal ob der Server asnychron od. synchron arbeitet und umgekehrt. Daher macht es keinen Sinn in der Beschreibung, der WSDL, dies festzuhalten.
Wenn ich es theoretisch serverseitig lösen wöllte, müssten doch auch entsprechende Methoden sichtbar sein, die ich dann aufrufen will. Ich möchte ja z.B. von einem externen Client die BeginOrder aufrufen. Müsste sie in dem Fall nicht sichtbar sein?

2. Variante:
Jetzt bin ich aber doch schon fast soweit die Webservice-Aufrufe clientseitig asynchron aufzurufen. Dann würde ich Deine 1. Möglichkeit (Verwendung von Sessions) implementieren.

Die Session würde ich doch nur dazu nutzen, die Aufrufe für einen Vorgang zu identifizieren. Würde das nicht auch mit der ID gehen?
    1. Client holt sich (synchron) die ID vom Server ab.
    2. Client startet asynchron den langen Vorgang am Server (mit Übergabe der ID).
    3. Sobald der Server fertig ist teilt er dies dem Client mit (entweder per End-Methode, Ereignis od. Task) (mit Übergabe der ID)
    4. Client holt sich (synchron) das Ergebnis vom Server (mit Übergabe der ID).


Gruß
Tilo

Thema: WCF: Asynchrone Webservice-Methoden erzeugen
Am im Forum: Netzwerktechnologien

Hallo Gü,

ganz großen Dank für Deine ausführlichen Erklärungen.

Ich hätte es also auch genauso gut mit asynchronem Client-seitigen Aufruf lösen können.
Ich habe aber jetzt Beginxxx- und Endxxx-Methoden, sowie einem eigenen AsyncResult auf dem Server eingerichtet.
Und meine Lösung funktioniert erstmal. Ich habe es an Deine Möglichkeit 1 angelehnt:

    1. Client startet die Beginxxx-Methode, die sofort die OrderID zurückgibt.
    2. Der Server fährt dann fort und startet asynchron den langen Vorgang.

Bis hierhin war das mein Hauptanliegen, und das funktioniert auch. Dann gibt es mehrere Möglichkeiten sich das Ergebnis abzuholen.
    3. Der Einfachheit halber prüfe ich manuell mit einen "Prüfen"-Button den Status meines States per synchronem Webservice-Aufruf. Der State wird anhand der OrderID identifiziert.
    4. Client holt sich (synchron) das Ergebnis vom Server.
Per End-Methode wäre eleganter, da bekommt der Client auch das Ergebnis, nur mit der Anzeige dieses hapert es noch, da an der Stelle die Webseite nicht automatisch aktualisiert wird (aber vielleicht bekomme ich das noch hin).

Hier der Code dazu:


public IAsyncResult BeginOrder(string input)
{
    OrderAsyncResult asyncResult = new OrderAsyncResult(GetOrderID(), input, null, null);
    ThreadPool.QueueUserWorkItem(new WaitCallback(CallbackOrder), asyncResult);
    return asyncResult;
}

private void CallbackOrder(object state)
{
    OrderAsyncResult asyncResult = state as OrderAsyncResult;
    asyncResult.Result = InternalOrder(asyncResult.OrderID, asyncResult.Input);
    asyncResult.Complete();
}

public string EndOrder(IAsyncResult ar)
{
    string result = "";
    using (OrderAsyncResult asyncResult = ar as OrderAsyncResult)
    {
        asyncResult.AsyncWait.WaitOne();
        result = asyncResult.Result;
    }
    return result;
}
Das OrderAsyncResult ist ein von IAsyncResult abgeleitetes Objekt mit zusätzlichen Eigenschaften für OrderID, Result und Input.
Auf diese Weise habe ich dann im AsyncResult die ID:


OrderAsyncResult res = srv.BeginOrder(input) as OrderAsyncResult;
string orderID = res.OrderID;
Die synchronen Webservice-Aufrufe für das Prüfen und das Holen des Ergebnisses sind dann recht unspektakulär.


bool statusReady = srv.CheckOrder(orderID);
und


string result = srv.GetResult(orderID);

Dein Link für die WSDL funktioniert leider nicht:
Zitat
Schau dir dazu auch die WSDL ( http://localhost:8893/myService.svc?wsdl) an, damit du besser verstehst worauf sich das bezieht. Mach das aber besser bei einem einfachen Service, denn sonst wird es gleich unübersichtlich.
Könntest Du da nochmal einen Link geben. Das Thema WSDL wäre für mich noch sehr interessant.

In meiner WSDL, die von dem erstellten Webservice gezogen wird, erscheinen nämlich nicht die Beginxxx und Endxxx-Methoden. Vom Client, der die Projekt-dll referenziert, habe ich natürlich Zugriff, aber ich bin mir nicht sicher, ob der Aufruf von einem entfernten Client genauso funktionieren würde.

Eigentlich müssten doch die BeginOrder und EndOrder-Methoden in der WSDL sichtbar sein? Oder sieht das bei asynchronen Methoden anders aus?

Gruß
Tilo

Thema: WCF: Asynchrone Webservice-Methoden erzeugen
Am im Forum: Netzwerktechnologien

Hallo Gü,

danke für Deine Antwort.
Es ist doch nicht so einfach, wie ich am Anfang dachte. Ich sehe schon etwas klarer, bin aber noch nicht am Ziel.

Ich möchte das in .NET 4.0 umsetzen. Aus folgenden Gründen ist es wahrscheinlich besser, das Server-seitig asynchron zu machen.
1. Ich möchte dem Kunden der das auch nutzen soll clientseitigen Aufwand ersparen.
2. Ich möchte im Webservice eine ID für den Vorgang generiern, und diese schon dem Client zukommen lassen, noch bevor der komplette Vorgang abgearbeitet ist, da das recht lange dauern kann. Der Client soll dann anhand dieser ID Statusprüfungen machen und sich dann das Ergebnis abholen.

Mittlereile bin ich soweit:


[ServiceContract]
public interface IMyService
{
    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginMyMethod(string input, AsyncCallback callback, object state);
    string EndMyMethod(IAsyncResult ar);
}


public class MyService : IMyService
{
    public IAsyncResult BeginMyMethod(string input, AsyncCallback callback, object asyncState)
    {
        MyAsyncResult asyncResult = null;
        asyncResult = new MyAsyncResult(input, callback, asyncState);
        
        return asyncResult;
    }

    public string EndMyMethod(IAsyncResult ar)
    {
        MyAsyncResult asyncResult = ar as MyAsyncResult;
        return asyncResult.result;
    }
}

    public class AsyncResult : IAsyncResult, IDisposable
    {
        AsyncCallback callback;
        object state;
        ManualResetEvent manualResentEvent;

        public AsyncResult(AsyncCallback callback, object state)
        {
            this.callback = callback;
            this.state = state;
            this.manualResentEvent = new ManualResetEvent(false);
        }
    }

    public class MyAsyncResult : AsyncResult
    {
        private int ID { get; set; }
        private string result { get; set; }
        public string input { get; set; }
        public Exception Exception { get; set; }

        public int Result
        {
            get { return result; }
            set { result = value; }
        }

        public MyAsyncResult(string input, AsyncCallback callback, object state)
            : base(callback, state)
        {
            this.input = input;
        }
    }
Mir ist nur noch nicht ganz klar wo (sicher in der BeginMyMethod) bzw. wie ich dort meine eigentliche Methode "MyMethod" aufrufe.

Die ID des Vorgangs müsste ich dann in der BeginMyMethod vor allem anderen erzeugen und dem asyncResult mitgeben.

Im Client sollte das dann nach meinem Stand so aussehen:


IAsyncResult res = service.BeginMyMethod(input, new AsyncCallback(MyCallback), service); 

static void MyCallback(IAsyncResult ar) 
{ 
    IMyService res = ar.AsyncState as IMyService; 
    Label1.Text = res.EndMyMethod(ar).Result.ToString()); 

Bin ich soweit auf dem richtigen Weg? Bzw. wie baue ich da die MyMethod ein?

Gruß
Tilo

Thema: WCF: Asynchrone Webservice-Methoden erzeugen
Am im Forum: Netzwerktechnologien

Hallo,

ich möchte aus einer synchronen Webservice-Methode (WCF-Webservice) eine asynchrone machen.
Nachdem was ich gelesen habe, sollte es so gehen:
- in der ServiceReference "Asynchrone Vorgänge generieren" anklicken
- Die Webservice-Methode muss das Attribut [WebMethod] besitzen
Dann sollte man im Client zusätzliche, automatisch generierte Methoden vorfinden, die mit "Begin..." beginnen.

Dort liegen sie aber in der Webservice-Klasse nicht vor. Fehlt da noch was, habe ich einen Denkfehler, oder wo könnte das Problem liegen?

Die WebService-Methode sieht so aus:


public class MyWebService : IMyWebService
{
   [WebMethod]
    public string Order(string param)
    {
        Thread.Sleep(10000);
        return "";
    }
}


    [ServiceContract(
        Namespace = "NS",
        SessionMode = SessionMode.Allowed)]
    public interface IMyWebService
    {
        [OperationContract]
        [WebInvoke(Method = "POST",
            RequestFormat = WebMessageFormat.Xml,
            ResponseFormat = WebMessageFormat.Xml)]
        string Order(string param);
    }

Bin für jede Hilfe dankbar.

Gruß
TiloS

Thema: Dekomprimieren mit GZipStream funktioniert im Debugger aber ohne Debugger nicht
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

So jetzt hab ich's.

Es lag nicht an der Dekomprimierung, sondern an der Komprimierung. Dort wurden 2 Zeichen am Ende abgeschnitten und damit hatte die Dekomprimierung Schwierigkeiten. Dort stand der Reader beim ReadToEnd schon an der Endposition. Beim direkten nochmaligen ReadToEnd war der outString dann gefüllt.

Die Lösung war aber die Komprimierungsmethode anzupassen. Mit der von "Sarc" hat es dann funktioniert.

Danke.
Gruß
Tilo

Thema: Dekomprimieren mit GZipStream funktioniert im Debugger aber ohne Debugger nicht
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

danke für die Antworten.

Ich habe mal ein paar Screenshots zusammengefügt. Ich muss direkt vor dem auslesen in den StreamReader hineinschauen, ansonsten wird der outString nicht gefüllt, und und ist auch bei einer Ausgabe nicht gefüllt.

Ich vermute auch, dass es irgendwas mit der Handhabung des GZipStream ist, habe aber noch nicht herausgefunden was.

Gruß
Tilo

Thema: Dekomprimieren mit GZipStream funktioniert im Debugger aber ohne Debugger nicht
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

ich möchte gzip-komprimierte Daten dekomprimieren, habe dabei aber einige merkwürdige Phänomäne bei folgendem Code:


byte[] cmpData = Convert.FromBase64String(cmpBase64String);
            
string outString = "";

using (MemoryStream decomStream = new MemoryStream(cmpData))
{
    using (GZipStream gzipStream = new GZipStream(decomStream, compressionMode.Decompress))
    {
        using (StreamReader sr = new StreamReader(gzipStream))
        {
            outString = sr.ReadToEnd();
        }
    }
}
Der outString ist leer. Wenn ich allerdings im Debug-Modus auf der StreamReader-Zuweisung stoppe und dabei in das gzipStream-Objekt hineinschaue, dann sehe ich dass er darin Daten hat. Gehe ich dann einen Schritt weiter, hat auch der StreamReader Daten und der outString wird gefüllt. Schaue ich beim Debuggen nicht in das Objekt, wird der outString bzw. der StreamReader nicht gefüllt.
Wer wüsste dafür eine Erklärung?

Gruß
Tilo

Thema: XML-Dokumentation direkt aus cs-Datei erzeugen (ohne sie compilieren zu müssen)
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hallo,

ich möchte von einem größeren Projekt für einen Teil eine Dokumentation schreiben. Ich habe einzelne cs-Dateien in die ich die XML-Dokumentationskommentare einfüge. Ich habe aber keine Möglichkeit, das gesamte Projekt zu kompilieren, möchte aber trotzdem die Dokumentation als XML erstellen lassen.

Geht das überhaupt ohne das Projekt zu kompilieren, bzw. gibt es irgend ein Tool dafür, welches das kann?

Gruß
Tilo

Thema: Zahl (addierte Binärwerte) in List<int> umwandeln?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Alles klar, vielen Dank.

Thema: Zahl (addierte Binärwerte) in List<int> umwandeln?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

konkret habe ich mit der Suchfunktion nichts gefunden.

Gibt es in C# eine Funktion, die einen Binärwertzahl(Dez-Zahl) in eine Liste von Integerwerten umwandelt?
Z.B. Aus der Zahl 13 möchte ich eine Liste von Zahlen erstellen:


List<int> liste = binToListOfInt(13);
Ergebnis für liste soll sein:
{1,3,4}

Codierung:
1 = 1
2 = 2
3 = 4
4 = 8
5 = 16
...

Oder wie kann ich das anstellen, wenn die Anzahl der Bits nicht bekannt ist?

Gruß
Tilo

Thema: [erledigt] WCF Webservice codebehind-Datei auf Server verfügbar machen
Am im Forum: Netzwerktechnologien

Zitat von gfoidl
Bei zweiterem wird das Markup auf dem Server kopiert und der C#-Code wird in eine Assembly kompiliert und diese wird ebenfalls auf den Server kopiert.

Für dich heißt das nun, dass du das Projekt kompilierst und die *.dll (die Build-Ausgab) auf dem Server in das bin-Verzeichnis kopierst.
Danke. Damit hats funktioniert. Die .cs-Datei ist in einem großen Projekt integriert, welches blöderweise nicht so wie der Webservice heißt. Das hat das Ganze noch mehr verwirrt. Aber mit der .dll gehts jetzt.

Gruß
Tilo

Thema: [erledigt] WCF Webservice codebehind-Datei auf Server verfügbar machen
Am im Forum: Netzwerktechnologien

Hallo,

ich möchte eine kleine Anpassung an einem bestehenden WCF Webservice machen. (Der Entwickler ist leider im Urlaub.) Die Webservice.svc.cs liegt lokal vor, die habe ich angepasst.

Mein Problem ist nun, wie stelle ich die Änderungen auf dem Server zur Verfügung?
Auf dem Server befindet sich die Webservice.svc, die auf die codebehind-Datei verweist. Nur sehe ich da nirgends eine Webservice.svc.cs, die ich überschreiben könnte. Der codebehind-Verweis beinhaltet nur die .cs-Datei ohne Verzeichnisse. Nach meiner Auffassung müsste die doch dann im selben Verzeichnis liegen? Tut sie aber nicht.

Entweder bin ich blind oder ich habe den Mechanismus nicht verstanden. Kann mir jemend auf die Sprünge helfen.

Gruß
Tilo