WCF i DataContract

Odpowiedz Nowy wątek
2010-09-15 22:11
Moderator

Rejestracja: 9 lat temu

Ostatnio: 57 minut temu

0

Zapoznaję się z WCFem po trochu z tutoriali msdna. Utknęłam jednak w jednej rzeczy - kompletnie nie wiem, jak użyć DataContract. W jak najprostszej wersji. Po stronie serwera mam:

    [DataContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    class LastResults
    {        
        private double result;

        [DataMember]
        public double ResultValue
        {

            get { return result; }
            set { result = value; }
        }
    }

...i kompletnie nie wiem jak to zawołać po stronie aplikacji :/ A przykładu w necie znaleźć nie mogę...

Pozostało 580 znaków

2010-09-16 00:18

Rejestracja: 11 lat temu

Ostatnio: 3 lata temu

0

np.
w kliencie podepnij referencje do dll z kontraktami

utworz ChannelFactory<t>
utworz Channel
uzywaj
zamknij channel i factory

Pozostało 580 znaków

2010-09-16 16:16

Rejestracja: 10 lat temu

Ostatnio: 8 lat temu

0

Jest kilka sposobów, pierwszy z nich podał kolega wyzej, ale wg tego co mówi nam SOA to aplikacje współdzielą SCHEMA a nie KLASY.

Tak więc klasy generuje się z WSDL udostępnianego przez service. Wsdl zawiera wlasnie schematy klas i przykladowo informacje o operacjach ktore mozna wykonac.
Na podstawie wsdl visual studio jest w stanie stworzyć nam interfejs, klasy, a także klase gotowego klienta.

Oczywiscie wczesniej trzeba ustawić aby nasz service udostepnial wsdl (Dodaje się obiekt klasy ServiceMetadataBehavior do instancji klasy ServiceHost (Description).

Jak mamy to juz za sobą, wystarczy odpalic naszą aplikacje, a z drugiego visual studio uzyc opcji AddServiceReference i wpisac adres. Wszystko jest generowane z automatu.


Pozostało 580 znaków

2010-09-16 23:11

Rejestracja: 11 lat temu

Ostatnio: 3 lata temu

0

wsdl oczywiscie mamy kiedy mowimy o web service, jesli hostujemy serwis wcf inaczej (np. tcp) to ogolniej nazywa sie to mex, ale idea ta sama
jesli mamy aplikacje po stronie klienta takze c# i mozemy dostarczyc biblioteke z kontraktami to wydaje mi sie to wlasciwym scenariuszem

Pozostało 580 znaków

2010-09-17 16:45

Rejestracja: 10 lat temu

Ostatnio: 8 lat temu

0

Gdy ma być to SOA, to takie posunięcie jest błędem. Musimy wtedy mieć ciągłą kontrolę nad wszystkimi klientami korzystającymi z naszej usługi i przykładowo w razie jakichś zmian, dostarczać nowych dll z kontraktami i ręcznie zmieniać konfiguracje a nawet prze kompilować. A tak, nasz service jest zarejestrowany w UDDI, klienci mają aktualne konfiguracje i klasy.

No ale zależy jaki to projekt, jeżeli WCF używa się tylko jako technologii do przesyłu informacji to owszem taki scenariusz, jak powiedziałeś, może zaistnieć. Jednak wydaje mi się zbyt wiele 'swoich' założeń przytoczyłeś aby stwierdzić czy faktycznie scenariusz z dll jest jako ten bardziej właściwy.


Pozostało 580 znaków

2010-09-17 17:03

Rejestracja: 11 lat temu

Ostatnio: 3 lata temu

0

ok, jesli SOA, to faktycznie w pelni sie zgadzam

Pozostało 580 znaków

2010-09-19 20:56
Moderator

Rejestracja: 9 lat temu

Ostatnio: 57 minut temu

0

Ok, ale chyba wciąż coś jest nie tak z moim kontraktem. Wkleję cały kod:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Runtime.Serialization;

namespace MyTypes
{
    [DataContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    class LastResults
    {
        private double result;

        [DataMember]
        public double ResultValue
        {

            get { return result; }
            set { result = value; }
        }
    }
}

namespace Microsoft.ServiceModel.Samples
{
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface ICalculator
    {
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
        [OperationContract]
        double Multiply(double n1, double n2);
        [OperationContract]
        double Divide(double n1, double n2);
    }

    class CalculatorService : ICalculator
    {
       MyTypes.LastResults lastResult;

        public double Add(double n1, double n2)
        {
            double result = n1 + n2;
            Console.WriteLine("Received Add({0},{1})", n1, n2);
            // Code added to write output to the console window.
            Console.WriteLine("Return: {0}", result);
            lastResult.ResultValue = result;
            return result;
        }

        public double Subtract(double n1, double n2)
        {
            double result = n1 - n2;
            Console.WriteLine("Received Subtract({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            lastResult.ResultValue = result;
            return result;
        }

        public double Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            Console.WriteLine("Received Multiply({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            lastResult.ResultValue = result;
            return result;
        }

        public double Divide(double n1, double n2)
        {
            double result = n1 / n2;
            Console.WriteLine("Received Divide({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            lastResult.ResultValue = result;
            return result;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");
            ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);

            try
            {
                selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService");
                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                selfHost.Description.Behaviors.Add(smb);

                selfHost.Open();
                Console.WriteLine("The service is ready.");
                Console.WriteLine("Press <ENTER> to terminate service.");
                Console.WriteLine();
                Console.ReadLine();

                // Close the ServiceHostBase to shutdown the service.
                selfHost.Close();
            }
            catch (CommunicationException ce)
            {
                Console.WriteLine("An exception occurred: {0}", ce.Message);
                selfHost.Abort();
            }
        }
    }
}

Widzę wszystkie Operation Contracty, ale Data Contract za nic nie mogę zawołać :/ Zapewne ma to związek z tym, że jedno ma dodane atrybuty kontraktu w interfejsie a drugie nie...? Powinnam to do interfejsu dorzucić? Ale czy nowego, czy tego samego? Czy może być przy jednym interfejsie zarówno atrybut Service Contract jak i Data Contract...?

edit:
To wydzielenie do oddzielnego namespace'a to już wynik moich kombinacji, z początku było w tym samym, ale to raczej nie ma znaczenia - nie działa tak czy siak :P

Pozostało 580 znaków

2010-09-19 22:50

Rejestracja: 11 lat temu

Ostatnio: 3 lata temu

0

zrob klase kontraktu publiczna, moze byc w osobnym namespace

Pozostało 580 znaków

2010-09-20 08:48
Moderator

Rejestracja: 9 lat temu

Ostatnio: 57 minut temu

0

Nic to nie zmieniło :/
A czy powodem moich problemów nie jest przypadkiem to, że nie wystawiam oddzielnego endpointu dla tego kontraktu? Chodzi mi o linijkę:

selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService");

Tutaj dodaję interfejs ICalculator, i faktycznie widzę w Service References wszystkie operacje z tego interfejsu. Nie widzę absoltnie nic na temat klasy LastResult :/ Może za bardzo trzymam się przykładu z msdna? (tam DataContract jest przy klasie, nie przy interfejsie). Może muszę zrobić interfejs?

Pozostało 580 znaków

Dark Astray
2010-09-20 11:36
Dark Astray
0

Nie widzisz, pewnie dlatego że w Interfejsie nie używasz nigdzie tej klasy więc nie ma powodu jej udostępniania na zewnątrz.

Pozostało 580 znaków

2010-09-20 15:54
Moderator

Rejestracja: 9 lat temu

Ostatnio: 57 minut temu

0

To jak sprawić, by był powód? Mnie nie chodzi o funkcjonalnośc. Ja chcę zobaczyć kilka różnych rodzai kontraktów. Chcę mieć możliwość użycia klasy LastResult po stronie klienta, nawet jeśli nie ma ona żadnego sensu ani żadnego związku z interfejsem CalculatorService. Jak dla mnie to może nawet nie przechowywać ostatniego wyniku, być po prostu klasą z jednym doublem dowolnym.

Ponowię pytanie - czy żeby wystawić kontrakt, musi on być nałożony na interfejs? Bo w przykładzie DataContractu na msdnie jest na klasie. Stąd w ogóle wziął się mój kod.

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0