WCF 4 (Windows Communication Foundation) for Beginner – part 8

18 בינואר 2011

תגיות: ,
3 תגובות



ללמוד WCF 4 פרק 8 – כתיבה של שירותים ב – web style והפעלה שלהם בעזרת קריאות GET ו – POST

 

 

(תודה לעידו על העזרה עם פוסט זה)

 

נושאים בפרק 8:


מה המשמעות של כתיבת שירותים web style.

להכיר את webHttp behavior וחלק מהמאפיינים שלו.

להכיר את WebGetAttribute, WebInvokeAttribute וחלק מהמאפיינים שלהם.

צריכה של שירות המוגדר כ – webHttp.

להכיר את WebServiceHost.

 

 

מה המשמעות של כתיבת שירותים web style.


לפעמים אנחנו רוצים לכתוב שירותים שיחשפו את המידע לא ב – SOAP אלא בפרוטוקולים אחרים, למשל כדי לאפשר יצירת RSS או כמו שראינו בדוגמא בפרק הקודם (להפעיל את השירות בעזרת AJAX) ואפילו לאפשר להפעיל את המתודות בצורה ישירה בעזרת גלישה בדפדפן (כמו ב – REST) ולאפשר להחזיר מידע בפורמטים שונים כמו JSON (שהוא יותר חסכוני בתעבורה, למעשה גם XML יותר חסכוני מ – SOAP), כדי לעשות את זה כבר ראינו בפרק הקודם שה – binding צריך להיות webHttpBinding, בפרק היום נראה עוד מידע הקשור ל – webHttpBindgin וה – behavior שמשמש אותו.

 

 

להכיר את webHttp behavior וחלק מהמאפיינים שלו.


כדי להתחיל לעבוד עם web style services מעבר לעובדה שצריך להגדיר את ה – binding כ – webHttpBinding צריך גם להגדיר behavior מיוחד שנקרא webHttp, כך:

 



<endpointBehaviors>


  <behavior>


    <webHttp />


  </behavior>


</endpointBehaviors>


 


יש לו מספר מאפיינים שנרצה להכיר חלק מהם.

 

automaticFormatSelectionEnabled:


שירות יכול להחזיר את התשובה באחד משני הפורמטים XML או JSON (אפשר גם פורמטים אחרים אבל זה דורש קצת יותר עבודה) המאפיין automatic מגדיר האם לנסות להחליט את הפורמט של התשובה (JSON או XML) בצורה אוטומטית לפי הסדר הבא:


הגדרה של media type ב – header של ה – request

הגדרה של ה – content-type של ה – request.

מה שהוגדר ב – OperationContract כברירת מחדל (נראה עוד מעט)

מה שהוגדר כברירת מחדל ב – webHttp behavior (נראה עוד מעט).

לעוד מידע בנושא WCF REST Formatting

 

helpEnabled:


מגדיר האם לחשוף החוצה דף עזרה שמספר על המתודות ובאיזה פרוטוקלים הם נחשפים.

הגישה לדף העזרה יהיה http://localhost/service.svc/help

 

לעוד מידע בנושא WCF REST Service Help Page.

 

faultExceptionEnabled:


במידה והערך אינו true כל שגיאה שתתרחש בשירות תחזיר קוד 500 (קוד שגיאה כללי) במידה והוא יסומן כ – true בזמן שגיאה נקבל הודעת fault (אנחנו נדבר על המושג fault באחד הפרקים הבאים).

 

המאפיין הזה מגיע בנוסף למאפיין includeExceptionDetailInFaults שמוגדר על serviceBehavior (כמו שראינו בפרק 4) שמגדיר האם להחזיר את פרטי השגיאה האמיתית, לעומתו המאפיין faultExceptionEnabled נותן את האפשרות כשכותבים web style services להחזיר שגיאה אמיתית ולא error code 500.

 

defaultOutgoingResponseFormat:


מגדיר מה ברירת המחדל של תשובות (יכול לקבל XML, JSON).

המאפיין הזה תלוי בערך ובהתנהגות של המאפיין automaticFormatSelectionEnabled.

 

defaultBodyStyle:


כשהמתודות שלנו מקבלות יותר מפרמטר אחד והגדרנו שהמתודה עובדת ב – WebInvoke וגם לא השתמשנו ב – UriTemplate (נראה עוד מעט מה זה אומר) ה – host יזרוק את השגיאה הבאה:

 

Operation 'Sub' of contract 'ICalc' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped

 



הסיבה לשגיאה היא פשוטה – כדי שהוא יצליח לעבור סרלזיצייה (כדי להעביר את הערכים) הוא אמור לכתוב קוד כזה:

 



<a>10</a>


<b>20</b>




שזה כמובן xml לא חוקי, לעומת זאת הקוד הבא:

<request>


  <a>10</a>


  <b>20</b>


</request>


 



שהוא xml חוקי מכיוון שיש root אחד.

כדי למנוע את השגיאה ניתן לקבוע את המאפיין defaultBodyStyle כ – Wrapped או כ – WrappedRequest (אפשר גם לקבוע את זה בעזרת  – attributes – נראה בהמשך)

 

 

להכיר את WebGetAttribute, WebInvokeAttribute וחלק מהמאפיינים שלהם.


ברירת המחדל של endpoint שנחשף עם webHttp Behavior מוגדר כ – POST, במידה ונרצה לחשוף ב – GET או להגדיר מספר הגדרות נוספות נצטרך להשתמש ב – attributes המתאימים.

 

כדי להגדיר שהמתודה תחשף החוצה ב – GET נצטרך לכתוב כך:

 



[WebGet]


[OperationContract]


int Add(int a, int b);


 


כעת ניתן יהיה לפנות לשירות בעזרת גלישה ישירה בדפדפן: http://localhost/service.svc/Add?a=1&b=9

 

במידה ונרצה פרוטוקול אחר (POST, PUT, DELETE) נכתוב:

 



[WebInvoke(Method = "POST")]


[OperationContract]


int Sub(int a, int b);


 


ה – attribues מקבלים מספר מאפיינים שכדאי להכיר:


bodyStyle:


זהה למאפיין defaultBodyStyle שהכרנו ב – webHttpBehavior.


RequestFormat ו – ResponseFormat


מגדירים את ברירת המחדל של הפורמטים (XML, JSON) והם תלויים בהגדרה של  automaticFormatSelectionEnabled


 

UriTemplate :


יש לו חשיבות רבה, הוא מאפשר לנו להחליט על הפורמט של ה – url, למשל נוכל לכתוב כזה דבר:

 



[WebGet(UriTemplate = "person/{id}")]


[OperationContract]


Person GetPerson(string id);


 



ואז ניתן יהיה לקבל את המידע בצורה הבאה: http://localhost/service.svc/person/2

 



חשוב לשים לב – שבמקרה שמשתמשים ב"שומרי מקום" ב – path, המשתנים יכולים להיות רק string, לעומת זאת אם ה"שומרי מקום" נמצאים ב – query string למשל:

 



[WebInvoke(Method = "POST", UriTemplate = "sub?a={a}&b={b}")]


[OperationContract]


int Sub(int a, int b);


 



סוג המשתנים יכול להיות כל דבר  (בדוגמא הזאת חסכנו את הצורך להשתמש ב – WrappedRequest).

 

שימוש ב – UriTemplate יכול לתת עוד הרבה ערך מוסף לשירות שלכם (לקריאה נוספת, כאן וכאן).

 

 

 

צריכה של שירות המוגדר כ – webHttp.


במידה והלקוח הוא לא WCF Client (למשל גלישה ישירה בדפדפן או שימוש ב – WebClient) הם יצרכו את השירות ככל שירות web רגיל,

במידה והלקוח הוא WFC (שימוש ב – Add Service Reference או ב – ChannelFactory, כמו שראינו בפרק 3) יש עוד כמה דברים קטנים שצריך לעשות.

האופצייה הפשוטה יותר היא שימוש ב – ChannelFactory, במקרה הזה כל מה שצריך לעשות זה להגדיר את הקונפיג עם ה – behavior כמו שצריך.

במידה ויש מתודה שצריכה הגדרה של Wrapped, אם ההגדרה הייתה על המתודה, למשל:

 



[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest)]


[OperationContract]


int Sub(int a, int b);


 


הלקוח לא צריך להגדיר שום דבר, לעומת זאת עם ההגדרה של ה – Wrapped היא בקונפיג בעזרת המאפיין defultBodyStyle, צריך את אותו הגדרה גם בצד הלקוח.

 

במידה והמאפיין automaticFormatSelectionEnabled הוגדר כ – true בצד השרת צריך גם להגדיר אותו כך בצד הלקוח ואז ניתן יהיה לכתוב קוד כזה:

 



try


{


    ChannelFactory<ICalc> channel = new ChannelFactory<ICalc>("calcEndpoint");


    ICalc proxy = channel.CreateChannel();


 


    int res = proxy.Sub(2, 4);


 


    channel.Close();


}


catch (FaultException ex)


{


 


}


catch (Exception ex)


{


 


}


 

 


לעומת זאת במידה והלקוח הוא בעזרת Add Service Reference, העניינים קצת יותר מסובכים. משום מה הוא לא מצליח לייצר את קובץ הקונפיג וצריך לכתוב אותו לבד (אמנם גם ב – ChnnelFactory אנחנו כותבים לבד,  אבל בשימוש עם ServiceReference אנחנו רגילים שהוא עושה את כל העבודה, בנוסף ויותר גרוע מכך הוא לא יודע להגדיר את המתודות שהוגדרו כ – WebGet כמו שצריך, ואנחנו צריכים להכנס לבד ל – מקום המתאים (תחת Service Refernece אחרי שלחצנו את ShowAllFiles נמצא את המחלקה שהוא יצר עבורנו) ולהוסיף על המתודה את ה – attribute של WebGet לבד.(כל פעם שנעשה Update Service Reference צריך לזכור להחזיר את ה – WebGetAttribute מכיון שמדובר בקוד שמחולל אוטומטית הוא ימחק את כל מה שאנחנו נעשה)

 

 

 

להכיר את WebServiceHost.


בפרק 6 דברנו על סוגי ה – host-ים השונים שקיימים, בנוסף על מה שהזכרתי שם יש גם host מיוחד שנקרא WebServiceHpst שבמידה ונשתמש בו במקום ServiceHpst הרגיל הוא מגדיר את כל ה – webHttp behavior בצורה אוטומטית.

 

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

3 תגובות

  1. יריב20 בינואר 2011 ב 9:51

    מה לגבי נושא של דחיפת הודעות למספר רב של קליינטים?
    אנו מעוניינים בפיתרון של מעין שרת הודעות עם X הודעות שהוא יכול לדחות למשתתפי קצה.
    עולה קליינט , נרשם , ומצהיר על Y הודעות שהוא מעוניין לקבל. ברגע שמגיעה ההודעה לשרת הוא דוחף אותה לקליינטים שנרשמו לקבל הודעה זאת.

    האם יש איזו שהיא שיטה לעשות זאת ב WCF , בצורה שהיא מעט יותר מתוחכמת מאשר מעבר בלולאה על כל הקליינטים ובדיקה אם הוא רשום או לא להודעה הזאת ואז לשלוח?

    תודה , ויופי של אתר.
    יריב

    הגב
  2. Shlomo20 בינואר 2011 ב 12:25

    יש – אבל תצטרך לחכות עד שאגיע לפרק המתאים (בגדול אתה מחפש משהו שנקרא DuplexChannel)

    הגב
  3. יוסי28 ביוני 2012 ב 7:58

    אני צריך להקים SERVER שהוא תומך בהודעות REST מאובטחות ב C#

    ז"א אני צריך שמשתמש יעשה login למערכת ורק אחר כך יהיה לו גישה לקבלת ולאחסון מידע באמצעות REST

    1. איך עושים זאת? אשמח מאוד לקבל דוגמת קוד כתובה

    2. האם ניתן לעשות זאת ללא שרת IIS? שוב אשמח לקבל דוגמת קוד

    הגב