نظرات مطالب
بررسی روش مشاهده خروجی SQL حاصل از کوئری‌های Entity framework Core
یک نکته‌ی تکمیلی: روش مشاهده‌ی مقدار پارامترها در لاگ‌های SQL
در حالت معمولی، خروجی SQL لاگ شده‌ی توسط EF Core به صورت زیر است:
Microsoft.EntityFrameworkCore.Database.Command[20101] Executed DbCommand (41ms) 
[Parameters=[@__id_0='?' (DbType = Int32)], 
CommandType='Text', CommandTimeout='30']
 SELECT TOP(2) [m].[Id], [m].[Address], [m].[City], [m].[Email], [m].[Name], [m].[Phone], [m].[PostalCode], [m].[State] FROM [Contact] AS [m] WHERE [m].[Id] = @__id_0
برای مشاهده‌ی مقدار پارامترها نیاز است SensitiveDataLogging را فعال کرد:
services.AddDbContext<ContactsContext>(options => { 
  options.UseSqlServer(Configuration["Data:ContactsContext:ConnectionString"]); 
  options.EnableSensitiveDataLogging(); 
});
اینبار خروجی لاگ شده، مقدار پارامترها را نیز به همراه دارد:
Microsoft.EntityFrameworkCore.Database.Command[20100] Executing DbCommand
 [Parameters=[@__id_0='1' (Nullable = true)], 
CommandType='Text', CommandTimeout='30'] 
SELECT TOP(2) [m].[Id], [m].[Address], [m].[City], [m].[Email], [m].[Name], [m].[Phone], [m].[PostalCode], [m].[State] FROM [Contact] AS [m] WHERE [m].[Id] = @__id_0
مطالب
AngularJS #4
در این قسمت قصد دارم تا یک سیستم ارسال دیدگاه را به کمک Angular پیاده سازی کنم. هدف از این مثال؛ آشنایی با چند Directive توکار Angular و همچنین آموختن چگونگی کار با سرویس http$ برای ارتباط با سرور است.
کدهای HTML زیر را در نظر بگیرید:
<div ng-app="myApp">
    <div ng-controller="CommentCtrl">

        <div ng-repeat="comment in comments">
            <div style="float:right;cursor:pointer;" ng-click="remove(comment.Id,$index);">X</div>
            <a href="#">
                <img style="width:32px;" ng-src="/Content/user.gif" alt="{{comment.Name}}">
            </a>
            <div>
                <h4>{{comment.Name}}</h4>
                {{comment.CommentBody}}
            </div>
        </div>

        <div>
            <form action="/Comment/Add" method="post">
                <div>
                    <label for="Name">Name</label>
                    <input id="Name" type="text" name="Name" ng-model="comment.Name" placeholder="Your Name" />
                </div>
                <div>
                    <label for="Email">Email</label>
                    <input id="Email" type="text" name="Email" ng-model="comment.Email" placeholder="Your Email" />
                </div>
                <div>
                    <label for="CommentBody">Comment</label>
                    <textarea id="CommentBody" name="CommentBody" ng-model="comment.CommentBody" placeholder="Your Comment"></textarea>
                </div>
                <button type="button" ng-click="addComment()">Send</button>
            </form>
        </div>

    </div>
</div>
خب از ابتدا ساختار را مورد بررسی قرار می‌دهم و موارد ناآشنای آن را توضیح می‌دهم:

ng-app: خاصیت ng-app جز خواص پیش فرض HTML نیست و یک خاصیت سفارشی است که توسط Angular به صورت پیش فرض تعریف شده است. این خاصیت به Angular می‌گوید که کدام بخش از DOM باید توسط Angular مدیریت و پردازش شود. در اینجا div ای که با خاصیت ng-app مزین شده است به همراه تمامی عناصر فرزند آن توسط موتور پردازش گر DOM توکار مورد پردازش قرار گرفته و اصطلاحا کامپایل می‌شود. بله! اینجا از لفظ کامپایل شدن برای بیان این فرآیند استفاده کردم. هیچ کدام از این Directive‌های سفارشی به خودی خود برای مرورگر قابل تفسیر نیست و اینجاست که Angular وارد عمل شده و این Directive‌ها را به کدهای HTML و جاوا اسکریپت که برای مرورگر قابل فهم است تبدیل می‌کند. به همین جهت با ng-app مشخص می‌کنیم که کدام بخش از DOM باید توسط Angular تفسیر و مدیریت شود.شاید این سوال برای شما مطرح شده باشد که در مثال قبلی ng-app مقداری نداشت و برای تگ html تعریف شده بود. پاسخ این است که در مثال قبلی چون برنامه‌ی ما دارای یک ماژول بیشتر نبود می‌توانستیم از مقدار دهی ng-app صرف نظر کنیم؛ اما در این مثال ما قصد داریم کمی هم مفهوم ماژول را در Angular بررسی کنیم. در نتیجه در این مثال برنامه‌ی ما از ماژولی به نام myApp تشکیل شده است. دلیل اینکه در این مثال ng-app بر روی یک div تعریف شده است این است که همین قسمت از DOM توسط Angular تفسیر شود برای ما کفایت می‌کند. هنگامی ng-app را بر روی html تعریف می‌کنیم که قصد داشته باشیم کل صفحه توسط Angular تفسیر شود.
 
ng-controller: در Angular کنترلر‌ها تابع سازنده‌ی کلاس‌های ساده‌ی جاوا اسکریپتی هستند که به کمک آن‌ها بخشی از صفحه را مدیریت می‌کنیم. این که کدام بخش از صفحه توسط کدام کلاس کنترل و مدیریت شود، توسط ng-controller مشخص می‌شود. در اینجا هم عنصری که با ng-controller مشخص شده به همراه تمامی فرزندانش، توسط کلاس جاوا اسکریپتی به نام CommentCtrl مدیریت می‌شود. در حقیقت ما به کمک ng-controller مشخص می‌کنیم که کدام قسمت از View توسط کدام Controller مدیریت می‌شود. مرسوم است که در Angular نام کنترلرها با Ctrl خاتمه یابد.
   
ng-repeat: همه‌ی نظرات دارای یک قالب html یکسان هستند که به ازای داده‌های متفاوت تکرار شده اند. اگر می‌خواستیم نظرات را استفاده از موتور نمایشی Razor نشان دهیم از یک حلقه‌ی foreach استفاده می‌کردیم. خبر خوب این است که ng-repeat هم دقیقا به مانند حلقه‌ی foreach عمل می‌کند.در اینجا عبارت comment in comments دقیقا برابر با آن چیزی است که در یک حلقه‌ی foreach می‌نوشتیم. Comments در اینجا یک لیست به مانند آرایه ای از comment هست که در کنترلر مقدار دهی شده است. پس اگر با حلقه‌ی foreach مشکلی نداشته باشید با مفهوم ng-repeat هم مشکلی نخواهید داشت و دقیقا به همان شکل عمل می‌نماید.
     
ng-click: همان طور که گفتیم Directive‌های تعریف شده می‌توانند یک event سفارشی نیز باشند. ng-click هم یک Directive تو کار است که توسط Angular به صورت پیش فرض تعریف شده است. کاملا مشخص است که یک تابع به نام remove تعریف شده است که به هنگام کلیک شدن، فراخوانی می‌شود. دو پارامتر هم به آن ارسال شده است. اولین پارامتر Id دیدگاه مورد نظر است تا به سرور ارسال شود و از پایگاه داده حذف شود. دومین پارامتر index$ است که یک متغیر ویژه است که توسط Angular در هر بار اجرای حلقه‌ی ng-repeat مقدارش یک واحد افزایش می‌یابد. index$ هم به تابع remove ارسال می‌شود تا بتوان فهمید در سمت کلاینت کدام نظر باید حذف شود.
 
ng-src: از این Directive برای مشخص کردن src عکس‌ها استفاده می‌شود. البته در این مثال چندان تفاوتی بین ng-src و src معمولی وجود ندارد. ولی اگر آدرس عکس به صورت Content/{{comment.Name}}.gif می‌بود دیگر وضع فرق می‌کرد. چرا که مرورگر با دیدن آدرس در src سعی به لود کردن آن عکس می‌کند و در این حالت در لود کردن آن عکس با شکست روبرو می‌شود. ng-src سبب می‌شود تا در ابتدا آدرس عکس توسط Angular تفسیر شود و سپس آن عکس توسط مرورگر لود شود.
   
{{comment.Name}}: آکلودهای دوتایی برای انقیاد داده (Data Binding) با view-model استفاده می‌شود. این نوع اقیاد داده در مثال‌های قبلی مورد بررسی قرار گرفته است و نکته‌ی بیشتری در اینجا مطرح نیست.
   
ng-model: به کمک ng-model می‌توان بین متن داخل textbox و خاصیت شی مورد نظر انقیاد داده بر قرار کرد و هر دو طرف از تغییرات یکدیگر آگاه شوند. به این عمل انقیاد داده دوطرفه (Two-Way Data-Binding) می‌گویند.برای مثال textbox مربوط به نام را به comment.Name و textbox مربوط به email را به comment.Email مقید(bind) شده است. هر تغییری که در محتوای هر کدام از طرفین صورت گیرد دیگری نیز از آن تغییر با خبر شده و آن را نمایش می‌دهد.
   
تا به اینجای کار قالب مربوط به HTML را بررسی کردیم. حال به سراغ کدهای جاوا اسکریپت می‌رویم:
var app = angular.module('myApp', []);

app.controller('CommentCtrl', function ($scope, $http) {

    $scope.comment = {};

    $http.get('/Comment/GetAll').success(function (data) {

        $scope.comments = data;

    })

    $scope.addComment = function () {

        $http.post("/Comment/Add", $scope.comment).success(function () {

            $scope.comments.push({ Name: $scope.comment.Name, CommentBody: $scope.comment.CommentBody });

            $scope.comment = {};

        });
    };

    $scope.remove = function (id, index) {

        $http.post("/Comment/Remove", { id: id }).success(function () {

            $scope.comments.splice(index, 1);

        });
    };

});
در تعریف ng-app اگر به یاد داشته باشید برای آن مقدار myApp در نظر گرفته شده بود. در اینجا هم ما به کمک متغیر سراسری angular که توسط خود کتابخانه تعریف شده است، ماژولی به نام myApp را تعریف کرده ایم. پارامتر دوم را فعلا توضیح نمی‌دهم، ولی در این حد بدانید که برای تعریف وابستگی‌های این ماژول استفاده می‌شود که من آن را برابر یک آرایه خالی قرار داده ام.
در سطر بعد برای ماژول تعریف شده یک controller تعریف کرده ام. شاید دفعه‌ی اول است که تعریف کنترلر به این شکل را مشاهده می‌کنید. اما چرا به این شکل کنترلر تعریف شده و به مانند قبل به شکل تابع سازنده‌ی کلاس تعریف نشده است؟
پاسخ این است که اکثر برنامه نویسان از جمله خودم دل خوشی از متغیر سراسری ندارند. در شکل قبلی تعریف کنترلر، کنترلر به شکل یک متغیر سراسری تعریف می‌شد. اما استفاده از ماژول برای تعریف کنترلر سبب می‌شود تا کنترلرهای ما روی هوا تعریف نشده باشند و هر یک در جای مناسب خود باشند. به این شکل مدیریت کدهای برنامه نیز ساده‌تر بود. مثلا اگر کسی از شما بپرسد که فلان کنترلر کجا تعریف شده است؛ به راحتی می‌گویید که در فلان ماژول برنامه تعریف و مدیریت شده است.
در تابعی که به عنوان کنترلر تعریف شده است، دو پارامتر به عنوان وابستگی درخواست شده است. scope که برای ارتباط با view-model و انقیاد داده به کار می‌رود و http$  که برای ارتباط با سرور به کار می‌رود. نمونه‌ی مناسب هر دوی این پارامترها توسط سیستم تزریق وابستگی تو کار angular در اختیار کنترلر قرار می‌گیرد.
قبلا چگونگی استفاده از scope$ برای اعمال انقیاد داده توضیح داده شده است. نکته‌ی جدیدی که مطرح است چگونگی استفاده از سرویس http$ برای ارتباط با سرور است. سرویس http $   دارای 4 متد put ، post ، get و delete است.
واقعا استفاده از این سرویس کاملا واضح و روشن است. در متد addComment وقتی که دیدگاه مورد نظر اضافه شد، به آرایه‌ی کامنت‌ها یک کامنت جدید می‌افزاییم و چون انقیاد داده دو طرفه است، بالافاصله دیدگاه جدید نیز در view به نمایش در می‌آید.کار تابع remove هم بسیار ساده است. با استفاده از index ارسالی، دیدگاه مورد نظر را از آرایه‌ی کامنت‌ها حذف می‌کنیم و ادامه‌ی کار توسط انقیاد داده دو طرفه انجام می‌شود.
همان طور که مشاهده می‌شود مفاهیم انقیاد داده دو طرفه و تزریق وابستگی خودکار سرویس‌های مورد نیاز، کار با angularjs را بسیار ساده و راحت کرده است. اصولا در بسیاری از موارد احتیاجی به باز اختراع چرخ نیست و کتابخانه‌ی angular آن را برای ما از قبل تدارک دیده است.
   
کدهای این مثال ضمیمه شده است. این کدها در Visual Studio 2013 و به کمک ASP.NET MVC 5 و Entity Framework 6 نوشته شده است. سعی شده تا مثال نوشته شده به واقعیت نزدیک باشد. اگر دقت کنید مدل کامنت در مثالی که نوشتم به گونه ای است که دیدگاه‌های چند سطحی به همراه پاسخ هایش مد نظر بوده است. به عنوان تمرین نمایش درختی این گونه دیدگاه‌ها را به کمک Angular انجام دهید. کافیست Treeview in Angular را جست و جو کنید؛ مطمئنا به نتایج زیادی می‌رسید. گرچه در مثال ضمیمه شده اگر جست و جو کنید من پیاده سازیش را انجام دادم. هدف از جست و جو در اینترنت مشاهده این است که بیشتر مسائل در Angular از پیش توسط دیگران حل شده است و احتیاجی نیست که شما با چالش‌های جدیدی دست و پنجه نرم کنید.
پس به عنوان تمرین، دیدگاه‌های چند سطحی به همراه پاسخ که نمونه اش را در همین سایتی که درحال مشاهده آن هستید می‌بینید را به کمک AngularJS پیاده سازی کنید.
  
در مقاله‌ی بعدی چگونگی انتقال منطق تجاری برنامه از کنترلر به لایه سرویس و چگونگی تعریف سرویس جدید را مورد بررسی قرار می‌دهم.
   

مطالب
لینک‌های هفته اول دی

وبلاگ‌ها و سایت‌های ایرانی

امنیت



ASP. Net


طراحی وب

PHP


اس‌کیوال سرور


سی شارپ


عمومی دات نت


مسایل اجتماعی و انسانی برنامه نویسی


کتاب‌های رایگان جدید


متفرقه
  • آهن بجای کروم! (یک برنامه نویس آلمانی قسمت‌هایی از مرورگر کروم را که در جهت جمع آوری اطلاعات برای گوگل بکار می‌رفته، حذف کرده و مرورگر دیگری به نام آهن را ارائه داده است!)

مطالب
قابلیت چند زبانه و Localization در AngularJs- بخش دوم: بررسی اجمالی قابلیت های ماژول angular-translate
در بخش قبلی به معرفی ماژول angular-tanslate پرداختیم. در این بخش قصد داریم تا به بررسی مفهومی قابلیت‌های موجود در این ماژول بپردازیم.
شکل زیر یک شمای کلی را از قابلیت‌های angular-translate، نمایش می‌دهد. همانطور که ملاحظه می‌کنید در مواردی نظیر ذخیره سازی زبان‌ها، بارگذاری ریسورس‌های زبان‌ها و گرامرهای استفاده در DOM راهکارهای گوناگونی دارد.

angular-translate دایرکتیو و فیلتر هایی را به صورت کامپوننت عرضه کرده است که شما می‌توانید به وسیله‌ی آنها پروژه خود را به زبان‌های گوناگون localize کنید. آنچه که در تصویر فوق مشاهده می‌کنید در حقیقت ساختار ماژول angular-translate را نمایش می‌دهد. به این صورت که در اولین لایه دایرکتیو translate قرار گرفته است.

سطح بعدی شاید کمی جذاب‌تر به نظر برسد. هر دو بخش دایرکتیو و فیلتر از سرویس تزریق شده translate$ استفاده می‌کنند. این بدین معنی است که در هنگام تغییر یک زبان به زبان دیگر به وسیله دایرکتیوهایی که در view نوشته شده است، در حقیقت شما این دایرکتیو‌ها را به سطح فیلتر انتقال داده‌اید و پس از آن، فیلتر آن را به لایه سرویس برده و سرویس کار اصلی را انجام می‌دهد. 

در سطح بعدی لایه Interpolator قرار گرفته است که وظیفه تغییر DOM‌ها را بر عهده دارد. این فرآیند متغیرهایی را که در ریسورس قرار داده‌ایم، درایه به درایه در view و در مکان‌های هم نام قرار می‌دهد. این فرآیند به وسیله راهکار‌های گوناگونی از قبیل Message Format و یا Angular Core Interpolation Service امکان پذیر است.

جعبه خاکستری رنگ بخش missing translation handler را نشان می‌دهد. این handlerها زمانی فراخوانی می‌گردند که translator به دنبال یک key می‌گردد که تعریف نشده باشد. angular-translate خود شامل یک logging service می‌باشد که به صورت extension باید آن را به پروژه خود اضافه نمایید که در بخش‌های بعدی در مورد آن مفصل‌تر بحث می‌کنیم.

بخش asynchronous loader شما را قادر می‌سازد که داده‌های زبان‌های متفاوت را به صورت غیر هم زمان بارگذاری نمایید. angular-translate از ماژول‌های asynchronous loader پشتیبانی می‌کند. روش معرفی شده در سایت مرجع در مورد بارگذاری غیر همزمان urlLoader و staticFilesLoader هستند که در بخش‌های بعدی به آن خواهیم پرداخت.

angular-translate برای ذخیره سازی داده‌های بازگذاری شده و نگه داشتن زبان سایت در صورت reload شدن صفحه راهکارهای متفاوتی را ارائه نموده است. این قابلیت در ابتدا چک می‌کند که ریسورس‌های زبان درون یک local storage قرار گرفته‌اند یا خیر. این عملیات طی یک فرآیند جستجوی key-value صورت می‌گیرد و در نهایت فایل‌های ریسورس زبان مورد نظر که درون کوکی یا localStorage ذخیره شده‌اند بارگذاری می‌شوند. angular-translate به صورت توکار دارای دو راهکار localStorage و cookieStorage برای ذخیره سازی ریسورس‌ها می‌باشد.

در بخش بعدی در مورد نحوه‌ی ذخیره سازی داده‌ها به دو روش cookieStorage و localStorage بیشتر صحبت خواهیم کرد.

مطالب
استفاده از کتابخانه‌ی moment-jalaali در برنامه‌های Angular
چندی قبل مطلب «نمایش تاریخ شمسی توسط JavaScript در AngularJS» را در این سایت مطالعه کردید. در اینجا قصد داریم معادل Angular آن‌را تهیه کنیم (واژه‌ی AngularJS به نگارش‌های 1x اشاره می‌کند و Angular به تمام نگارش‌های پس از 2).


نصب پیشنیازهای کار با moment-jalaali

ابتدا نیاز است بسته‌ی npm این کتابخانه را نصب کنیم که به همراه فایل‌های js مرتبط با آن می‌باشد:
 npm install moment-jalaali --save

سپس جهت بهبود تجربه‌ی کاربری با آن در IDEهای امروزی، خصوصا VSCode، بهتر است typings آن‌را نیز نصب کنیم؛ تا علاوه بر داشتن Intellisense، بتوان به صورت strongly typed با آن کار کرد:
 npm install @types/moment-jalaali --save-dev


VSCode به صورت خودکار پوشه‌ی مخصوص node_modules\@types را تحت نظر قرار می‌دهد و نصب بسته‌های typings در آن، سبب بارگذاری آنی آن‌ها خواهد شد.
به علاوه اگر به فایل tsconfig.json واقع در ریشه‌ی پروژه نیز دقت کنید، وجود تعریف ذیل، امکان خوانده شدن این تعاریف را توسط کامپایلر TypeScript میسر می‌کند:
{
    "typeRoots": [
      "node_modules/@types"
    ]
}

 
نحوه‌ی کار Strongly Typed با کتابخانه‌ی moment-jalaali در برنامه‌های مبتنی بر TypeScript

پس از نصب پیشنیازهای یاد شده، ابتدا برای دسترسی به امکانات این کتابخانه، ماژول آن‌را import می‌کنیم:
import * as momentJalaali from "moment-jalaali";

export class MomentJalaaliTestComponent implements OnInit {
  now: string;
  nowLongDateFormat: string;
  nowExtraLongDateFormat: string;

  ngOnInit() {
    this.persianDateTests();
  }

  persianDateTests() {
    // https://github.com/jalaali/moment-jalaali
    momentJalaali.loadPersian(/*{ usePersianDigits: true }*/); // نمایش فارسی نام ماه‌ها، روزها و امثال آن

    this.now = momentJalaali().format("jYYYY/jMM/jDD HH:mm");
    this.nowLongDateFormat = momentJalaali().format("jD jMMMM jYYYY [ساعت] LT");
    this.nowExtraLongDateFormat = momentJalaali().format(
      "dddd، jD jMMMM jYYYY [ساعت] LT"
    );
  }
}
- پس از import ماژولی به نام moment-jalaali، اکنون نحوه‌ی استفاده‌ی از آن‌را در متد persianDateTests مشاهده می‌کنید.
- متد momentJalaali.loadPersian باید تنها یکبار فراخوانی شود. کار آن تبدیل نام‌های روزها و ماه‌های میلادی، به شمسی است.
- پس از آن از طریق متد format آن، می‌توان انواع و اقسام حالات مختلف را بررسی کرد که در اینجا سه نمونه را مشاهده می‌کنید.



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

پس آشنا شدن با نحوه‌ی استفاده‌ی از این کتابخانه در یک برنامه‌ی تایپ‌اسکریپتی، تبدیل کردن آن به یک Pipe سفارشی بسیار ساده‌است. برای این منظور ابتدا یک Pipe جدید را به ماژول فرضی custom-pipe.module اضافه می‌کنیم:
 ng g p CustomPipe/moment-jalaali -m custom-pipe.module
با این محتوا:
import { Pipe, PipeTransform } from "@angular/core";

import * as momentJalaali from "moment-jalaali";

@Pipe({
  name: "momentJalaali"
})
export class MomentJalaaliPipe implements PipeTransform {
  transform(value: any, args?: any): any {
    return momentJalaali(value).format(args);
  }
}
در اینجا نیز ابتدا ماژول moment-jalaali تعریف شده‌است و سپس توسط آن، value به عنوان پارامتر متد momentJalaali و args به عنوان پارامتر متد format ارسال شده‌اند. در حین استفاده‌ی از Pipe، مقدار value همان تاریخ دریافتی است و args به فرمت خاصی که توسط استفاده کننده مشخص می‌شود، تنظیم خواهد شد.
به این ترتیب می‌توان یک چنین تبدیلات سمت کاربری را انجام داد که نمونه‌ای از خروجی آن‌را در تصویر فوق نیز ملاحظه می‌کنید:
<h2>Server side dates:</h2>
<div *ngFor="let date of dates">
  <span dir="ltr">{{date | momentJalaali:'jYYYY/jMM/jDD hh:mm' }}</span>,
  <span dir="rtl">{{date | momentJalaali:'jD jMMMM jYYYY [ساعت] LT'}}</span>
</div>


کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید.
نظرات مطالب
AngularJS #1
به شدت دنبال آموزش angularjs بودم. سپاس و چند سوال.
- آیا با استفاده از angularjs برای یک SPA دیگر نیازی به asp.net mvc خواهد بود؟
-کامپایلر ویژوال استودیو به خوبی برای razor کار میکند و بسیار intellisence قوی دارد و امکانات Strongly typed نیز دارد. آیا این امکانات برای angular نیز موجود است تا خطایابی راحت‌تر شود؟
- من یک اپلیکیشن دارم که کاربر هربار یکی از آیتم‌های منو را انتخاب میکند و برای آن یک ویو بصورت partialview درون یک تب لود میشود. هر ویو ، فایل جاوااسکریپت مخصوص به خود دارد. کاربر می‌تواند چندین ویوی مجزا را درون تب‌ها باز کند و بین آنها جابه جا شود. اما مدیریت دستی آنها بسیار سخت شده است. آیا انگولار امکان نمایش چند ویو را بطور همزمان و جابه جا شدن بین آنها را میدهد.( بدون بروز تداخل بین فایل‌های جاوا اسکریپت مربوط به هر ویو).
با تشکر.