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
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.
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(){...}
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