نظرات مطالب
بازخوردهای دوره
بایدها و نبایدهای استفاده از IoC Containers
برای این که مطمئن بشم که آیا DI رو به صورت صحیح پیاده کردم یا نه آیا چک لیستی یا روشی برای این کار هست؟
برای مثال الان دارم فکر میکنم که چطور این کارو تو winForms میشه انجام داد، پس از انجام ، آیا کارم درست هست یا نه؟
روشی برای حصول اطمینان هست؟
- مثال نهایی این سه قسمت دارای دو افزونه است. کدهای نهایی آنرا پس از مطالعهی هر سه قسمت، بررسی کنید.
- ساختار تمام افزونههای دیگر هم مانند افزونهی توضیح داده شدهاست. قسمت «بارگذاری و تشخیص خودکار افزونهها » در مطلب، اساسا کاری به محل قرارگیری یا نحوهی تعریف افزونهها ندارد. فقط اسمبلیهای موجود در پوشهی bin برنامهی اصلی (فایلهای dll نهایی) را اسکن میکند و بر اساس قرارداد مشخص شده، آنها را به سیستم اضافه خواهد کرد. بنابراین مهم نیست که این افزونهها جزئی از پروژهی جاری هستند یا خیر. آیا توسط یک تیم دیگر در سیستمهای مستقلی در حال تهیه هستند یا خیر. همینقدر که فایل dll نهایی این افزونهها را در پوشهی bin برنامهی اصلی کپی کنید، کار اسکن خودکار آنها توسط استراکچرمپ انجام خواهد شد.
- ساختار تمام افزونههای دیگر هم مانند افزونهی توضیح داده شدهاست. قسمت «بارگذاری و تشخیص خودکار افزونهها » در مطلب، اساسا کاری به محل قرارگیری یا نحوهی تعریف افزونهها ندارد. فقط اسمبلیهای موجود در پوشهی bin برنامهی اصلی (فایلهای dll نهایی) را اسکن میکند و بر اساس قرارداد مشخص شده، آنها را به سیستم اضافه خواهد کرد. بنابراین مهم نیست که این افزونهها جزئی از پروژهی جاری هستند یا خیر. آیا توسط یک تیم دیگر در سیستمهای مستقلی در حال تهیه هستند یا خیر. همینقدر که فایل dll نهایی این افزونهها را در پوشهی bin برنامهی اصلی کپی کنید، کار اسکن خودکار آنها توسط استراکچرمپ انجام خواهد شد.
بعید میدونم. علتش به توسعه پذیری SharePoint بر میگرده که بر اساس معماری وب فرمها از ابتدا طراحی شده. اگر بروند سراغ MVC تمام افزونههای قبلی از کار میافته یا به شدت مشکل پیدا میکنند. ضمن اینکه SharePoint پلتفرم واقعا عظیمی است. خیلی هزینهبر است تبدیل آن.
برای مثال شاید همین سوال در مورد IE هم باشد. چرا IE رو با دات نت نمینویسند؟ علتش این است که بعد از این همه سال میلیونها دلار خرج code base آن شده. دور ریختن و دل کندن از آن واقعا سخت است.
برای مثال شاید همین سوال در مورد IE هم باشد. چرا IE رو با دات نت نمینویسند؟ علتش این است که بعد از این همه سال میلیونها دلار خرج code base آن شده. دور ریختن و دل کندن از آن واقعا سخت است.
در نگارشهای اخیر کتابخانه jQuery (از نگارش 1.3 به بعد) متدی به نام live به آن اضافه شده است که کاربرد آنرا در ادامه مرور خواهیم کرد.
ابتدا مثال زیر را در نظر بگیرید:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestLive.aspx.cs" Inherits="TestJQueryAjax.TestLive" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('a.mylink').click(function(e) {
var $a = $(this);
alert($a.attr('id'));
});
$('a#lnkLoad').click(function(e) {
$('div#dynContent').load('live.ashx');
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<a href='#' id='lnk1' class='mylink'>link1</a>
<br />
<a href='#' id='lnkLoad'>load .ashx</a>
<div id='dynContent'>
</div>
</form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace TestJQueryAjax
{
/// <summary>
/// Summary description for $codebehindclassname$
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class live : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("<a href='#' id='lnk2' class='mylink'>link2</a>");
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
همچنین اگر بر روی لینکی با id مساوی lnkLoad کلیک شود، محتوایی پویا از یک generic handler به نام live.ashx دریافت شده و به div ایی با id مساوی dynContent اضافه میگردد.
این محتوای دریافتی از generic handler ما نیز کلاسی مساوی mylink دارد، اما اینبار هر چقدر بر روی لینک اضافه شده به صفحه کلیک کنیم کار نمیکند. چرا؟ چون در هنگام فراخوانی document.ready ، این لینک وجود نداشته و روال رخدادگردانی به آن bind نشده است.
به صورت خلاصه میخواهیم روال کلیک بر روی لینکهایی با کلاس mylink همیشه کار کند. (چه در مورد عناصری در صفحه که از قبل وجود داشتهاند و چه عناصری که توسط عملیاتی Ajax ایی بعدا اضافه خواهند شد)
این مشکل با معرفی متد live حل شده است. برای این منظور تنها کافی است کد ما به صورت زیر تغییر کند:
<script type="text/javascript">
$(document).ready(function() {
$('a.mylink').live("click", function() {
var $a = $(this);
alert($a.attr('id'));
});
.
.
.
اکنون jQuery کلیه لینکهایی با کلاس مساوی mylink را که از این پس اضافه خواهند شد، به صورت live و زنده تحت نظر قرار میدهد و عکس العمل نشان خواهد داد.
مطالب
ASP.NET MVC #8
معرفی HTML Helpers
یک HTML Helper تنها یک متد است که رشتهای را بر میگرداند و این رشته میتواند حاوی هر نوع محتوای دلخواهی باشد. برای مثال میتوان از HTML Helpers برای رندر تگهای HTML، مانند img و input استفاده کرد. یا به کمک HTML Helpers میتوان ساختارهای پیچیدهتری مانند نمایش لیستی از اطلاعات دریافت شده از بانک اطلاعاتی را پیاده سازی کرد. به این ترتیب حجم کدهای تکراری تولید رابط کاربری در Viewهای برنامههای ASP.NET MVC به شدت کاهش خواهد یافت، به همراه قابلیت استفاده مجدد از متدهای الحاقی HTML Helpers در برنامههای دیگر.
HTML Helpers در ASP.NET MVC معادل کنترلهای ASP.NET Web forms هستند اما نسبت به آنها بسیار سبکتر میباشند؛ برای مثال به همراه ViewState و همچنین Event model نیستند.
ASP.NET MVC به همراه تعدادی متد HTML Helper توکار است و برای دسترسی به آنها شیء Html که وهلهای از کلاس توکار HtmlHelper میباشد، در تمام Viewها قابل استفاده است.
نحوه ایجاد یک HTML Helper سفارشی
از دات نت سه و نیم به بعد امکان توسعه اشیاء توکار فریم ورک، به کمک متدهای الحاقی (extension methods) میسر شده است. برای نوشتن یک HTML Helper نیز باید همین شیوه عمل کرد و کلاس HtmlHelper را توسعه داد. در ادامه قصد داریم یک HTML Helper را جهت رندر تگ label در صفحه ایجاد کنیم. برای این منظور پوشهی جدیدی به نام Helper را به پروژه اضافه نمائید (جهت نظم بیشتر). سپس کلاس زیر را به آن اضافه کنید:
using System;
using System.Web.Mvc;
namespace MvcApplication4.Helpers
{
public static class LabelExtensions
{
public static string MyLabel(this HtmlHelper helper, string target, string text)
{
return string.Format("<label for='{0}'>{1}</label>", target, text);
}
}
}
همانطور که ملاحظه میکنید متد Label به شکل یک متد الحاقی توسعه دهنده کلاس HtmlHelper که تنها یک رشته را بر میگرداند، تعریف شده است. اکنون برای استفاده از این متد در View دلخواهی خواهیم داشت:
@using MvcApplication4.Helpers
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@Html.MyLabel("firstName", "First Name:")
ابتدا فضای نام مرتبط با متد الحاقی باید پیوست شود و سپس از طریق شیء Html میتوان به این متد الحاقی دسترسی پیدا کرد. اگر برنامه را اجرا کنید، این خروجی را مشاهده خواهیم کرد. چرا؟
Index
<label for='firstName'>First Name:</label>
علت این است که Razor، اطلاعات را Html encoded به مرورگر تحویل میدهد. برای تغییر این رویه باید اندکی متد الحاقی تعریف شده را تغییر داد:
using System.Web.Mvc;
namespace MvcApplication4.Helpers
{
public static class LabelExtensions
{
public static MvcHtmlString MyLabel(this HtmlHelper helper, string target, string text)
{
return MvcHtmlString.Create(string.Format("<label for='{0}'>{1}</label>", target, text));
}
}
}
تنها تغییر صورت گرفته، استفاده از MvcHtmlString بجای string معمولی است تا Razor آنرا encode نکند.
تعریف HTML Helpers سفارشی به صورت عمومی:
میتوان فضای نام MvcApplication4.Helpers این مثال را عمومی کرد. یعنی بجای اینکه بخواهیم در هر View آنرا ابتدا تعریف کنیم، یکبار آنرا همانند تعاریف اصلی یک برنامه ASP.NET MVC، عمومی معرفی میکنیم. برای این منظور فایل web.config موجود در پوشه Views را باز کنید (و نه فایل web.config قرار گرفته در ریشه اصلی برنامه). سپس فضای نام مورد نظر را در قسمت namespaces صفحات اضافه نمائید:
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="MvcApplication4.Helpers"/>
</namespaces>
به این ترتیب متدهای الحاقی تعریف شده در فضای نام MvcApplication4.Helpers، در تمام Viewهای برنامه در دسترس خواهند بود.
استفاده از کلاس TagBuilder برای تولید HTML Helpers سفارشی:
using System.Web.Mvc;
namespace MvcApplication4.Helpers
{
public static class LabelExtensions
{
public static MvcHtmlString MyNewLabel(this HtmlHelper helper, string target, string text)
{
var labelTag = new TagBuilder("label");
labelTag.MergeAttribute("for", target);
labelTag.InnerHtml = text;
return MvcHtmlString.Create(labelTag.ToString());
}
}
}
در فضای نام System.Web.Mvc، کلاسی وجود دارد به نام TagBuilder که کار تولید تگهای HTML، مقدار دهی ویژگیها و خواص آنها را بسیار ساده میکند و روش توصیه شدهای است برای تولید متدهای HTML Helper. یک نمونه از کاربرد آنرا برای بازنویسی متد MyLabel ذکر شده در اینجا ملاحظه میکنید.
شبیه به همین کلاس، کلاس دیگری به نام HtmlTextWriter در فضای نام System.Web.UI برای انجام اینگونه کارها وجود دارد.
نوشتن HTML Helpers ویژه، به کمک امکانات Razor
نوع دیگری از این متدهای کمکی، Declarative HTML Helpers نام دارند. از این جهت هم Declarative نامیده شدهاند که مستقیما درون فایلهای cshtml یا vbhtml به کمک امکانات Razor قابل تعریف هستند. تولید این نوع متدهای کمکی به این شکل نسبت به مثلا روش TagBuilder سادهتر است، چون توسط Razor به سادگی و به نحو طبیعیتری میتوان تگهای HTML و کدهای مورد نظر را با هم ترکیب کرد (این رفتار طبیعی و روان، یکی از اهداف Razor است).
به عنوان مثال، تعاریف همان کلاسهای Product و Products قسمت قبل (قسمت هفتم) را در نظر بگیرید. با همان کنترلر و View ایی که ذکر شد.
سپس برای تعریف این نوع خاص از HTML Helpers/Razor Helpers باید به این نحو عمل کرد:
الف) در ریشه پروژه یا سایت، پوشهی جدیدی به نام App_Code ایجاد کنید (دقیقا به همین نام. این پوشه، جزو پوشههای ویژه ASP.NET است).
ب) بر روی این پوشه کلیک راست کرده و گزینه Add|New Item را انتخاب کنید.
ج) در صفحه باز شده، MVC 3 Partial Page/Razor را یافته و مثلا نام ProductsList.cshtml را وارد کرده و این فایل را اضافه کنید.
د) محتوای این فایل جدید را به نحو زیر تغییر دهید:
@using MvcApplication4.Models
@helper GetProductsList(List<Product> products)
{
<ul>
@foreach (var item in products)
{
<li>@item.Name ($@item.Price)</li>
}
</ul>
}
در اینجا نحوه تعریف یک helper method مخصوص Razor را مشاهده میکنید که با کلمه @helper شروع شده است. مابقی آن هم ترکیب آشنای code و markup هستند که به کمک امکانات Razor به این شکل روان میسر شده است.
اکنون اگر Viewایی بخواهد از این اطلاعات استفاده کند تنها کافی است به نحو زیر عمل نماید:
@model List<MvcApplication4.Models.Product>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@ProductsList.GetProductsList(@Model)
ابتدا نام فایل ذکر شده بعد نام متد کمکی تعریف شده در آن. Model هم در اینجا به لیستی از محصولات اشاره میکند.
همچنین چون در پوشه app_code قرار گرفته، تمام Viewها به اطلاعات آن دسترسی خواهند داشت. علت هم این است که ASP.NET به صورت خودکار محتوای این پوشه ویژه را همواره کامپایل میکند و در اختیار برنامه قرار میدهد.
به علاوه در این فایل ProductsList.cshtml، باز هم میتوان متدهای helper دیگری را اضافه کرد و از این بابت محدودیتی ندارد. همچنین میتوان این متد helper را مستقیما داخل یک View هم تعریف کرد. بدیهی است در این حالت قابلیت استفاده مجدد از آنرا به همراه داشتن Viewهایی تمیز و کم حجم، از دست خواهیم داد.
جهت تکمیل بحث
Turn your Razor helpers into reusable libraries
نظرات مطالب
ASP.NET MVC #21
- دقیقا به همان نحوی که نوشته شده. onSuccess پس از پایان کار عملیات Ajax ایی فراخوانی میشود. در آنجا متد یاد شده را بر روی Id محتوای پویای بارگذاری شده فراخوانی کنید. یک نمونه مثال دیگر آن استفاده از این روش در مطلب «نمایش فرمهای مودال Ajax ایی در ASP.NET MVC به کمک Twitter Bootstrap» است.
- محل قرارگیری تمام عناصر رو در صفحه با استفاده از jQuery میشود تغییر داد.
اگر با مفاهیمی مانند Id عناصر و نحوه استفاده از آنها در jQuery آشنایی ندارید، یک دوره مقدماتی در اینباره در سایت موجود است.
- محل قرارگیری تمام عناصر رو در صفحه با استفاده از jQuery میشود تغییر داد.
اگر با مفاهیمی مانند Id عناصر و نحوه استفاده از آنها در jQuery آشنایی ندارید، یک دوره مقدماتی در اینباره در سایت موجود است.
نظرات مطالب
بررسی واژه کلیدی static
سلام،
- همانطور که تاکید کردم فیلد استاتیک و نه متد استاتیک که مشکل همزمانی را ندارد.
- برای jQuery Ajax چون بسیاری از ملاحظاتی که توسط MS Ajax انجام میشود مانند کار با ViewState و ارسال و مدیریت آن صورت نمیگیرد، امکان ایجاد وهلهای از کلاس استاندارد صفحه ASP.Net توسط آن میسر نیست. بنابراین باید این متد را استاتیک تعریف کرد تا وابستگی آنرا از شیء صفحه قطع کرد. به همین جهت jQuery Ajax بسیار بهینهتر از MS Ajax عمل میکند (چون اساسا درکی از ViewState ندارد)
- همانطور که تاکید کردم فیلد استاتیک و نه متد استاتیک که مشکل همزمانی را ندارد.
- برای jQuery Ajax چون بسیاری از ملاحظاتی که توسط MS Ajax انجام میشود مانند کار با ViewState و ارسال و مدیریت آن صورت نمیگیرد، امکان ایجاد وهلهای از کلاس استاندارد صفحه ASP.Net توسط آن میسر نیست. بنابراین باید این متد را استاتیک تعریف کرد تا وابستگی آنرا از شیء صفحه قطع کرد. به همین جهت jQuery Ajax بسیار بهینهتر از MS Ajax عمل میکند (چون اساسا درکی از ViewState ندارد)
«این کار احتمالا در ASP.NET WebForm کار سختی نیست»
اتفاقا کار سادهای نیست و همین مراحل باید طی شود. ضمن اینکه کار با jquery ajax در آنجا به این یک دستی نیست. نیاز است در code behind فرم، متد وب سرویس مانندی به صورت استاتیک تعریف شود (که خودش سبب میشود تا دسترسی به اعتبار سنجی توکار مبتنی بر فرمها محدود شود) یا اینکه از یک هندلر مجزا بجای یک اکشن متد کمک گرفته شود ... خلاصه خیلی داستان دارد.
نظرات مطالب
پلاگین DataTables کتابخانه jQuery - قسمت سوم
سلام
رندر کردن جدول حاوی دادهها باید به data tables سپرده بشه. بدین صورت که دادههای دریافتی از سرور به فرمت مناسبی تبدیل بشن و بعد به خصوصیت aaData نسبت داده بشن، البته به تبع اون و حتما باید خصوصیت aoColumns هم مقدار دهی بشه.
کدهای سمت سرور:
مثلا فرض کنید ذر سمت سرور بخواهید لیستی از مرورگرها رو برگشت بدین. کلاس زیر رو در نظر بگیرید:
برای برگشت دادن لیستی از مرورگرها به طرف کلاینت، متدی مثل زیر خواهید داشت:
در متد بالا، لیستی از مرورگرها با استفاده از یک متد الحاقی تبدیل به فرمت json میشه و به طرف کاربر فرستاده میشه.
رندر کردن جدول حاوی دادهها باید به data tables سپرده بشه. بدین صورت که دادههای دریافتی از سرور به فرمت مناسبی تبدیل بشن و بعد به خصوصیت aaData نسبت داده بشن، البته به تبع اون و حتما باید خصوصیت aoColumns هم مقدار دهی بشه.
$(document).ready(function () { $.ajax({ url: "ِDefault.aspx/GetBrowsers", contentType: "application/json; charset=utf-8", dataType: "json", type: "POST", success: function (response) { if (response != "") { var data = eval("(" + response.d + ")"); $('#browsers-grid').dataTable({ "aaData": data, "bProcessing" : true, "aoColumns": [ { "mData": "Engine" }, { "mData": "Name" }, { "mData": "Platform" }, { "mData": "Version", "sClass": "center" }, { "mData": "Grade", "sClass": "center" } ] }); } }, }); });
کدهای سمت سرور:
مثلا فرض کنید ذر سمت سرور بخواهید لیستی از مرورگرها رو برگشت بدین. کلاس زیر رو در نظر بگیرید:
public class Browser { public int Id { get; set; } public string Engine { get; set; } public string Name { get; set; } public string Platform { get; set; } public float Version { get; set; } public string Grade { get; set; } }
برای برگشت دادن لیستی از مرورگرها به طرف کلاینت، متدی مثل زیر خواهید داشت:
[WebMethod] public static string GetBrowsers() { List<Browser> browsers = new List<Browser>() { new Browser { Id = 1, Engine = "Trident", Name = "Internet Explorer 4.0", Platform = "Win95+", Version = 4, Grade = "X" }, new Browser { Id = 2, Engine = "Trident", Name = "Internet Explorer 5.0", Platform = "Win95+", Version = 5, Grade = "C" }, }; return browsers.ToJson(); }
در متد بالا، لیستی از مرورگرها با استفاده از یک متد الحاقی تبدیل به فرمت json میشه و به طرف کاربر فرستاده میشه.