ایجاد سرویس چندلایه‎ی WCF با Entity Framework در قالب پروژه - 9
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: سه دقیقه

یک Windows Form جدید ایجاد کنید و نام آن را frmAddEditNews بگذارید. 
برابر با شکل ویژگی‌های IsDeleted، tblCategory و tblNewsId را برابر با None کنید و tblCategoryId را از نوع Combobox انتخاب کنید. سپس با فشار فلش کنار tblNews گزینه‌ی Details را انتخاب کنید.

روی tblNews کلیک کرده آن‌را بکشید و روی فرم رها کنید. آن‌گاه ظاهر فرم و چیدمان کنترل‌ها را تنظیم کنید و دو دکمه ذخیره و لغو برابر با شکل در فرم ایجاد کنید:

کد روی‌داد دو دکمه را این‌گونه بنویسید:

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
        }

در پایین فرم روی tblNewsBindingSource کلیک کنید و از قسمت Properties ویژگی Modifiers آن‌را برابر با Public کنید. 

روی Combobox کلیک کنید، سپس ویژگی DataBinding -> Text آن‌را خالی کنید. سپس روی فلش بالای Combobox دسته خبر کلیک کنید و تنظیمات آن‌را مانند شکل زیر انجام دهید.

برای پرشدن آن کد زیر را در روی‌داد Load فرم این‌گونه بنویسید:

        private void frmAddEditNews_Load(object sender, EventArgs e)
        {
            MyNewsService.MyNewsServiceClient MyNews = new MyNewsService.MyNewsServiceClient();
            tblCategoryIdComboBox.DataSource = MyNews.GetAllCategory();
        }

به فرم اصلی بازگردید و برای روی‌داد دکمه‌ی ویرایش چنین بنویسید:

        private void btnEdit_Click(object sender, EventArgs e)
        {
            if (tblNewsDataGridView.CurrentRow == null)
            {
                MessageBox.Show("سطری برای ویرایش انتخاب کنید");
            }
            else
            {
                //tblNews news = tblNewsDataGridView.CurrentRow.DataBoundItem as tblNews;
                tblNews news  = MyNews.GetNews(Convert.ToInt32(tblNewsDataGridView.CurrentRow.Cells["tblNewsId"].Value));
                frmAddEditNews frmAdd = new frmAddEditNews();
                frmAdd.tblNewsBindingSource.DataSource = news;
                if (frmAdd.ShowDialog() == DialogResult.OK)
                {
                    MyNews.EditNews(news);
                    tblNewsBindingSource.DataSource = MyNews.GetAllNews().Select(p => new { p.tblNewsId, p.tblCategory.CatName, p.Title, p.Description, RegDate = MiladiToShamsi(p.RegDate) });
                }
            }
        }

در صورتی که متد GetAllNews را به صورت ساده به ویژگی DataSource دیتاگرید نسبت داده بودیم می‌توانستید از کد زیر برای مقداردهی به متغیر news بهره ببریم. ولی در حال حاضر این خط کد پیغام خطا می‌دهد. البته راه‌های دیگری برای حل این مشکل وجود دارد که در این درس قصد پرداختن به آن‌را ندارم.

tblNews news = tblNewsDataGridView.CurrentRow.DataBoundItem as tblNews;

کد مربوط به روی‌داد دکمه‌ی افزودن و حذف را نیز به صورت زیر بنویسید:

        private void btnAdd_Click(object sender, EventArgs e)
        {
            tblNews news = new tblNews();
            frmAddEditNews frmAdd = new frmAddEditNews();
            frmAdd.tblNewsBindingSource.DataSource = news;
            if (frmAdd.ShowDialog() == DialogResult.OK)
            {
                MyNews.AddNews(news);
                tblNewsBindingSource.DataSource = MyNews.GetAllNews().Select(p => new { p.tblNewsId, p.tblCategory.CatName, p.Title, p.Description, RegDate = MiladiToShamsi(p.RegDate) });
            }
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("آیا با حذف این سطر اطمینان دارید؟","هشدار",MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {
                MyNews.DeleteNews(Convert.ToInt32(tblNewsDataGridView.CurrentRow.Cells["tblNewsId"].Value));
                tblNewsBindingSource.DataSource = MyNews.GetAllNews().Select(p => new { p.tblNewsId, p.tblCategory.CatName, p.Title, p.Description, RegDate = MiladiToShamsi(p.RegDate) });
            }
        }

برنامه را اجرا کنید. کار ما کم و بیش به پایان رسیده است. شما یک پروژه‌ی ویندوز ساده با استفاده از WCF ای که از Entity Framework برای اتصال به پایگاه داده بهره می‌برد؛ ایجاد کردید. WCF بسیار گسترده‌تر از این است و در این‌جا تنها به بخشی از آن پرداختیم. احتمالاً در صورت استقبال خوانندگان در آینده درباره‌ی تنظیمات ریز WCF برای امنیت، سرعت، محدودیت و استفاده در محیط‌های مختلف خواهم نوشت.

شاد و پیروز باشید.

  • #
    ‫۱۰ سال و ۸ ماه قبل، پنجشنبه ۳ بهمن ۱۳۹۲، ساعت ۱۰:۱۲
    بسیار عالی بود
  • #
    ‫۱۰ سال و ۸ ماه قبل، پنجشنبه ۳ بهمن ۱۳۹۲، ساعت ۲۲:۲۱
    مرسی ، خیلی عالی بود. اگه میشه در مورد security in WCF مقاله بگذارید ممنون میشم. باز هم ممنون
  • #
    ‫۱۰ سال و ۸ ماه قبل، یکشنبه ۶ بهمن ۱۳۹۲، ساعت ۰۴:۱۱
    سلام مطالب فوق العاده کاربردی هستند مشتاقانه منتظر ادامه این بحث هستیم
    سوال:
    در صورتی که بخوام از سرویس WCF روی یک سرور جدا استفاده کنم چطور با WinApp خودم به سرویس‌های WCF Server وصل شم؟ بدون واسطه Web App ?
    و اینکه سرعت واکشی اطلاعات ( رکوردهای زیاد 2 ، 3 هرارتا یا بیشتر ) چگونه هست؟ با WCF و WinApp واسه نرم افزار‌های سازمانی که تحت شبکه محلی و وایرلس داخل شهری هستن بخوام ازین روش استفاده شه آیا در بلند مدت با افزایش رکوردها به مشکل برخورد نمی‌کنم از نظر کار با دیتابیس و داده ها؟
    • #
      ‫۱۰ سال و ۸ ماه قبل، یکشنبه ۶ بهمن ۱۳۹۲، ساعت ۱۰:۲۹
      با درود و سپاس از همه‌ى همراهان.
      همان‌سان که پیش‌تر هم نوشته ام مى‌توانید سرویس WCF را در IIS یک سرور دیگر راه‌اندازى کنید و آدرس آی‌پی و یا DNS مربوط به آن‌را در WinApp خود استفاده کنید.
      هنوز به تنظیمات خاص Web.Config نرسیده ایم در آن‌جا به امنیت و محدودیت‌ها خواهم پرداخت.
      پیروز باشید.
  • #
    ‫۱۰ سال و ۸ ماه قبل، یکشنبه ۶ بهمن ۱۳۹۲، ساعت ۰۴:۴۸
    تستی که من با تعداد رکوردها برای واکشی از دیتابیس انجام دادم به یه مشکل برخورد کردم:
    زمانی که تعداد رکوردها زیر 100 تا باشه خب win app به راحتی اطلاعات رو بارگزاری می‌کنه
    ولی وقتی بیش از این مقدار مثلا 288 رکورد در زمان اجرای پروژه به مشکل برخورد می‌کنم که فرم بارگزاری نمیشه و از حالت Start می‌پره بیرون
    دلیلش چی می‌تونه باشه؟ محدودیت‌های وب سرویس؟ چطور و چگونه این مشکل رو برطرف کنیم؟
    پیام Catch :
    The maximum message size quota for incoming messages (65536) has been exceeded.
     To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.
    از پیام معلومه که از حداکثر مقدار دریافتی یک واکشی بیش از حد درخواست کردیم ...
    یک راه حل جامع چی می‌تونه باشه؟
    • #
      ‫۱۰ سال و ۸ ماه قبل، یکشنبه ۶ بهمن ۱۳۹۲، ساعت ۰۵:۱۳
      راه حلی که بنده پیدا کردم؛ تغییراتی در مقدار سایز پیام دریافتی به شکل زیر در appConfig مربوط به پروژه WinApp از این شکل :
      <?xml version="1.0" encoding="utf-8" ?>
      <configuration>
          <system.serviceModel>
              <bindings>
                  <basicHttpBinding>
                      <binding name="BasicHttpBinding_IMyNewsService" />
                  </basicHttpBinding>
              </bindings>
              <client>
                  <endpoint address="http://localhost:4636/SedaService.svc" binding="basicHttpBinding"
                      bindingConfiguration="BasicHttpBinding_IMyNewsService" contract="MyNewsService.IMyNewsService"
                      name="BasicHttpBinding_IMyNewsService" />
              </client>
          </system.serviceModel>
      </configuration>
      به این شکل تغییر دهید :
      <bindings>
                  <basicHttpBinding>
                      <binding maxReceivedMessageSize="2147483647" name="BasicHttpBinding_IMyNewsService" />
                  </basicHttpBinding>
              </bindings>
      حالا امنیت رو نمیدونم اینجا نقض کردم یا نه؟ لطفا اگر اطلاعاتی دارید راهنمایی بفرمایید که امنیت نقض شده یا نه؟ و کلا با یه عدد این شکلی که Max رو مشخص می‌کنه بنظرم نسبت به آینده نگری یک نرم افزار تجاری منطقی نیست...
  • #
    ‫۱۰ سال و ۷ ماه قبل، شنبه ۲۴ اسفند ۱۳۹۲، ساعت ۱۴:۳۱
    سلام
    با تشکر از این آموزش. فقط یه خواهش دارم . اگر براتون مقدوره در مورد امنیت برای تبادل داده‌ها در wcf این مبحث رو ادامه بدید.

    ممنون
  • #
    ‫۱۰ سال و ۶ ماه قبل، یکشنبه ۱۷ فروردین ۱۳۹۳، ساعت ۱۹:۴۴
    با عرض سلام؛  آیا برای استفاده از یک وب سرویس هم باید مبحث "Dependency Injection" در نظر گرفته بشه؟ اگر پاسخ مثبت است لطفا با مثالی ساده توضیح دهید روش کار به چه صورت است؟ ممنون
    • #
      ‫۱۰ سال و ۶ ماه قبل، یکشنبه ۱۷ فروردین ۱۳۹۳، ساعت ۲۱:۲۴
      - برای تولید سرویس: «پیاده سازی InstanceProvider برای سرویس‌های WCF»
      - برای استفاده از سرویس: در همان لایه سرویس برنامه از آن استفاده کنید. مباحث و مفاهیم تزریق وابستگی‌های آن تفاوتی با حالت استفاده از یک دیتابیس یا یک WebClient ندارد و یکی است.
      • #
        ‫۱۰ سال و ۵ ماه قبل، سه‌شنبه ۲۶ فروردین ۱۳۹۳، ساعت ۱۹:۰۴
        مشکلی که در استفاده از وب سرویس دارم اینه که وب سرویس در ازای بعضی از درخواست‌ها خطایی از نوع System.ServiceModel.FaultException بر میگردونه. این خطا رو میتوان در Controller با HandleError به View ی خاصی هدایت کرد. اما من قصد دارم پیام بازگردانده شده از نوع FaultException  رو به کاربر نمایش بدم. برای این کار چه باید کرد؟ ممنون
        • #
          ‫۱۰ سال و ۵ ماه قبل، سه‌شنبه ۲۶ فروردین ۱۳۹۳، ساعت ۱۹:۱۲
          - به دلایل امنیتی نباید جزئیات خطاها را به کاربران نمایش داد. صرفا به نمایش صفحات و پیام‌های عمومی بسنده کنید.
          + در مورد MVC و مدیریت خطاها در آن بحث مجزایی در سایت وجود دارد (^)؛ قسمت «دسترسی به اطلاعات استثناء در صفحه نمایش خطاها»
  • #
    ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۱۵ تیر ۱۳۹۳، ساعت ۱۳:۳۱
    سلام ممنون از مطالب خوب و ارزشمندی که گذاشتید
    فقط یه سوال دارم که هر چی گشتم نتونستم حل کنم
    اونم نحوه پابلیش و خروجی گرفتن از برنامه برای IIS هست
    ممنون میشم راهنمایی کنید که پروژه ای رو که ساختید چطوری میشه پابلیش کرد
    بازهم ممنون
    • #
      ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۱۵ تیر ۱۳۹۳، ساعت ۱۳:۳۸
      - در قسمت هفتم، تنظیمات برنامه‌های وب آن بحث شده. پابلیش آن کپی و پیست پروژه در یک دایرکتوری مجازی در IIS است (یعنی فرقی با راه اندازی یک وب سایت معمولی ASP.NET نداره در اساس).
      - اگر به خطایی برخوردید در این بین، عین خطا را ارسال کنید تا بیشتر بشود بحث کرد.
      • #
        ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۱۵ تیر ۱۳۹۳، ساعت ۱۶:۵۲
        سلام
        فکر می‌کنم ایراد از تنظیمات IIS ویندوز باشه و ربطی به برنامه نویسی نداره
        اول که IIS تنظیم می‌کردم این Error میداد

         HTTP Error 404.3 - Not Found The page you are requesting cannot be served because of the
        extension configuration. If the page is a script, add a handler. If the file should be downloaded, 
        add a MIME map
         که کارهایی که در وبلاگ زیر گفته شده انجام دادم
        http://blogs.msdn.com/b/ericwhite/archive/2010/05/11/getting-started-building-a-wcf-web-service.aspx
        الان پیغام زیر رو میده
         Server Error in '/MyNewService' Application.
        Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
        ممنون میشم اگه بتونی مشکل منو حل کنی
        با تشکر
        • #
          ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۱۵ تیر ۱۳۹۳، ساعت ۱۷:۱۱

          خطای آخری رو که ارسال کردید اینجا توضیح داده شده: http://support.microsoft.com/kb/2015129

          خلاصه‌اش اینکه باید دستور aspnet_regiis.exe /iru رو در خط فرمان اجرا کنید. محل قرارگیری برنامه aspnet_regiis.exe در پوشه ویندوز هست (فایل‌ها رو جستجو کنید تا یافت بشه).

          • #
            ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۱۵ تیر ۱۳۹۳، ساعت ۱۷:۵۲
            ممنون دوست عزیز
            درضمن باید تنظیمات زیر روا هم اعمال کنید
            Everywhere the problem to this solution was mentioned as re-registering aspNet by using aspnet_regiis.exe. But this did not work for me.
            Though this is a valid solution (as explained beautifully here)
            but it did not work with Windows 8.
            For Windows 8 you need to Windows features and enable everything under ".Net Framework 3.5" and ".Net Framework 4.5 Advanced Services".