در WCF سه نوع Message Encoder وجود دارد:
- Text(Xml) Message Encoder(به صورت پیش فرض در تمام Http-Base Bindingها از این Encoder استفاده میشود)
- Binary Message Encoder(به صورت پیش فرض در تمام Net* Bindingها از این encoder استفاده میشود که برای سرویسهای وب مناسب نیست)
- MTOM Message Encoder (در حالت استفاده از Http-Base Bindingها و انتقال اطلاعات به صورت باینری از این گزینه استفاده میشود که به صورت پیش فرض غیر فعال است)
وضعیتی را در نظر بگیرید که در یک پروژه مبتنی بر WCF قصد دارید حجمی زیاد
از داده به فرمت باینری (نظیر فایل ها) را بین سرور و کلاینت رد و بدل
کنید. به صورت معمول بسیاری از برنامه نویسان، یک کلاس به همراه
DataContractAttribute ایجاد میکنند که در آن خاصیتی به صورت آرایه ای از
نوع بایت که DataMemberAttribute را نیز دارد برای انتقال محتویات فایل
استفاده میشود. اما باید یک نکته را مد نظر داشت و آن این است که به صورت
پیش فرض فرمت انتقال دادهها در WCF به صورت Text/Xml است و برای انتقال
دادهها نیز از فرمت Base 64
استفاده خواهد شد. مشکل اصلی این جاست که در حالت Text/Xml Encoding برای
انتقال دادههای باینری، برای هر سه بایت، چهار کاراکتر استفاده میشود در
نتیجه، این باعث افزایش حجم داده تا 33 درصد خواهد شد که کارایی سیستم را
تحت تاثیر قرار میدهد.
اما خبر خوب این است که استانداردی وجود دارد به نام MTOM یا همان Message Transmission Optimization Mechanism،
برای این که بتوان محتوای باینری را بدون افزایش حجم داده انتقال داد.
برای پیاده سازی این روش باید موارد زیر را در نظر داشته باشید:
ابتدا کلاس مورد نظر را به صورت زیر تهیه میکنیم:
چند تذکر
اما یک نکته...
هدف از استفاده از MTOM برای افزایش کارایی انتقال دادههای باینری در حجم زیاد است. در زیر نتایج مقایسه بررسی انتقال اطلاعات به دو صورت MTOM و Text برای حجم دادههای متفاوت را مشاهده میکنید:
با دقت در نتایج بالا مشخص میشود که این روش در حجم دادههای پایین (مثل 100 بایت یا 1000 بایت) عملکرد مورد انتظار را نخواهد داشت. پس این نکته را نیز در هنگام پیاده سازی به این روش مد نظر داشته باشید.
»متد یا همان OperationContract که وظیفه آن ارسال یا دریافت دادهها با
فرمت MTOM است فقط کلاس هایی را انتقال دهد که دارای
MessageContractAttribute هستند. نباید از DataContractAttribute استفاده
نمایید.
»خاصیتی که نوع آن آرایه ای از بایتها است نباید دارای DataMemberAttribute باشد؛ بلکه به جای آن باید از MessageBodyMember استفاده نمایید.
»به جای []Byte میتوان از نوع Stream نیز استفاده کرد(الزامی نیست).
»مقدار خاصیت MessageEncoding در Binding استفاده شده باید MTOM تعیین شود.
پیاده سازی یک مثال »خاصیتی که نوع آن آرایه ای از بایتها است نباید دارای DataMemberAttribute باشد؛ بلکه به جای آن باید از MessageBodyMember استفاده نمایید.
»به جای []Byte میتوان از نوع Stream نیز استفاده کرد(الزامی نیست).
»مقدار خاصیت MessageEncoding در Binding استفاده شده باید MTOM تعیین شود.
ابتدا کلاس مورد نظر را به صورت زیر تهیه میکنیم:
[MessageContract] public class MyFile { [MessageHeader] public String Filename { get; set; } [MessageBodyMember] public Byte[] Contents { get; set; } }
- به جای DataContract از MessageContract استفاده میشود؛
- تمام خاصیت هایی که نوع آنها غیر از []Byte است باید دارای MessageHeader باشند؛
- خاصیتی که برای انتقال محتوای باینری تهیه شده است، باید از MessageBodyMember استفاده نماید؛
- مجاز به تعریف فیلد یا فیلد هایی که نوع آنها Primitive Type است نمیباشید.
تنظیمات مربوط به Binding نیز به صورت خواهد بود:
<bindings> <wsHttpBinding> <binding name="WsHttpMtomBinding" messageEncoding="Mtom" /> </wsHttpBinding> </bindings>
هدف از استفاده از MTOM برای افزایش کارایی انتقال دادههای باینری در حجم زیاد است. در زیر نتایج مقایسه بررسی انتقال اطلاعات به دو صورت MTOM و Text برای حجم دادههای متفاوت را مشاهده میکنید:
با دقت در نتایج بالا مشخص میشود که این روش در حجم دادههای پایین (مثل 100 بایت یا 1000 بایت) عملکرد مورد انتظار را نخواهد داشت. پس این نکته را نیز در هنگام پیاده سازی به این روش مد نظر داشته باشید.