ایجاد سرویس Restful
شاید بتوان گفت که سرویس های Rest جایگزین وب سرویس ها شده باشند، همانطور
که می دانیم این نوع سرویس از پروتوکل HTTP پشتیبانی می کند و در پروژه های
وب شاید مناسبترین انتخاب باشد. ارسال و دریافت اطلاعات توسط سرویس
های Rest در قالب xml و یا Json اتفاق می افتد که ساختار شناخته شده ای
برای برنامه نویسان هستند.کار کردن با سرویس های REST بسیار ساده تر از کار
کردن با وب سرویس های پیچیده ای مانند SOAP می باشد.
حال برای تبدیل پروژه ایجاد شده ما به سرویس Rest چه باید بکنیم.
ابتدا باید تغییراتی در اینترفیس مربوط به سرویس خود ایجاد کنیم ( کلیه این
تغییرات از یک استاندارد پیروی می کنند که ما هم طبق آن اسلوب باید تغییرات
خود را روی سرویس و میزبان آن ایجاد کنیم. ابتدا به سراغ اینترفیس سرویس
خود می رویم ، همانجا که Service Contract و Operation Contract را
نعریف کرده ایم. سرویس های Rest از چهار متد اصلی مورد نیاز برنامه نویسان
پشتیبانی می کنند، و ما باید به هر کدام از متد های داخل Interface بگوییم
که این متد قرار هست چه کاری برای ما انجام دهد. در کل از چهار دستور زیر
برای تعریف متد های سرویس RESTful استفاده می کنیم :
GET برای بازیابی یک شی
POST برای ویرایش یک شی
PUT برای ایجاد یک شی
DELETE برای حذف یک شی
البته ما در مثال های خود در این مقاله از متد POST برای درچ و از PUT برای
ویرایش استفاده کرده ایم.
با هر بار فراخوانی سرویس ما ،باید یکی از این متد ها به سرور ارسال
شود تا سرور بداند چه عملیاتی را باید انجام دهد.
اولین متد ما در اینترفیس ما متد Add بود که دو پارامتر را از ما
گرفته و جمع آن را به ما برمیگرداند. ابتدا باید مشخص کنیم که متد ما قرار
است کدام یک از دستور های GET , POST ، PUT و یا DELETE را انچام دهد، برای
این کار کافیست که در ابتای تعریف متد عبارت زیر را قرار دهیم:
[WebGet(UriTemplate = "add/{n1}/{n2}")]
[OperationContract]
double Add(double n1, double n2);
برای فعال شدن این امکانات و جلوگیری از خطای کامپایل ابتدا باید یک
Namespace جدید به Reference های پروژه خود اضافه کنیم. از
کتابخانه دات نت System.ServiceModel.Web را به Reference های پروژه اضافه
می کنیم و در ابتدای اینترفیس حود آن را به اصطلاح خودمان Use می
کنیم:
using System.ServiceModel.Web;
چون انتظار داریم متد Add از دستور های Getاستفاده کند از کلید
WebGet استفاده کرده ایم ، همانطور که می بینید از کلمه add برای تعریف
شناسه برای این متد استفاده کرده ایم که می نوانست هر عبارت دیگری نیز باشد
و بعد از آن دو تا پارامتر به URL اضافه می کنیم. در زمان فراخوانی سرویس،
این رشته به انتهای آدرس اولیه سرویس اضافه خواهد شد. مثلا بدین شکل:
http://localhost:8000/GettingStarted/CalculatorService/add/3/4
و به همین صورت هم فراخوانی خواهد شد. همین کار را برای سه متد بعدی انجام
می دهیم. و نتیجه چنین خواهد شد:
namespace GettingStartedLib
{
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
[WebGet(UriTemplate = "add/{n1}/{n2}")]
[OperationContract]
double Add(double n1, double n2);
[WebGet(UriTemplate = "subtract/{n1}/{n2}")]
[OperationContract]
double Subtract(double n1, double n2);
[WebGet(UriTemplate = "multiply/{n1}/{n2}")]
[OperationContract]
double Multiply(double n1, double n2);
[WebGet(UriTemplate = "devide/{n1}/{n2}")]
[OperationContract]
double Divide(double n1, double n2);
}
}
حال باید در پروژه GettingStartedHost در کد مشخص کنیم که چه نوع
سرویس را برای ما هاست کند. بنا براین به جای ایجاد یک سرویس از نوع
ServiceHost در مرحله دوم، یک سرویس از نوع WebServiceHost ایجاد می
کنیم:. کتابخانه System.ServiceModel.Web در اینجا هم باید Use شود.
مرحله سوم نیز بدین ترتیب باید تغییر پیدا کند:
به جای خط کد زیر:
// Step 3 Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService");
از خط کد زیر استفاده می کنیم:
// Step 3 Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(ICalculator), new WebHttpBinding(), "CalculatorService").Behaviors.Add(new WebHttpBehavior());
همانطور که می بینید به جای نوع اتصال WSHttpBinding از نوع اتصال
WebHttpBinding استفاده کرده ایم.
و همچنین یک WebHttpBehavoir هم به آن اضافه کردیم.
اگر بخواهیم میزبان سرویس را اجرا کنیم خطای زیر را دریافت خواهیم کرد:
البته باید خط کد اولیه زیر را به صورت کامنت در آورده یا حذف کنیم:
// Step 3 Add a service endpoint.
//
selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService");
همانطور که مشاهده می کنید، خطایی که رخ داده است به خاطر وجود نوع پارامتر
double است که برای URITemplate تخصیص داده ایم، در صورتی که از روش ارسال
پارامتر به حالت /{n1}/{n2}/{n3}/ بخواهیم استفاده نماییم باید از
نوع string تعریف کرده باشیم. ولی اگر پارامتر های مرتبط با URTemplate را
به روش زیر تعریف کنیم، دیگر نیازی به تغییر نوع پارامتر نیست:
/?n1={n1}&n2={n2}
برای این که بتوانیم هر دو حالت را تست کنیم، پارامتر های ورودی متد اول و
دوم را به روش اول
(/{n1}/{n2}/{n3}/) و متدهای سوم و چهارم را به
روش دوم
(/?n1={n1}&n2={n2}) تعریف می کنیم.
بنابراین در دو متد اول باید نغییراتی را اعمال کنیم. و نوع پارامتر های
ورودی را از double به string تغییر دهیم. بنابراین اینترفیس ما به شکل زیر
تغییر خواهد کرد:
public interface ICalculator
{
[WebGet(UriTemplate = "add/{n1}/{n2}")]
[OperationContract]
double Add(string n1, string n2);
[WebGet(UriTemplate = "subtract/{n1}/{n2}")]
[OperationContract]
double Subtract(string n1, string n2);
[WebGet(UriTemplate = "multiply/?n1={n1}&n2={n2}")]
[OperationContract]
double Multiply(double n1, double n2);
[WebGet(UriTemplate = "devide/?n1={n1}&n2={n2}")]
[OperationContract]
double Divide(double n1, double n2);
}
و کلاس ما نیز به شکل زیر تغییرات خواهد داشت:
public class CalculatorService : ICalculator
{
public double Add(string n1, string n2)
{
double result = Convert.ToDouble(n1)
+ Convert.ToDouble(n2);
Console.WriteLine("Received
Add({0},{1})", n1, n2);
// Code added to write output to the
console window.
Console.WriteLine("Return: {0}",
result);
return result;
}
public double Subtract(string n1, string n2)
{
double result = Convert.ToDouble(n1)
- Convert.ToDouble(n2);
Console.WriteLine("Received
Subtract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}",
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);
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);
return result;
}
}
در پروژه GettingStartedHost چند خط کد زیر را هم اضافه می کنیم تا
نام سرویس و endpoint مربوطه را به ما نمایش دهد. بنابراین مرحله 5 از کد
مربوطه به شکل زیر خواهد بود:
// Step 5 Start the service.
selfHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("{0} is up and running with these endpoints: ",
selfHost.Description.ServiceType);
foreach (var se in selfHost.Description.Endpoints)
{
Console.WriteLine(se.Address);
}
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
حال پروژه GettingStartedHost را اجرا می کنیم تا سرویس ما توسط این برنامه
کنسول میزبانی گردد و ما بتوانیم آن را تست کنیم. بعد ار اجرای پروژه
صفحه زیر نمایان خواهد شد:
حال سرویس Rest ما مهیای
تست است. برای تست باید مرور گر خود را اجرا کرده و URL هایی درستی را که
سرویس ما را فراخوانی می کنند را توسط مرورگر صدا بزنیم. با توجه به تعریفی
که برای چهار متد داخل سرویس داشته ایم URL های مربوطه چنین خواهد بود:
برای تست متد add از url زیر استفاده می کنیم:
http://localhost:8000/GettingStarted/CalculatorService/add/3/4
آن را در بخش آدرس مرورگر وارد کرده و کلید Enter را فشار میدهیم تا اجرا شود. نتیجه زیر را مشاهده خواهیم کرد:
برای متد Subtract از URL زیر استفاده می کنیم:
http://localhost:8000/GettingStarted/CalculatorService/subtract/8/2
آن را در بخش آدرس مرورگر وارد کرده و کلید Enter را فشار میدهیم تا اجرا
شود. نتیجه زیر را مشاهده خواهیم کرد:
اگر بخواهیم دو متد Multuply و Devide را به همین روش فراخوانی کنیم، پیام
خطایی دریافت خواهیم کرد که در زیر میبینیم:
بنابراین نحوه فراخوانی دو متد بعدی باید منطبق با نحوه تعریف پارامتر های
ورودی آن باشد.
پس متد اول را به روش زیر فراخوانی می کنیم و نتیجه را نیز در زیر آن
مشاهده می کنیم:
http://localhost:8000/GettingStarted/CalculatorService/multiply/?n1=17&n2=23
متد دوم را نیز فراخوانی می کنیم و نتیجه را هم مشاهده می کنیم:
http://localhost:8000/GettingStarted/CalculatorService/divide/?n1=170&n2=21
اگر صفحه CMD اجرا کننده میزبان سرویس را مشاهده کنید، کلیه عملیاتی را که
توسط مرورگر فراخوانی کردیم آنجا نیز اجرا شده است.
توابعی را که مشاهده کردید همه از متد GET از سرویس Rest استفاده می
کرد که در اصل برای بازیابی اطلاعات از آنها استفاده می کنیم. حال می
خواهیم برای دو متد POST و DELETE نیز تابعی را نوشته و از آن
استفاده کنیم. برای فراخوانی متد POST و DELETE از یک فایل واسط به نام
httputil.js استفاده خواهیم کرد تا بتوانیم پارامتر های ورودی مورد نیاز
تابع مورد نظر را به آن ارسال کنیم. به عنوان مثال اگر ما بخواهیم یک لیست
از اعداد را به تابع Insert ارسال کنیم باید از این فایل استفاده کرده و یک
لیست از اعداد را در قالب XML به آن ارسال کنیم. البته ما از این فایل واسط
برای این استفاده می کنیم که صحت کارکرد سرویس خود را تست کنیم. در دنیای
واقعی برنامه نوسی سمت سرویس گیرنده، نحوه استفاده از سرویس ها کمی متفاوت
تر خواهد بود.
ما سه متد زیر را به Interface خود اضافه می کنیم:
[WebInvoke(Method = "POST", UriTemplate = "insert")]
[OperationContract]
List<int> InsertList(List<int> numbers);
[WebGet(UriTemplate = "show")]
[OperationContract]
List<int> ShowList();
[WebInvoke(Method = "DELETE", UriTemplate = "delete/{number}")]
[OperationContract]
List<int> DeleteItem(string number);
[WebInvoke(Method = "PUT",
UriTemplate = "edit/{n1}/{n2}")]
[OperationContract]
List<int> UpdateItem(string n1, string n2);
متد اول برای ارسال کردن یک لیست به تابع و وارد کردن آن در یک فضای
ذخیره کننده این مقادیر استفاده خواهد شد. البته چون در مثال ما فضای
فیزیکی مانند فایل یا بانک اطلاعاتی برای ذخیره کردن این دیتا و وارد کردن
این اعداد به بانک اطلاعاتی وجود ندارد، لذا آنها را در یک لیست
(List<int>)
از اعداد که در ابتدای کد تعریف خواهیم کرد نگهداری می کنیم.
متد دوم نیز برای نمایش اعدادی که توسط تابع قبل در لیست ذخیره کردیم پیاده
سازی می شود و متد سوم نیز برای حذف یک عدد از این لیست پیاده
سازی خواهد شد. بدنه سه متد فوق به شکل زیر خواهد بود. لطفا به نحوه تعریف
متد های POST و DELETE و عبارات استفاده شده در سطر های مربوطه دقت کنید.
همانطور که می بینید دیگر از عبارت WebGet خبری نیست و از WebInvoke
استفاده شده است که در این صورت حتما باید غیر از UriTemplate
متد POST یا DELETE را هم در آن قرار دهیم تا سرویس بداند چه رفتاری قرار
هست نشان دهد. ( البته این یک استاندارد در تعریف متدها و توابع داخل
سرویس های REST است).
بدنه متد های پیاده سازی شده در داخل کلاس سرویس ما بدین شکل خواهد بود.
public List<int> InsertList(List<int> numbers)
{
for (int i = 0; i < numbers.Count; i++)
{
NumberList.Add(numbers[i]);
Console.WriteLine("Number is ({0})",
numbers[i]);
}
return numbers;
}
public List<int> ShowList()
{
for (int i = 0; i < NumberList.Count; i++)
{
Console.WriteLine("Number is ({0})",
NumberList[i]);
}
return NumberList;
}
public List<int> DeleteItem(string number)
{
for (int i = 0; i < NumberList.Count; i++)
{
if (NumberList[i] ==
Convert.ToInt32(number))
{
NumberList.RemoveAt(i);
}
Console.WriteLine("Deleted Number is
({0})", NumberList[i]);
}
return NumberList;
}
public List<int> UpdateItem(string n1, string n2)
{
for (int i = 0; i < NumberList.Count; i++)
{
if (NumberList[i] ==
Convert.ToInt32(n1))
{
NumberList[i]
= Convert.ToInt32(n2);
}
Console.WriteLine("Number changed
from ({0}) to ({1})", n1, NumberList[i]);
}
return NumberList;
}
NumberList را هم به صورت static در بالای کلاس خود تعریف می کنیم تا
بتوانیم در طول اجرای برنامه از مقادیر داخل آن در توابع خود استفاده کنیم.
بدین شکل:
private static List<int> NumberList = new List<int>();
حال متد های ما آماده اند تا از آنها استفاده کنیم. برای تست متد های
POST،DELETE , PUT نیاز به ابزاری داریم که دیتای ما را به متد های نوشته
شده پاس کند. یک ابزار به نام httputil.js وجود دارد که ما از آن
برای تست صحت کارکرد متد های خود استفاده خواهیم کرد، می توانید با جستجوی
ساده در اینترنت به این ابزار دسترسی پیدا کنید.
برای تست متد اول به نام InsertList نیاز داریم ما یک لیست از اعداد
به آن ارسال کنیم، برای این کار باید یک فایل XML به آن ارسال کنیم که شامل
اعداد مورد نظر ما باشند. ما اگر یک متدی بنویسیم که اعداد زوح بین 20 و
100 را به عنوان یک لیست برای ما ارسال کند، یعنی خروجی تابع اشاره شده
لیستی از این اعداد باشد ، و در مرورگر به روش های اشاره شده قبلی آن متد
را فراخوانی کنیم، خروجی آن یک XML به شکل زیر خواهد بود:
<ArrayOfint
xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<int>20</int>
<int>22</int>
<int>24</int>
<int>26</int>
<int>28</int>
<int>30</int>
<int>32</int>
<int>34</int>
<int>36</int>
<int>38</int>
<int>40</int>
<int>42</int>
<int>44</int>
<int>46</int>
<int>48</int>
<int>50</int>
<int>52</int>
<int>54</int>
<int>56</int>
<int>58</int>
<int>60</int>
<int>62</int>
<int>64</int>
<int>66</int>
<int>68</int>
<int>70</int>
<int>72</int>
<int>74</int>
<int>76</int>
<int>78</int>
<int>80</int>
<int>82</int>
<int>84</int>
<int>86</int>
<int>88</int>
<int>90</int>
<int>92</int>
<int>94</int>
<int>96</int>
<int>98</int>
<int>100</int>
</ArrayOfint>
ممی توانیم نتیجه بگیریم که اگر همین ساختار را درون یک فایل xml ذخیره کنیم
و در صورت نیاز اعداد دلخواه خود را جایگزین اعداد جاری کنیم، می توانیم به
عنوان پارامتر ورودی به تابع خود ارسال نماییم.
ابتدا می خواهیم متد InsertList را فراخوانی نماییم. برای این کار به روش
زیر عمل می کنیم.
ابتدا فایل httputil.js و فایل xml ار در یک پوشه کنار هم قرار می دهیم.
CMD را اجرا می کنیم و با اجرا و فراخوانی احکام مورد نیاز داخل فولدر
مربوطه می رویم
کد زیر را اجرا می کنیم تا محتوای فایل XML ما به تابع مربوطه ارسال شده و
آن تابع اجرا گردد.
httputil.js POST http://localhost:8000/GettingStarted/CalculatorService/insert evennumbers.xml
در اصل نحوه استفاده از فایل httputil.js به شکل زیر است:
Usage: httputil.js method uri file
که اگر مشاهده بکنید، مقدار مناسب هر عبارت جایگزین شده و سپس دستور مربوطه
فراخوانی شده است.
بعد از اجرای دستور فوق پیام زیر ظاهر خواهد شد:
بعد از اجرای این دستور اعداد زوج داخل این XML به متد InsertList
ارسال شده و این متد نیز آنها را داخل لیست NumberList ذخیره می کند.
برای اینکه مطمئن شویم، حال تابع و متد ShowList را فراخوانی می کنیم
تا محتوای لیست NumberList را به ما نشان دهد.
عبارت زیر را در بخش آدرس مرورگر خود وارد کرده و کلید Enter را فشار می
دهیم.
http://localhost:8000/GettingStarted/CalculatorService/show
نتیجه کار چنین خواهد بود:
حال متد DeleteItem را تست می کنیم. برای تست این متد نیز عبارت زیر
را در CMD فراخوانی می کنیم.
httputil.js DELETE http://localhost:8000/GettingStarted/CalculatorService/delete/20
این دستور عدد 20 را در صورت وجود داشتن در لیست NumberList ، این عدد
را از لیست حذف می نماید.
ابن دستور را برای چند عدد دیگر تکرار می کنیم.
httputil.js DELETE http://localhost:8000/GettingStarted/CalculatorService/delete/40
httputil.js DELETE http://localhost:8000/GettingStarted/CalculatorService/delete/52
httputil.js DELETE http://localhost:8000/GettingStarted/CalculatorService/delete/66
حال اگر دستور زیر رو مجددا فراخوانی کنیم نتیجه زیر مشاهده خواهد
شد:
http://localhost:8000/GettingStarted/CalculatorService/show
همانطور که مشاهده می کنید، اعداد 20و 40،52،66 از لیست ما حذف شده اند.
نتیجه کار چنین خواهد بود:
حال متد UpdateItem را تست می کنیم. برای تست این متد نیز عبارت زیر
را در CMD فراخوانی می کنیم.
httputil.js PUT http://localhost:8000/GettingStarted/CalculatorService/edit/30/55555
این دستور عدد 30 را در صورت وجود داشتن در لیست NumberList ، با عدد
555555 جایگزین می نماید.
ابن دستور را برای چند عدد دیگر تکرار می کنیم.
httputil.js PUT http://localhost:8000/GettingStarted/CalculatorService/edit/50/55555
httputil.js PUT http://localhost:8000/GettingStarted/CalculatorService/edit/60/55555
httputil.js PUT http://localhost:8000/GettingStarted/CalculatorService/edit/70/55555
حال اگر دستور زیر رو مجددا فراخوانی کنیم نتیجه زیر مشاهده خواهد
شد:
http://localhost:8000/GettingStarted/CalculatorService/show
بدین ترتیب نحوه تبدیل سرویس ما به یک سرویس Restful نشان داده شد.
ما در پروژه GettingStartedSite نیز باید تغییراتی را اعمال کنیم تا
بتوانیم از سرویس مربوطه که در IIS میزبانی کرده ایم استفاده کنیم.
ابتدا سراغ پروژه GettingStartedHost میرویم. برای اینکه کد قبلی را حفظ
کنیم، داحل فایل اصلی پروژه به نام Program.cs یک متد به نام StartServiceHostProgrammatically ایجاد کرده و کد
قبلی را داخل آن Paste می کنیم.
private static void StartServiceHostProgrammatically()
{
// Step 1 Create a URI to serve as the base address.
Uri baseAddress = new
Uri("http://localhost:8000/GettingStarted/");
// Step 2 Create a WebServiceHost instance
WebServiceHost selfHost = new
WebServiceHost(typeof(CalculatorService), baseAddress);
try
{
// Step 3 Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(ICalculator), new
WebHttpBinding(), "CalculatorService").Behaviors.Add(new
WebHttpBehavior());
// Step 4 Enable metadata exchange.
ServiceMetadataBehavior smb = new
ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
// Step 5 Start the service.
selfHost.Open();
Console.WriteLine("The service is
ready.");
Console.WriteLine("{0} is up and
running with these endpoints: ", selfHost.Description.ServiceType);
foreach (var se in
selfHost.Description.Endpoints)
{
Console.WriteLine(se.Address);
}
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();
}
}
اگر به یاد داشته باشید کلیه تنظیمات مربوط به سرویس داخل کد تعریف می شد
که الان داخل متد StartServiceHostProgrammatically قرار دارد. حال
می خواهیم بخشی از تنظیمات مربوطه را داخل App.config قرار دهیم. کد
فعلی داخل App.Config به شکل زیر است:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>
همانطور که مشاهده می فرمایید هیچ کدی در رابطه با سرویس ما در این فایل وجود ندارد
. حال تنظیمات زیر را به این فایل اضافه می کنیم ( نحوه تعریف استانداردی
دارد که باید رعایت گردد):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5"/>
</startup>
<system.serviceModel>
<services>
<service
name="GettingStartedLib.CalculatorService">
<endpoint address="http://localhost:8000/GettingStarted/CalculatorService"
binding="webHttpBinding" bindingConfiguration=""
contract="GettingStartedLib.ICalculator" />
</service>
</services>
</system.serviceModel>
</configuration>
از المان های داخل این تنظیمات کاملا معلوم است که به چه هدفی قرار داده
شده اند.
name برای قرار دادن نام سرویس همراه با nameSpace مربوطه است.
همانطور که می دانید endpoint برای مشخص کردن نحوه اتصال ماست که چند المان
دارد:
address که آدرس و در اصل به نوعی URL است که توسط آن سرویس فراخوانی می
شود.
binding نحوه و پروتکل اتصال ما را تعیین می کند که در سرویس های webHttpBinding ، Restful است
Contract نیز به قرار داد ما اشاره دارد که در اصل آدرس اینترفیس ماست.
حال تنظیمات ما آماده است و App.config تکمیل شده است. این تنظیمات را به
روش دیگری نیز می توانیم انجام دهیم که قبلا در مورد آن صحبت کرده ایم و آن
استفاده از ویزارد Edit WCF Configuration است.
تصاویر مرحله به مرحله آن را مشاهده می کنید، فراموش نشود بعد از اتمام کار
باید تغییرات انجام یافته ذخیره گردد تا در App.Config اعمال گردند. فقط در
انتها باید نوع binding را به webHttpBinding تغییر دهیم.
مرحله اول :
مرحله دوم:
مرحله سوم:
مرحله چهارم:
مرحله پنجم:
مرحله ششم:
حال کد دیگری را باید در پروژه GettingStartedHost ، جایگزین کد قبلی
کنیم، یعنی در اصل تغییر کوچکی در کد قبلی باید بدهیم. کد جدید را داخل یک
متد قرار می دهیم و آن را در جای خود فراخوانی می کنیم. متد جدید با کمی
تغییرات روی کد قبلی به شرح زیر خواهد بود.
private static void StartServiceHost()
{
// Step 1 Create a WebServiceHost instance
WebServiceHost selfHost = new
WebServiceHost(typeof(CalculatorService));
try
{
// Step 2 Start the service.
selfHost.Open();
Console.WriteLine("The service is
ready.");
Console.WriteLine("{0} is up and
running with these endpoints: ", selfHost.Description.ServiceType);
foreach (var se in
selfHost.Description.Endpoints)
{
Console.WriteLine(se.Address);
}
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();
}
}
همانطور که مشاهده می فرمایید از 5 مرحله تعریف و فعال سازی سرویس تنها دو
مرحله آن را نیاز داریم تا بتوانیم سرویس خود را میزبانی کنیم. مراحلی را
که از کد حذف کرده ایم به نحوی در داخل Web.Config قرار داده شده
اند.
ححال نوبت اعمال تغییرات در پروژه
GettingStartedSite است که از طریق این پروژه سرویس خودر را روی IIS هاست
کرده ایم. فایل Web.config را باز کرده و کلیه کد های مرتبط به
سرویس را کامنت می کنیم، می خواهیم کاری کنیم نا همه این تنظیمات به
طور اتوماتیک اتفاق بی افتد. بعد از کامنت کردن کد های مرتبط با تعریف و
تنظیمات سرویس کد زیر را خواهیم داشت:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add
key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="false"
targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<!-- Deleted From Here -->
<!--<system.serviceModel>
<services>
<service
name="GettingStartedLib.CalculatorService">
<endpoint address="basic" binding="basicHttpBinding"
bindingConfiguration="" name="basicHttpBinding"
contract="GettingStartedLib.ICalculator" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add
binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"
/>
</system.serviceModel>-->
<system.webServer>
<modules
runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory
during debugging, set the value below to true.
Set to false before deployment to
avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
کدی که به رنگ سبز نوشته شده است کدی است که میتواند حذف گردد. حال یک
تغییر کوچک در فایل Service.svc می دهیم .
اگر فایل Service.svc را باز کنیم کد زیر را مشاهده خواهیم کرد:
<%@ ServiceHost Language="C#" Debug="true"
Service="GettingStartedLib.CalculatorService"%>
کد زیر زیر را به انتهای کد فوق اضافه می کنیم و تمام.
Factory="System.ServiceModel.Activation.WebServiceHostFactory"
پس کد انتهایی چنین خواهد بود:
<%@ ServiceHost Language="C#" Debug="true"
Service="GettingStartedLib.CalculatorService"
Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>
ححال سرویس میزبانی شده ما روی IIS آماده استفاده است. برای تست آن ، مراحل
زیر را مشابه با مراحلی که در بخش های قبلی انجام داده ایم ، انجام می
دهیم.
ابتدا فایل Service.svc را فراخوانی می کنیم تا url ما برای فراخوانی
معلوم گردد. برای ان کار روی Service.svc داخل پروژه کلیک راست می کنیم و
سپس View In Browser را کلیک می کنیم. صفحه ای روی مرورگر باز
شده و عبارت زیر مشاهده می شود.
url ما مشخص شد: http://localhost:5532/Service.svc
حال url بالا را جایگزین url قبلی
(http://localhost:8000/GettingStarted/CalculatorService) می کنیم. و url
های زیر را در مرور گر صدا می کنیم تا نتایج را مشاهده کنیم:
1) http://localhost:5532/Service.svc/add/3/4 را
صدا می زنیم نتیجه زیر حاصل می شود:
2) http://localhost:5532/Service.svc/subtract/1/2 را
صدا می زنیم و نتیجه زیر حاصل می شود:
3) http://localhost:5532/Service.svc/multiply/?n1=17&n2=23 را صدا می زنیم
و نتیجه زیر بدست می آید:
4) http://localhost:5532/Service.svc/divide/?n1=170&n2=21
را صدا می زنیم و نتیجه زیر را خواهیم دید:
5) حال مثل روش قبلی می خواهیم از طریق httputil.js متد
http://localhost:5532/Service.svc/insert را فراخوانی کنیم. بعد از
فراخوانی url مربوطه از طریق Command Prompt نتیجه زیر را خواهیم داد:
6) حال اگر آدرس http://localhost:5532/Service.svc/show
را فراخوانی کنیم نتیجه زیر را مشاهده خواهیم کرد:
7) حال می خواهیم چند عدد را از این لیست حذف کنیم و متد Delete را
فراخوانی کنیم.
متد های زیر را از طریق CMD فراخوانی و اجرا می کنیم:
httputil.js DELETE http://localhost:5532/Service.svc/delete/20
httputil.js DELETE http://localhost:5532/Service.svc/delete/40
httputil.js DELETE http://localhost:5532/Service.svc/delete/52
httputil.js DELETE http://localhost:5532/Service.svc/delete/66
حال اگر آدرس http://localhost:5532/Service.svc/show را دوباره فراخوانی
کنیم نتیجه زیر را مشاهده خواهیم کرد:
8) حال می خواهیم چند عدد را در لیست ویرایش کنیم و متد Update را
فراخوانی کنیم.
متد های زیر را از طریق CMD فراخوانی و اجرا می کنیم:
httputil.js PUT http://localhost:5532/Service.svc/edit/30/55555
httputil.js PUT http://localhost:5532/Service.svc/edit/50/55555
httputil.js PUT http://localhost:5532/Service.svc/edit/60/55555
httputil.js PUT http://localhost:5532/Service.svc/edit/70/55555
حال اگر آدرس http://localhost:5532/Service.svc/show را دوباره فراخوانی
کنیم نتیجه زیر را مشاهده خواهیم کرد:
همانطور که مشاهده فرمودید در ابتدای URL های ما عبارت
http://localhost:5532/Service.svc قرار داشت، این آدرسی هست که IIS
Express در اختیار ما قرار می دهد. امکان این وجود دارد که عدد موجود در
این URL در اجرا های بعدی تغییر یابد. اگر به خاطر داشته باشید ما
سرویس خود را در IIS اصلی ویندوز نیز میزبانی کردیم و بنابراین ما می
توانیم با
جایگزین کردن آدرس فوق با آدرس
http://localhost/GettingStartedSite/Service.svc
احتمال بروز این مشکل را به صفر برسانیم و کلیه عملیات قبلی را با
URL جدید انجام دهیم.