درسته . اما در این حالت دیگر کلاینت شما مستقیما به کار ساخت Object را انجام نمیدهد و کار را به کلاس دیگری واگذار کرده.
دوست عزیز
بحث ما در مورد توانایی انجام موارد فوق الذکر بود. نه اینکه حالا چون ...
به تواناییهای MVC شکی نیست.مسئله اصلی اینه که آیا پست جاری را میتوان به راحتی با WebPage و یا WebForm انجام داد؟!
چه از طریق قابلیتهای ASP.NET Web Form و ASP.NET Web Page راحته.
استفاده از Razor چه از طریق Jquery و یا Iframe (نظر قبلی)و یا به طور مستقل و یا روشهای دیگر در ASP.NET Web Form و ASP.NET Web Page
و استفاده معمولی با تواناییهای DataBind
یا بطور کامل از Razor View Engine در Web Page
در نهایت کار سختی نیست.
بحث ما در مورد توانایی انجام موارد فوق الذکر بود. نه اینکه حالا چون ...
به تواناییهای MVC شکی نیست.مسئله اصلی اینه که آیا پست جاری را میتوان به راحتی با WebPage و یا WebForm انجام داد؟!
چه از طریق قابلیتهای ASP.NET Web Form و ASP.NET Web Page راحته.
استفاده از Razor چه از طریق Jquery و یا Iframe (نظر قبلی)و یا به طور مستقل و یا روشهای دیگر در ASP.NET Web Form و ASP.NET Web Page
و استفاده معمولی با تواناییهای DataBind
یا بطور کامل از Razor View Engine در Web Page
در نهایت کار سختی نیست.
برای برقراری امنیت، تعیین هویت و اعتبارسنجی در وب API عموما یا از Forms authentication استفاده میشود و یا از ASP.NET Identity . زیر ساخت آن یکی است و مشترک.
نظرات مطالب
Blogger auto poster
ساخت این فایل خودکار هست و در اولین بار دریافت اطلاعات از وب ساخته میشود و اگر ایجاد نشده یعنی برنامه دسترسی نوشتن و رایت در پوشه نصب شده را ندارد. در کل یک نمونه از این فایل رو میتونید اینجا پیدا کنید: (^)
مطالب
AngularJS #1
پیش از اینکه آموزش AngularJs را شروع کنیم بهتر است با مفهوم برنامههای تک صفحه ای وب و یا Single Page Web Applications آشنا شویم؛ چرا که AngularJS برای توسعه هر چه سادهتر و قویتر این گونه برنامهها متولد شده است.
Single Page Application
برای درک چگونگی کارکرد این برنامه ها، مثالی را میزنیم که هر روزه با آن سرو کار دارید، یکی از نمونههای کامل و قدرتمند برنامههای Single Page Application و یا به اختصار SPA، سرویس پست الکترونیکی Google و یا همان Gmail است.
اجازه بدهید تا ویژگیهای SPA را با بررسی Gmail انجام دهم، تا به درک روشنی از آن برسید:
Reload نشدن صفحات
در Gmail هیچ گاه صفحه Reload و یا اصطلاحا بارگیری مجدد نمیشود. برای مثال، وقتی شما لیست ایمیلهای خود را مشاهده میکنید و سپس بر روی یکی از آنها کلیک میکنید، بدون اینکه به صفحه ای دیگر هدایت شوید؛ایمیل مورد نظر را میبینید. در حقیقت تمامی اطلاعات در همان صفحه نمایش داده میشوند و بر عکس وب سایتهای معمول است که از صفحه ای به صفحهی دیگر هدایت میشوید ، در یک صفحه تمام کارهای مورد نیاز خود را انجام میدهید و احتیاجی به بارگیری مجدد صفحات نیست. با توجه به این صحبتها برای توسعه دهندههای وب آشکار است که تکنیک AJAX، نقشی اساسی در این گونه برنامهها دارد، چون کلیهی عملیات ارتباط با سرور در پشت زمینه انجام میشوند.
تغییر URL در نوار آدرس مرورگر
وقتی شما بر روی یک ایمیل کلیک میکنید و آن ایمیل را بدون Reload شدن مجدد صفحه مشاهده میکنید، آدرس صفحه در مرورگر نیز تغییر میکند. خب مزیت این ویژگی چیست؟ مزیت این ویژگی در این است که هر ایمیل شما دارای یک آدرس منحصر به فرد است و به شما امکان Bookmark کردن آن لینک، باز کردن آن در یک Tab جدید و یا حتی ارسال آن به دوستان خود را دارید. حتی اگر این مطلب را جدا از Gmail در نظر بگیریم، به موتورهای جست و جو کمک میکند، تا هر صفحه را جداگانه Index کنند؛ جدا از اینکه وبسایت ما SPA است. همچنین این کار یک مزیت مهم دیگر نیز دارد؛ و آن کار کردن کلیدهای back و forward مرورگر، برای بازگشت به صفحات پیمایش شده قبلی است.
شاید قبل از بیان این ویژگی با خود گفته باشید که پیاده سازی Reload نشدن صفحات با AJAX آن چنان کار پیچیده ای نیست. بله درست است، اما آیا شما قبل از این راه حلی برای تغییر URL اندیشیده بودید؟ مطمئنا شما هم صفحات وب زیادی را دیده اید که همهی صفحات آن دارای یک URL در نوار آدرس مرورگر هستند و هیچگاه تغییر نمیکنند و با باز کردن یک لینک در یک Tab جدید، باز همان صفحهی تکراری را مشاهده میکنند! و یا بدتر از همه که دکمهی back مرورگر غیر عادی عمل میکند. بله، اینها تنها تعدادی از صدها مشکلات رایج سیستمهای نوشته شده ای است که سعی کردند همهی کارها در یک صفحه انجام شود.
Cache شدن اطلاعات دریافتی
شاید خیلیها ویژگیهای فوق را برای یک SPA کافی بدانند، اما تعدادی هم مانند نگارنده وجود یک کمبود را حس میکنند و آن کش شدن اطلاعات دریافتی در مرورگر است. Gmail این امکان را به خوبی پیاده سازی کرده است. لیست ایمیلهای دریافتی در بار اول از سرور دریافت میشود، سپس شما بر روی یک ایمیل کلیک و آن را مشاهده میکنید. حال به لیست ایمیلهای دریافتی بازگردید، آیا رفت و برگشتی به سرور انجام میشود؟ مسلما خیر. حتی اگر دوباره بر روی آن ایمیل مشاهده شده ، کلیک کنید، بدون رفت و برگشتی به سرور آن ایمیل را مشاهده میکنید.
کش شدن اطلاعات سبب میشود که بار سرور خیلی کاهش یابد و رفت و آمدهای بیهوده صورت نگیرد. کش شدن دادهها یک مزیت دیگر نیز دارد و آن تبدیل برنامههای معمول وب stateless به برنامههای شبه دسکتاپ state full است.
تکنیک AJAX در پیاده سازی امکانات فوق نقشی اساسی را بازی میکند. کمی به عقب برمیگردیم یعنی زمانی که AJAX برای اولین بار مطرح شد و هدف اصلی به وجود آمدن آن پیاده سازی برنامههای وب به شکل دسکتاپ بود و این کار از طریق انجام تمامی ارتباطات سرور با XMLHttpRequest امکان پذیر میشد. شاید آن زمان با توجه به محدودیت تکنولوژیها موجود این کار به صورت تمام و کمال امکان پذیر نبود، اما امروزه به بهترین شکل ممکن قابل پیاده سازی است.
شاید اکنون این سوال پیش بیاید که چرا باید وبسایت خود را به شکل SPA طراحی کنیم؟
برای پاسخ دادن به این سوال باید گفت که سیستمهای وب امروزی به دو دستهی زیر تقسیم میشوند:
- Web Documents و یا همان وب سایتهای معمول
- Web Applications و یا همان Single Page Web Applications
اگر هدف شما طراحی یک وب سایت معمول است که هدف آن، نمایش یک سری اطلاعات است و به قولی دارای محتواست، مطمئنا پیاده سازی این سیستم به صورت SPA کاری بیهوده به نظر میآید؛ ولی اگر هدفتان نوشتن سیستم هایی مثل Gmail، Google Maps، Azure، Facebook و ... است، پیاده سازی آنها به صورت وب سایتهای معمولی، غیر معقول به نظر میآید. حتی بخشهای مدیریتی یک وبسایت هم میتواند به خوبی توسط SPA پیاده سازی شود، چرا که واقعا برای مدیریت اطلاعات یک وب سایت احتیاجی نیست، که از این صفحه به آن صفحه جا به جا شد.
معرفی کتابخانهی AngularJS
AngularJS فریم ورکی متن باز و نوشته شده به زبان جاوا اسکریپت است. هدف از به وجود آمدن این فریم ورک، توسعه هر چه سادهتر SPAها با الگوی طراحی MVC و تست پذیری هر چه آسانتر آنها است. این فریم ورک توسط یکی از محققان Google در سال 2009 به وجود آمد. بعدها این فریم ورک تحت مجوز MIT به صورت متن باز در آمد و اکنون گوگل آن را حمایت میکند و توسط هزاران توسعه دهنده در سرتاسر دنیا، توسعه داده میشود.
قبل از اینکه به بررسی ویژگیهای Angular بپردازم، بهتر است ابتدا مطلبی دربارهی به کارگیری Angular از Brad Green که کارمند گوگل است، بیان کنم.
در سال 2009 تیمی در گوگل مشغول انجام پروژه ای به نام Google Feedback بودند. آنها سعی داشتند تا در طی چند ماه، به سرعت کدهای خوب و تست پذیر بنویسند. پس از 6 ماه کدنویسی، نتیجهی کار 17000 خط کد شد. در آن موقع یکی از اعضای تیم به نام Misko Hevery، ادعا کرد که میتواند کل این پروژه را در دو هفته به کمک کتابخانهی متن بازی که در اوقات فراغت توسعه داده است، بازنویسی کند. Misko نتوانست در دو هفته این کار را انجام دهد. اما پس از سه هفته همهی اعضای تیم را شگفت زده کرد. نتیجهی کار تنها 1500 خط بود! همین باعث شد که ما بفهمیم که، Misko بر روی چیزی کاری میکند که ارزش دنبال کردن دارد.
پس از آن قضیه Misko و Brad بر روی Angular کار کردند و اکنون هم Angular توسط تیمی در گوگل و هزاران توسعه دهندهی متن باز حرفه ای در سرتاسر جهان، درحال توسعه است.
فکر کنم همین داستان ذکر شده، قدرت فوق العاده زیاد این فریم ورک را برای همگان آشکار سازد.
ویژگیهای AngularJS:
- قالبهای سمت کاربر (Client Side Templates): انگولار دارای یک template engine قدرتمند برای تعریف قالب است.
- پیروی از الگوی طراحی MVC: انگولار، الگوی طراحی MVC را برای توسعه پیشنهاد میدهد و امکانات زیادی برای توسعه هر چه راحتتر با این الگو فراهم کرده است.
- Data Binding: امکان تعریف انقیاد داده دوطرفه (Two-Way Data Binding) در این فریم ورک به راحتی هرچه تمام، امکان پذیر است.
- Dependency Injection: این فریم ورک برای دریافت وابستگیهای تعریف شده، دارای یک سیستم تزریق وابستگی توکار است.
- تعریف Serviceهای سفارشی: در این فریم ورک امکان تعریف سرویسهای دلخواه به صورت ماژول وجود دارد. این ماژولهای مجزا را به کمک سیستم تزریق وابستگی توکار Angular، به راحتی در هر جای برنامه میتوان تزریق کرد.
- تعریف Directiveهای سفارشی: یکی از جذابترین و قدرتمندترین امکانات این فریم ورک، تعریف Directiveهای سفارشی است. Directive ها، امکان توسعه HTML را فراهم کرده اند. توسعهی HTML اکنون در قالب Web Componentsها فراهم شده است، اما هنوز هم خیلی از مرورگرهای جدید نیز از آن پشتیبانی نمیکنند.
- فرمت کردن اطلاعات با استفاده از فیلترهای سفارشی: با استفاده از فیلترها میتوانید چگونگی الحاق شدن اطلاعات را برای نمایش به کاربر تایین کنید ؛ انگولار همراه با فیلترهای گوناگون مختلفی عرضه میشود که میتوان برایه مثال به فیلتر currency ، date ،uppercase کردن رشتهها و .... اشاره کرد همچنین شما محدود به فیلترهای تعریف شده در انگولار نیستید و آزادید که فیلترهای سفارشی خودتان را نیز تعریف کنید.
- سیستم Routing: دارا بودن سیستم Routing قدرتمند، توسعه SPAها را بسیار ساده کرده است.
- سیستم اعتبار سنجی: Angular دارای سیستم اعتبار سنجی توکار قدرتمند برای بررسی دادههای ورودی است.
- سرویس تو کار برای ارتباط با سرور: Angular دارای سرویس پیش فرض ارتباط با سرور به صورت AJAX است.
- تست پذیری: Angular دارای بستری آماده برای تست کردن برنامههای نوشته شده است و از Unit Tests و Integrated End-to-End Test هم پشتیبانی میکند.
- جامعهی متن باز بسیار قوی
اینها فقط یک مرور کلی بر تواناییهای این فریم ورک بود و در ادامه هر کدام از این ویژگی را به صورت دقیق بررسی خواهیم کرد.
در مقالهی بعدی، به چگونگی نصب AngularJS خواهیم پرداخت. سپس، اولین کد خود را با استفاده از آن خواهیم نوشت و مطالب Client Side Templates و MVC را دقیقتر بررسی خواهیم کرد.
در بخش پیشین به بررسی جزئیتر ایجاد پایگاه داده و همچنین توسعه Custom Filter Attribute پرداختیم که وظیفه تایید صلاحیت کاربر جاری و بررسی دسترسی وی به API Method مورد نظر را بررسی میکرد. در این مقاله به این بحث میپردازیم که در Filter Attribute توسعه داده شده، قصد داریم یک سرویس Access Control ایجاد نماییم.
همانطور که ملاحظه میکنید، ما سه متد GetUserPermissions، GetUserRoles و HasPermission را توسعه دادهایم. حال اینکه بر حسب نیاز، میتوانید متدهای بیشتری را نیز به این سرویس اضافه نمایید. متد اول، وظیفهی واکشی تمامی permissionهای کاربر را عهده دار میباشد. متد GetUserRoles نیز تمامی نقشهای کاربر را در سیستم، بازمیگرداند و در نهایت متد سوم، همان متدی است که ما در Filterattribute از آن استفاده کردهایم. این متد با دریافت پارامترها و بازگردانی یک مقدار درست یا نادرست، تعیین میکند که کاربر جاری به آن محدوده دسترسی دارد یا خیر.
در متد فوق ما از متد سرویس Access Control که لیست تمامی permissionهای کاربر را باز میگرداند، کمک گرفتیم. متد GetUserPermissions پس از ورود کاربر توسط کلاینت فراخوانی میگردد و لیست تمامی دسترسیها در سمت کلاینت، در rootScope انگیولار ذخیره سازی میگردد. حال نوبت به آن رسیده که به بررسی عملیات سمت کلاینت بپردازیم.
اگر بخواهیم مختصری دربارهی این سرویس صحبت کنیم، متد اول که یک دستور GET ساده است و لیست دسترسیها را از PermissionController دریافت میکند. متد بعدی که در آینده بیشتر با آن آشنا میشویم، عملیات تایید صلاحیت کاربر را به ناحیه مورد نظر، انجام میدهد (همان مثال دسترسی به دکمه ویرایش مطلب در یک صفحه). در این متد برای جستجوی لیست permissions از کتابخانهای با نام Lodash کمک گرفتهایم. این کتابخانه کاری شبیه به دستورات Linq را در کالکشنها و آرایههای جاوااسکریپتی، انجام میدهد. متد some یک مقدار درست یا نادرست را بازمیگرداند. بازگردانی مقدار درست، به این معنی است که کاربر به ناحیهی مورد نظر اجازهی دسترسی را خواهد داشت.
حال تمامی اطلاعات دسترسی، در سمت کلاینت نیز قابل دسترسی میباشد. تنها کاری که نیاز است، broadCast کردن متد isAuthorize است که آن هم باید در rootScope قرار بگیرد. ما برای این انتساب یک راهکار را ارائه کردهایم. معماری سیستم کلاینت به این صورت است که تمامی کنترلرها درون یک parentController قرار گرفتهاند. از این رو میتوان در parentController این انتساب (ایجاد دسترسی عمومی برایisAuthorize) صورت گیرد. برای این کار در parentController تغییرات زیر صورت میگیرد:
در کد فوق ما isAuthorize را درون scope قرار دادهایم. دلیل آن هم این است که هر چه که در scope قرار بگیرد، تمامی کنترلرهای child نیز به آن دسترسی خواهند داشت. البته ممکن است که این بهترین نوع پیاده سازی برای به اشتراک گذاری یک منبع نباشد.
همانطور که مشاهده میکنید، تمامی المانها را میتوان با دستور ساده ng-if، از دید کاربران بدون صلاحیت، پنهان نمود. البته توجه داشته باشید که شما نمیتوانید تنها به پنهان کردن این اطلاعات اکتفا کنید. بلکه باید تمامی متدهای کنترلرهای سمت سرور را هم با همین روش (فیلتر کردن با Filter Attribute) بررسی نمایید. به ازای هر درخواست کاربر باید بررسی شود که او به منبع مورد نظر دسترسی دارد یا خیر.
این سرویس وظیفه تمامی اعمال مربوط به نقشها و دسترسیهای کاربر را بر عهده خواهد داشت. این سرویس به صورت زیر تعریف میگردد:
public class AccessControlService { private DbContext db; public AccessControlService() { db = new DbContext(); } public IEnumerable<Permission> GetUserPermissions(string userId) { var userRoles = this.GetUserRoles(userId); var userPermissions = new List<Permission>(); foreach (var userRole in userRoles) { foreach (var permission in userRole.Permissions) { // prevent duplicates if (!userPermissions.Contains(permission)) userPermissions.Add(permission); } } return userPermissions; } public IEnumerable<Role> GetUserRoles(string userId) { return db.Users.FirstOrDefault(x => x.UserId == userId).Roles.ToList(); } public bool HasPermission(string userId, string area, string control) { var found = false; var userPermissions = this.GetUserPermissions(userId); var permission = userPermissions.FirstOrDefault(x => x.Area == area && x.Control == control); if (permission != null) found = true; return found; } {
تمامی حداقلهایی که برای نگارش سمت سرور نیاز بود، به پایان رسید. حال به بررسی این موضوع خواهیم پرداخت که چگونه این سطوح دسترسی را با سمت کاربر همگام نماییم. به طوری که به عنوان مثال اگر کاربری حق دسترسی به ویرایش مطالب یک سایت را ندارد، دکمه مورد نظر که او را به آن صفحه هدایت میکند نیز نباید به وی نشان داده شود. سناریویی که ما برای این کار در نظر گرفتهایم، به این گونه میباشد که در هنگام ورود کاربر، لیستی از تمامی دسترسیهای او به صورت JSON به سمت کلاینت ارسال میگردد. حال وظیفه مدیریت نمایش یا عدم نمایش المانهای صفحه، بر عهده زبان سمت کلاینت، یعنی AngularJs خواهد بود. بنابراین در ابتداییترین حالت، ما نیاز به یک کنترلر و متد Web API داریم تا لیست دسترسیهای کاربر را بازگرداند. این کنترلر در حال حاضر شامل یک متد است. اما بر حسب نیاز، میتوانید متدهای بیشتری را به کنترلر اضافه نمایید.
[RoutePrefix("َAuth/permissions")] public class PermissionsController : ApiController { private AccessControlService _AccessControlService = null; public PermissionsController() { _AccessControlService = new AccessControlService(); } [Route("GetUserPermissions")] public async Task<IHttpActionResult> GetUserPermissions() { if (!User.Identity.IsAuthenticated) { return Unauthorized(); } return Ok(_AccessControlService.GetPermissions(User.Identity.GetCurrentUserId())); } }
توسعه سرویسها و فرآیندهای سمت وب کلاینت AngularJS
در ابتدا در سمت کلاینت نیاز به سرویسی داریم که دسترسیهای سمت سرور را دریافت نماید. از این رو ما نام این سرویس را permissionService مینامیم.
'use strict'; angular.module('App').factory('permissionService', ['$http', '$q', function ($http, $q) { var _getUserPermissions = function () { return $http.get(serviceBaseUrl + '/api/permissions/GetUserPermissions/'); } var _isAuthorize = function (area, control) { return _.some($scope.permissions, { 'area': area, 'control': control }); } return { getUserPermissions: _getUserPermissions, isAuthorize: _isAuthorize }; }]);
حال باید متدهای این سرویس را در کنترلر لاگین فراخوانی نماییم. در این مرحله ما از rootScope dependency استفاده میکنیم. برای نحوهی عملکرد rootScope میتوانید به مقالهای در این زمینه در وب سایت toddomotto مراجعه کنید. در این مقاله ویژگیها و اختلافهای scope و rootScope به تفصیل بیان شده است. مقالهای دیگر در همین زمینه نوشته شده است که در انتهای مقاله به بررسی چند نکته در مورد کدهای مشترک پرداخته شدهاست. تکه کد زیر، متد login را نمایش میدهد که در loginController قرار گرفته است و ما در آن از نوشتن کل بلاک loginController چشم پوشی کردهایم. متد savePermissions تنها یک کار را انجام میدهد و آن هم این است که در ابتدا، به سرویس permissionService متصل شده و تمامی دسترسیها را واکشی مینماید و پس از آن، آنها را درون rootScope قرار میدهد تا در تمامی کنترلرها قابل دسترسی باشد.
$scope.login = function () { authService.login($scope.loginData).then(function (response) { savePermissions(); $location.path('/userPanel'); }, function (err) { $scope.message = err.error_description; }); }; var savePermissions = function () { permissionService.getUserPermissions().then(function (response) { $rootScope.permissions = response.data; }, function (err) { }); } }
App.controller('parentController', ['$rootScope', '$scope', 'authService', 'permissionService', function ($rootScope, $scope, authService, permissionService) { $scope.authentication = authService.authentication; // isAuthorize Method $scope.isAuthorize = permissionService.isAuthorize(); // rest of codes }]);
در گام بعدی کافیست المانهای صفحه را بر اساس همین دسترسیها فعال یا غیر فعال کنیم. برای این کار از دستور ng-if میتوان استفاده کرد. برای این کار به مثال زیر توجه کنید:
<div ng-controller="childController"> <div ng-if="isAuthorize('articles', 'edit')" > <!-- the block that we want to not see unauthorize person --> </div> </div>
تنها نکتهای که باقی میماند این است که طول عمر scope و rootScope چقدر است؟! برای پاسخ به این سوال باید بگوییم هر بار که صفحه refresh میشود، تمامی مقادیر scope و rootScope خالی میشوند. برای این کار هم یک راهکار خیلی ساده (و شاید کمی ناشیانه) در نظر گرفته شدهاست. میتوان بلاک مربوط به پر کردن rootScope.permissions را که در loginController نوشته شده بود، به درون parentController انتقال داد و آن را با استفاده از emit اجرا کرد و در حالت عادی، در هنگام refresh شدن صفحه نیز چون parentController در اولین لحظه اجرا میشود، میتوان تمامی مقادیر rootScope.permissions را دوباره از سمت سرور دریافت کرد.
با سلام و تشکر از مطالب شما
میخواستم بدونم میشه یه پروژه از نوع mvc و یه پروژه از نوع web form رو به صورت subdomain رو iis نصب کرد؟
در واقع من میخوام cms سایت رو با mvc انجام بدم و خود سایت رو با web from و به صورت ساب دومین مثلاً:
میخواستم بدونم میشه یه پروژه از نوع mvc و یه پروژه از نوع web form رو به صورت subdomain رو iis نصب کرد؟
در واقع من میخوام cms سایت رو با mvc انجام بدم و خود سایت رو با web from و به صورت ساب دومین مثلاً:
cms.mysite.com
mysite.com
mysite.com
ممنون.
نظرات مطالب
شروع کار با ASP.NET Web API 2
با سلام
سوالی که برای من پیش آمد این است که هنگامی که قصد فراخوانی اکشنهای web api در برنامه ای دیگر را داریم، حتما باید یک کلاس معادل مثلا product در برنامه مورد نظر ایجاد کنیم. ایا روشی به جز این وجود دارد؟ چون در مورد وب سرویسهای wcf بعد از اضافه کردن به referenceها و ایجاد یک ابجکت از روی آن، میتوان به فیلدهای مورد نظر (بدون ایجاد کلاسی معادل) و صرفا با استفاده از ابجکت ریسپانس دسترسی داشت. ایا در مورد web pi هم چنین قابلیتی وجود دارد تا نیازی به ایجاد کلاسی معادل برای نگهداری اطلاعات در سمت کاربر نباشد؟ فرض کنید در حال حاضر یک وب سرویس wcf در سمت کاربر وجود دارد و صرفا قصد جایگزنی آن با اکشن web pi را داریم( تغییری بیش از این مورد نیاز نباشد)
با تشکر
<iframe src="/twitter" frameborder="0" height="400" width="270" scrolling="no"></iframe>
فلسفه و کاربرد web pages متفاوت است. در مورد وب فرمها هم نمیتونید از razor استفاده کنید چون در یک فایل نمیشود از دو موتور view استفاده کرد. موتور view وب فرمها، نامش همین web forms view engine است و قابل تعویض هم نیست (برخلاف MVC). در مقالهای که لینک دادید، داره از یک iframe استفاده میکنه برای الحاق razor.
به علاوه در مورد Web API که کلا مطلب جدیدی نیست. نسخه ساده شده WCF است.