استفاده از MVC Razor Views در پروژه های WebForms

چهارشنبه 29 شهریور 1396

در این مقاله نحوه ترکیب WebForms و MVC Razor Views را در یک برنامه تحت وب را به صورت کاملا گام به گام آموزش خواهیم داد. ترکیب این دو چارچوب با هم در عمل بسیار ساده تر از چیزی است که به نظر می آید.

استفاده از MVC Razor Views در پروژه های WebForms

مقدمه

خیلی مواقع از ما خواسته می شود که به توسعه برنامه های WebForms بپردازیم، در این جور مواقع اولین واکنش ما این است که برنامه موجود را براساس MVC دوباره پیاده سازی کنیم ولی این یک راه حل بسیار بد و نامناسب است. مهاجرت بین WebForms و MVC دارای هزینه خیلی زیادی است و همچنین بسیار زمان بر است و علاوه بر اینها، این کار بسیار پر ریسک است. WebForms در سال 2001 معرفی شده و امروزه به مرور کنار گذاشته شده است، البته به طور قطع این چارچوب تا مدت زیادی توسط مایکروسافت پشتیبانی خواهد شد. حالا در این شرایط با برنامه های WebForms باید چه کنیم؟ افزودن قابلیت های جدید با یک چارچوب در حال نابودی، به نظر کار اشتباهی می آید. در نتیجه بهترین روش برای این مشکل، ترکیب دو چارچوب WebForms و MVC است.

مشکل

از ویژوال استدیو 2013 به بعد، به راحتی می توان WebForms وMVC Razor Views  را در یک برنامه با یکدیگر ترکیب کرد و این برنامه باید دو موتور داشته باشد و routing باید به شکلی عمل نماید که موتور مورد استفاده درست انتخاب شود.

public class RazorDemoController : Controller
{
  public ActionResult Index()
  {
    return View();
  }
...

در اینجا مشکلات شروع می شود. razor view اطلاعاتی در مورد Master Page ندارد، چراکه Master Page مربوط به چارچوب WebForms است تا در WebForms بتوانیم یک layout برای تمامی صفحات بسازیم در حالی که در داخل MVC از Razor Layout Page برای این کار استفاده می شود. این دو روش با یکدیگر ترکیب نمی شوند و نتیجه نهایی یک صفحه مستقل خواهد بود.

راه حل

در این مرحله به ارائه راه حل به صورت گام به گام می پردازیم.

این مشکل توسط کلاس پایه ایی RazorController حل خواهد شد و باعث خواهد شد که کدها به شکل قابل قبولی ساده تر شوند و به جای پردازش View() به پردازش RazorView() می پردازیم.

public class RazorDemoController : RazorController
 {
   public ActionResult Index()
   {
     return RazorView();
   }

نحوه کار

نحوه کار به این شکل است که باید Razor view را در داخل Web Form پردازش کنیم (به شکل زیر).

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="RazorContent" ContentPlaceHolderID="MainContent" runat="server">
  <% Html.RenderPartial((String)ViewBag.ViewName); %>
</asp:Content>

فایل RazorView.aspx یک فایل Web Form به حساب می آید و حاوی یک content placeholder برای نمایش Razor view است. لطفا توجه کنید که ما بخش Inherits= را اصلاح کرده ایم و مقدار آن را از "System.Web.UI.Page"  به "System.Web.Mvc.ViewPage" تغییر داده ایم. این اصلاح که انجام دادیم باعث می شود که از موتور پردازش MVC در Html.RenderPartial به جای موتور پیشفرض WebForms استفاده شود. فایل RazorView.aspx در داخل بخش اشتراکی Views قرار دارد و این فایل برای تمامی Razor view ها در دسترس خواهد بود.

ارسال نام view

Html.RenderPartial برای پردازش به نام view نیاز دارد. فایل RazorView.aspx یک صفحه اشتراکی است که اطلاعی ندارد کدام view را باید پردازش کند به همین دلیل ما باید حتما نام view را به این فایل ارسال کنیم. فایل RazorView.aspx  از Mvc.ViewPage استفاده می کند و شامل خصوصیت ViewBag است. خصیصه ViewBag از داخل کنترلر قابل دسترسی است پس ما به کمک این خصیصه می توانیم نام view را به Html.RenderPartial که در داخل صفحه RazorView.aspx است، انتقال دهیم.

RazorController

RazorController تمامی کدهای مورد نیاز را کپسوله می نماید.

public class RazorController : Controller
 {
   public ActionResult RazorView(String viewName, Object model)
   {
     // pass the viewname to RazorView.aspx
     // the view will be rendered as partial view
     ViewBag.ViewName = viewName;

     return View("RazorView", model);
   }

   public ActionResult RazorView(Object model)
   {
     return RazorView(GetCurrentViewName(), model);
   }

   public ActionResult RazorView(String viewName)
   {
     return RazorView(viewName, null);
   }

   public ActionResult RazorView()
   {
     return RazorView(GetCurrentViewName(), null);
   }

   private String GetCurrentViewName()
   {
     var result = $"{Url.RequestContext.RouteData.Values["action"]}";

     return result;
   }
 }

متد RazorView()  دارای چند overloads است. اگر نام viwe حذف شود، به کمک تابع GetCurrentViewName()  می توان نام اکشن فعلی را به جای نام view ارسال کرد.

کنترلر RazorDemoController از کنترلر RazorController وراثت شده است و همانگونه که مشاهده می کنید، متدهای RazorView به راحتی قابل استفاده اند.

public class RazorDemoController : RazorController
  {
    public ActionResult Index()
    {
      return RazorView();
    }


    // Example render some other view
    public ActionResult RenderOtherView()
    {
      return RazorView("Hello");
    }

    // Example Render view with Model
    public ActionResult Customer(Int32 id)
    {
      var model = new Customer()
      {
        Id = id,
        Name = "Company ABC",
        City = "The One that never sleeps"
      };

      return RazorView(model);
    }

    [HttpGet]
    public ActionResult SomeAjaxCall(Int32 id)
    {
      var model = new Customer()
      {
        Id = id,
        Name = "Company ABC",
        City = "The One that never sleeps"
      };

      return View("Customer", model);
    }
  }

فراخوانی وابستگی های مرتبط با RazorView

<div>
  <h3>I am really a MVC Razor view in a WebForms world</h3>
</div>

<div>
  <h3>Hi there...</h3>
</div>

@model Models.Customer

<div>
  <h3>Customer</h3>
  <p>Id : <strong>@Model.Id</strong>
  <p>Name : <strong>@Model.Name</strong>
  <p>City : <strong>@Model.City</strong>

</div>

صفحه Customer.cshtml به شکل زیر نمایش داده می شود.

تنظیمات پروژه ویژوال استدیو

برنامه های قدیمی WebForms را نمی توان طوری پیکربندی کرد که از WebForms و MVC به طور همزمان استفاده کند. حتی انتقال برنامه به آخرین نسخه ویژوال استدیو هم باعث برطرف شدن این مشکل نشد. شما می توانید مرجع های MVC را به پروژه اضافه کنید یا که تمامی form های موجود در برنامه تان را به یک پروژه جدید منتقل کنید. اینکه کدام روش برای کار شما بهتر است را خودتان باید تشخیص دهید. اگر یک پروژه جدید WebForms ساختید، به یاد داشته باشید که حتما گزینه MVC reference را بزنید تا مرجع های MVC به پروژه تان اضافه شود.

مرحله 1

راه اندازی یک پروژه ترکیبیWebForms  و MVC

پروژه Web Forms را انتخاب کنید و مرجع های MVC را به آن اضافه کنید.

مرحله 2

یک پروژه جدید که شامل تمامی مرجع های مورد نیاز، ساخته می شود که توانایی پردازش هر دو موتور پردازشی WebForms و MVC  را دارد.

جی کوئری و Ajax

گزینه دیگر ما، استفاده از جی کوئری به همراه Ajax است. این طرح  بسیار ساده است و نحوه کار به شکلی است که در داخل صفحه Web Form یک عنصر Div می سازیم و به کمک Ajax، کنترلر های MVC را فراخوانی می کنیم تا محتویات این صفحه دریافت شود. کدهای این روش در پایین قرار داده شده است. صفحه AjaxDemo.aspx که از نوع Web Form است، به کمک دستورات Ajax، اکشن متد SomeAjaxCall را فراخوانی می کند و محتویات دریافتی را در داخل عنصر Div با شناسه razorViewContent که در صفحه ساخته بودیم، نمایش می دهد.

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="AjaxDemo.aspx.cs" 

Inherits="WebForm.WebForms.AjaxDemo" %>

<asp:Content ID="content" ContentPlaceHolderID="MainContent" runat="server">
  <h3>Ajax demo</h3>

  <%--Setup place holder for Razor MVC view content--%>
  <div id="razorViewContent">
  </div>

  <script type="text/javascript">
    $(function () {

      // Call MCV view on document completed
      $.ajax({
        type: "Get",
        url: "/RazorDemo/SomeAjaxCall",        
        data: 'id=55',              
        success: function (document) {
          $('#razorViewContent').html(document);
        }
      }); 
    });
</script>

</asp:Content>

پیاده سازی کنترلر

[HttpGet]
   public ActionResult SomeAjaxCall(Int32 id)
   {
     var model = new Customer()
     {
       Id = id,
       Name = "Company ABC",
       City = "The One that never sleeps"
     };

     return View("Customer", model);
   }

روش استفاده از Ajax دارای یک مشکل است و مشکل این است که در این روش ما یک فایل بیشتر باید از سرور دریافت کنیم تا نتیجه کاملا مشابه روش قبل را به کاربر نمایش دهیم. البته استفاده از این روش در خیلی مواقع باعث راحتی کار می شود.

شرایط Asp.Net Core

اگر می خواهید که MVC و WebForms را بر روی بستر Asp.Net Core پیاده سازی کنید، باید بدانید که امکان این کار وجود ندارد چرا از WebForms در داخل Asp.Net Core پشتیبانی نمی شود، پس ترکیب این دو چارچوب ممکن نیست.

نتیجه گیری

WebForms و MVC Razor views به صورت کاملا بی نقصی با یکدیگر ترکیب می شوند و شرایط توسعه برنامه های WebForms را به کمک تکنیک های جدید MVC فراهم می کنند. ترکیب این دو چارچوب با یکدیگر را می توان از طریق دو روش انجام روش اول پردازش یک Razor view در داخل صفحه WebForms است و روش دوم استفاده از جی کوئری و Ajax برای نمایش MVC در داخل یک عنصر Div است. هر دوی این روش ها از layout اصلی سایت استفاده می کنند.

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید