雖然Web Service早就不是什麼新玩意兒,透過SOAP來進行資料交換/傳輸也不是什麼新奇的科技,不過還是有個和Web Service相關的「玩具」想要和大家分享一下。
前言
雖然Web Service早就不是什麼新玩意兒,透過Soap來進行資料交換/傳輸也不是什麼新奇的科技,不過還是有個和Web Service相關的「玩具」想要和大家分享一下。
有透過Visual Studio開發/引用過WebService的朋友們應該都有親身體驗過Visual Studio針對Web Service所帶來的威力及便利性,我們只需要輕鬆的透過Visual Studio輸入要參考的Web Service中所提供的WSDL網址,Visual Studio就會替我們產生一整套的Proxy,以方便我們可以直接透過平常熟悉的撰寫物件導向程式的方法去叫用位於遠端的Web Service,一切看起來就如同引用一顆dll一樣那麼的輕鬆自然…
如下圖,當在專案中透過Visual Studio加入Web Service參考時,Visual Studio就會依據該Web Service的WSDL幫我們處理掉圖中網路左邊的部份。
也基於上述的特性,Web Service的中的介面一旦定義好了,就不建議再去做任何修改,否則Client端就得透過新版的WSDL更新參考,產生符合新介面的Proxy;若資料需要進行加解密,一般也會建議在設計階段就先考慮進去,將加密後的資料格式一併定義在Web Method中,才不致於在日後又得改動到WSDL。
不過!!!!!~事情總是不會永遠如預期般順利的發展下去,總是會有特殊的需求來為我們的生活增添「趣味」…例如有客戶希望你不變動整個WSDL的結構,但是又要以加密過的特殊格式來當傳SOAP訊息中的SOAP Body時,原來簡單的Web Service,就變得不那麼簡單了。
準備
為了能夠以貼近現實案例的方式來講解這次的範例,我們必需先準備好兩個專案,分別為Web Service本身及一個Consumer端的應用程式(這邊以一個簡單的WPF應用程式來實作)。
我們先以Visual Studio 2012來建立一個簡單的Web Service(請注意,在Visual Studio 2012中建立Web Service專案的話需要選取.Net Framework 3.5才會出現專案樣版供我們選擇)。
Web Service專案建立完成後,在專案中建立一個Models資料夾,並且在裡面加入一個自訂的Member類別:
namespace MySimpleWebService.Models
{
public class Member
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool Sex { get; set; }
}
}
並且稍微的調整一下Web Service的名稱及內容:
using MySimpleWebService.Models;
using System.Collections.Generic;
using System.Linq;
using System.Web.Services;
namespace MySimpleWebService
{
[WebService( Namespace = "http://tempuri.org/" )]
[WebServiceBinding( ConformsTo = WsiProfiles.BasicProfile1_1 )]
[System.ComponentModel.ToolboxItem( false )]
public class SimpleService : WebService
{
private static List<Member> _allMembers;
public SimpleService()
{
if( _allMembers == null )
{
_allMembers = new List<Member>
{
new Member{ Id = 0 , Age = 35 , Name = "Ouch" , Sex = true },
new Member{ Id = 1 , Age = 27 , Name = "Sandy" , Sex = false },
new Member{ Id = 2 , Age = 30 , Name = "Wei" , Sex = true },
new Member{ Id = 3 , Age = 30 , Name = "Cross" , Sex = true },
new Member{ Id = 4 , Age = 10 , Name = "尼古拉" , Sex = true },
};
}
}
[WebMethod]
public List<Member> ListAllMembers()
{
return _allMembers;
}
[WebMethod]
public bool UpdateMember( int id , Member updatedMember )
{
Member member = _allMembers.FirstOrDefault( m => m.Id == id );
if( member == null )
{
return false;
}
member.Age = updatedMember.Age;
member.Name = updatedMember.Name;
member.Sex = updatedMember.Sex;
return true;
}
[WebMethod]
public List<Member> QueryMembersBySex( bool sex )
{
return _allMembers.Where( m => m.Sex == sex ).ToList();
}
}
}
完成之後按下F5鍵進行除錯,確認Web Service可以執行:
![]() |
![]() |
Web Service的部份完成之後,再來就要準備叫用它的Client端WPF應用程式了,這邊就直接在同一個方案中建立一個新的WPF專案,並且將專案中的Web Service加入參考,方法如下:
在方案總管的WPF專案名稱上按下滑鼠右鍵,選取Add Service Reference...,並且於彈出的對話視窗中點選Advanced...按鈕
接著在進階設定視窗中點選Add Web Reference...鈕,就會出現加入Web Service參考的視窗。
點選Web services in this solution以找到同方案中的Web Service。
找到我們剛才建立好的Web Service後,點擊Web Service列表中的連結。
確認Web Service的內容無誤後,在Web reference name欄位中輸入Client端服務的自訂名稱之後按下Add Reference按鈕,到這邊為止,我們就做好了讓WPF應用程式能呼叫Web Service的準備工作了。
接下來對WPF應用程式的UI及Code-Behind稍做修改,讓它可以真正的呼叫我們的Web Service。
<Window x:Class="MySimpleWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MySimpleWebService Test Window" Width="800" Height="600" WindowStartupLocation="CenterScreen" FontSize="14">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,10,0" VerticalAlignment="Center">Query members by sex:</TextBlock>
<RadioButton Name="rdoMale" IsChecked="True" Margin="0,0,10,0" VerticalAlignment="Center">Male</RadioButton>
<RadioButton Name="rdoFemale" Margin="0,0,10,0" VerticalAlignment="Center">Female</RadioButton>
<Button Name="btnQuery" VerticalAlignment="Center" Padding="5" Click="btnQuery_Click">Query</Button>
</StackPanel>
<Rectangle Grid.Row="1" StrokeThickness="0" Height="2" Fill="#FF646464" Margin="0,5"></Rectangle>
<DataGrid Name="dgdMembers" Grid.Row="2" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Id}" Header="Id" MinWidth="100"/>
<DataGridTextColumn Binding="{Binding Name}" Header="Name" MinWidth="100"/>
<DataGridTextColumn Binding="{Binding Age}" Header="Age" MinWidth="100"/>
<DataGridCheckBoxColumn Binding="{Binding Sex}" Header="Sex" MinWidth="100"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
using MySimpleWpfApp.MySimpleService;
using System.Windows;
namespace MySimpleWpfApp
{
public partial class MainWindow : Window
{
private SimpleService _simpleService = new SimpleService();
public MainWindow()
{
InitializeComponent();
}
private void btnQuery_Click( object sender , RoutedEventArgs e )
{
dgdMembers.ItemsSource = _simpleService.QueryMembersBySex( rdoMale.IsChecked == true );
}
}
}
完成之後,再透過除錯功能做個小測試,確認WPF應用程式真的可以透過Web Service取得資料,並且顯示在畫面上:
到這邊為止,我們就完成了最基本的Web Service與Client端的開發作業。(沒錯!!!...現在還沒進入正題~我們下集待續~~)
本文專案原始碼如下,請自行取用: