webForumDet fria alternativet

Web service flera klasser

.NET

3 svar · 767 visningar · startad av invecklaren

Medlem sedan jan. 2008280 inlägg
Frågan#1

Hej!

Jag vill bygga en web service som är något mer avancerad än alla Hello World-exempel jag hittar.

Låt oss anta att jag har en klass Person som jag vill exponera. Denna person ska ha en Property som heter HomeAddress. HomeAddress är av typen Address, min egen klass som innehåller egenskaperna StreetAddress, ZipCode, Country osv.

Från min konsumerande app vill jag instansiera en Person och börja sätta Personens HomeAddress. För att det ska funka så måste förstås Address-klassen vara exponerad i web-servicen.

Problemet är hur jag ska kunna få Address-klassen exponerad i webservicen. Med följande kod funkar det inte:

Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel

<System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class Person
    Inherits System.Web.Services.WebService
    Private _HomeAddress As Address
    Public Property HomeAddress() As Address
        Get
            Return _HomeAddress
        End Get
        Set(ByVal value As Address)
            _HomeAddress = value
        End Set
    End Property
End Class

<System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class Address
    Private _StreetAddress As String

    Public Property StreetAddress() As String
        Get
            Return Me._StreetAddress
        End Get
        Set(ByVal Value As String)
            Me._StreetAddress = Value
        End Set
    End Property
End Class
Medlem sedan maj 20012 812 inlägg
#2

Din webservice kan bara ha en klass, men många olika metoder. Du kan alltså ha en metod som returnerera en person/lista av personer, och en metod som returener en adress/lista av adresser. Alternativet är att göra 2 HELT separata webservices. Alltså 2 olika asmx-filer.

Jag tycker dock att du tänker lite fel när du vill öppna upp ditt gränssnitt och låta någon klient först hämta personen och sedan hämta en adress för att sedan hämta ytterligare en annan adress. Det ger en massa onödig overhead med en massa onödig trafik över nätet. Istället så när man frågar efter en person så hämtar du alla data som är intressant för denna person, alltså även adresserna följer med personen i första anropet.

Nu skall man givetviss ha lite sunt förnuft här och få en avvägning av datan som skickas med, om en person råkar ha 1000 orders och varje order har 100 orderrader, så är ju det INGET som skall skickas med när man hämtar personens information. Det hela beror ju på hur troligt det är att datan skall visas och det är inte speciellt troligt att du någonsin vill se alla order med alla order rader samtidigt, men just adress informationen är ganska troligt att du vill visa, och dessutom så är det inte speciellt mycket extra data som skickas iväg, vilket gör att vinsten att skicka med den extra datan även om den inte behövs är mer än att ligga och göra en massa extra anrop för att hämta datan när den behövs.

- M

Medlem sedan maj 20012 812 inlägg
#3

Jag tittade lite närmare på din kod, och den ser inte helt "rätt" ut, i mina ögon. Du presenterar inte en class på det sättet i en webservice (inte i normalfallet iallafall). Se din webservice som vilken annan fasadklass som helst, alltså en väg in för att hämta data. Så i ditt exempel så hade jag gjort något sånt här istället.

public class MyWebservice: System.Web.Services.WebService
{
    [WebMethod()]
    public Person[] GetPersons(){...}
    [WebMethod()]
    public Address GetAddress(int identifier){...}
}

[Serializable]
public class Person(){...}

[Serializable]
public class Address(){...}

Eller ännu bättre ta bort GetAddress() metoden och fyll ditt Person objekt med adress information, så du slipper att efterfråga den senare. Och skall vi vara helt petiga så använder du dig inte av RPC-style i dina metoder utan Message-style istället och då blir det så här.

public class MyWebservice: System.Web.Services.WebService
{
    [WebMethod()]
    public GetPersonsResponseMessage GetPersons(GetPersonsRequestMessage){...}
}

[Serializable]
public class GetPersonsRequestMessage(){...}

[Serializable]
public class GetPersonsResponseMessage()
{
     public Person[] Persons{get;set;}
}

[Serializable]
public class Person()
{
   public Address HomeAddress{get;set;}
   public Address BusinessAddress{get;set;}
}

[Serializable]
public class Address(){...}

- M

Medlem sedan jan. 2008280 inlägg
#4

Det låter rätt det du säger. I a f applicerat på mitt enkla exempel.

Jag har dock använt (men inte skrivit) web services som bygger lite på samma princip, som jag ovan beskrivit.
Skillnaden är att de har arbetat med en form av request och response. Requesten hade properties man kunde använda och man kunde sedan skicka iväg hela requesten och få ett response-objekt i retur. Det är väl mer det jag är ute efter, än jobba med person och adress.

270 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
123 ms — deklarationer (db)
0 ms — hämta statistik (cache)
135 ms — hämta tråd, inlägg och bilagor (db)
132 ms — ändringar (db)