۱۳۸۸/۰۴/۰۹

ويديوي رايگان آموزش ساخت مديريت تغييرات توسط SharePoint

ويديوي يك ساعت و 20 دقيقه‌اي در مورد پياده سازي يك change management system توسط SharePoint 2007 . نحوه ايجاد يك گردش كاري در شركت به همراه فرم‌هاي مربوطه جهت مديريت تغييرات درخواستي بر روي پروژه‌ها.



مشاهده آنلاين، مشاهده اسلايدها ، دريافت (پس از دريافت پسوند فايل را به flv تغيير دهيد)

۱۳۸۸/۰۳/۲۳

از كجا به وب سرور شما حمله DOS شده است؟


اگر پيش فرض‌هاي IIS را تغيير نداده باشيد، تمامي اعمال رخ داده در طي يك روز را در يك سري فايل‌هاي متني در يكي از آدرس‌هاي زير ذخيره مي‌كند:

IIS 6.0: %windir%\System32\LogFiles\W3SVC<SiteID>
IIS 7.0: %systemDrive%\Inetpub\logfiles

اطلاعات فوق العاده ارزشمندي را مي‌توان از اين لاگ فايل‌هاي خام بدست آورد. اعم از تعداد بار دقيق مراجعه به صفحات، چه فايل‌هايي مفقود هستند (خطاي 404)، كدام صفحات كندترين‌هاي سايت شما را تشكيل مي‌دهند و الي آخر.
مايكروسافت براي آناليز اين لاگ فايل‌ها (كه محدود به IIS‌ هم نيست) ابزاري را ارائه داده به نام LogParser كه اين امكان را به شما مي‌دهد تا از فايل‌هاي CSV مانند با استفاده از عبارات SQL كوئري بگيريد (چيزي شبيه به پروايدرهاي LINQ البته در سال‌هاي 2005 و قبل از آن).
يكي از كاربردهاي اين ابزار، بررسي‌هاي امنيتي است.

سؤال؟ چگونه متوجه شوم كدام كامپيوتر در شبكه اقدام به حمله DOS كرده و سرور را دارد از پا در مي‌آورد؟
از آنجائيكه در لاگ‌هاي IIS دقيقا IP تمامي درخواست‌ها ثبت مي‌شود، با آناليز اين فايل ساده متني مي‌توان اطلاعات لازم را بدست آورد.
logparser.exe -i:iisw3c "select top 25 count(*) as HitCount, c-ip from C:\WINDOWS\system32\LogFiles\W3SVC1\*.log group by c-ip order by HitCount DESC" -rtp:-1 > top25-ip.txt
دستور خط فرمان فوق، يك كوئري SQL را بر روي تمامي لاگ فايل‌هاي قرار گرفته در مسير ياد شده اجرا كرده و نتيجه را در يك فايل متني ذخيره مي‌كند.
به اين صورت مي‌توان دقيقا متوجه شد كه از كدام IP‌ مشغول به زانو درآوردن سرور هستند.

اگر به اين ابزار علاقمند شديد مطالعه مقاله زير توصيه مي‌شود:


۱۳۸۸/۰۳/۲۰

اصلاح شيوه نامگذاري در ReSharper


يكي از روش‌هاي متداول نام گذاري متدها در سي شارپ به اين صورت است كه متدهاي خصوصي با حروف كوچك شروع شوند يا lower camel case و متدهاي عمومي با حرف بزرگ.
ReSharper 4.5 كه جزو ابزارهاي واجب كاري است، گزينه Naming style را نيز اضافه كرده و اگر شما از اصول نامگذاري متدها، كلاس‌ها ، متغيرها و غيره پيروي نكنيد، علايم راهنمايي را به شما ارائه خواهد كرد. در اين نگارش تمامي متدها به يك صورت در نظر گرفته مي‌شوند: Upper camel case .



براي اصلاح آن مي‌توان به برگه گزينه‌هاي آن مراجعه كرده و در قسمت naming style بر روي دكمه add مربوط به user defined naming rules كليك و تغيير زير را اعمال نمود:



پس از اعمال آن اگر يك متد خصوصي را با حرف بزرگ شروع كنيد، تصوير زير نمايش داده خواهد شد:





۱۳۸۸/۰۳/۱۸

مشكل امنيتي FreeTextBox‌ و روش رفع آن


FreeTextBox يكي از اديتورهاي متني بسيار خوب تحت وب ASP.Net‌ است كه از نگارش 1 تا 3 و نيم ASP.Net را پشتيباني مي‌كند. به همراه آن يك image gallery هم جهت آپلود تصاوير ارائه مي‌شود كه بسيار ارزشمند است. اما مشكلي كه دارد عدم بررسي پسوند فايل آپلود شده است. به عبارتي خاصيت AcceptedFileTypes آن هنگام آپلود تصاوير بررسي نمي‌شود و مي‌تواند مشكلات امنيتي حادي را به وجود آورد (براي مثال شخص بجاي تصوير مي‌تواند فايل aspx را نيز آپلود كند). راه حلي هم براي آن وجود ندارد. سورس اين كامپوننت فقط به خريداران ارائه مي‌شود و نگارش مجاني آن بدون سورس است.

اما با استفاده از توانايي‌هاي موجود در فايل استاندارد global.asax مي‌توان روي آپلود تمامي فايل‌ها در برنامه نظارت داشت (نه فقط اين يك مورد بلكه سراسر برنامه تحت كنترل قرار مي‌گيرد). روش كار به صورت زير است:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
List<string> toFilter = new List<string> { ".aspx", ".asax", ".asp", ".ashx", ".asmx", ".axd", ".master", ".svc" };
if (HttpContext.Current != null && HttpContext.Current.Request != null && HttpContext.Current.Request.Files != null)
for (int i = 0; i < HttpContext.Current.Request.Files.Count; i++)
{
string fileNamePath = HttpContext.Current.Request.Files[i].FileName.ToLower();
string name = Path.GetFileName(fileNamePath);
string ext = Path.GetExtension(fileNamePath);
if (toFilter.Contains(ext) || name == "web.config")
{
HttpContext.Current.Response.StatusCode = 403; //Forbidden
HttpContext.Current.Response.End();
}
}
}
در اين‌جا تمامي فايل‌هاي آپلودي بررسي شده و اگر پسوند خطرناكي داشتند، يك صفحه forbidden به شخص نمايش داده مي‌شود و تمام!

اين كد را به صورت Http module هم مي‌توان درآورد.

۱۳۸۸/۰۳/۱۷

برنامه LINQPad و مثال‌هاي جديد آن


برنامه معروف LINQPad تا كنون به همراه مثال‌هاي كتاب C# 3.0 in a Nutshell به صورت يكپارچه ارائه مي‌شد.
اكنون مثال‌هاي كتاب LINQ in Action نيز قابليت يكپارچگي با اين برنامه را يافته‌اند. به اين صورت بسيار ساده و در همان محيط LINQPad مي‌توان اين مثال‌ها را مرور و اجرا كرد كه در يادگيري LINQ كمك شاياني مي‌نمايند.
براي نصب اين مثال‌هاي يكپارچه جديد، بر روي لينك Download more samples آن كليك كرده و در صفحه‌ي باز شده، بر روي لينكي به نام Download full code listings into LINQPad كليك كنيد.



اكنون مثال‌هاي سي شارپ و VB.Net آن به صورت يكپارچه در اختيار شما خواهند بود.


۱۳۸۸/۰۳/۱۶

ويديوهاي رايگان WCF مخصوص توسعه دهندگان WPF


اخيرا يك سري ويديوي رايگان در سايت codePlex در زمينه WCF منتشر شده‌اند كه از آدرس زير قابل دريافت هستند:




اين ويديوها هر از چندگاهي نيز به روز شده و اضافه مي‌شوند. بنابراين اگر به اين مبحث علاقمنديد، مي‌توانيد مشترك فيد RSS آن پروژه در CodePlex شويد.


۱۳۸۸/۰۳/۱۵

نمايش يك پيغام به كاربر در ASP.Net


عموما در برنامه‌هاي وب مرسوم است كه پيغام به كاربر را در همان لابلاي html صفحه نمايش مي‌دهند. مثلا يك برچسب و سپس تنظيم متن آن در كد برنامه به صورت پويا.
با استفاده از پلاگين‌هاي jQuery اين‌كار را به صورت شكيل‌تري مي‌توان انجام داد. براي مثال:


پلاگين كم حجمي براي اين منظور موجود است به نام jQuery Notice (يكي از چند ده نمونه موجود)
<script type="text/javascript">
$(document).ready(function()
{
jQuery.noticeAdd({
text: 'پيغامي به كاربر',
stay: false
});
});
</script>
كمي اين پلاگين را اصلاح كردم تا مشكل عدم نمايش آن هنگام اسكرول طولاني صفحه در IE حل شود (به صورت پيش فرض با فايرفاكس مشكلي ندارد). براي مثال اين div را در نظر بگيريد:
<div id="myElement" style="position: absolute">This stays at the top</div>
قصد داريم مكان آن‌را در بالاي صفحه ثابت كنيم (حتي با يك اسكرول طولاني مانند تصوير فوق، باز هم همان بالا باقي بماند و قابل مشاهده باشد).
با استفاده از jQuery اين‌كار به صورت زير قابل انجام است:
<script type="text/javascript">
$(document).ready(function()
{
$(window).scroll(function() {
$('#myElement').css('top', $(this).scrollTop() + "px");
});
});
</script>
زمانيكه scroll ايي در window جاري صورت ‌گيرد، div ايي با id مساوي myElement يافت شده و سپس مقدار top آن تنظيم شده و در بالاي صفحه نمايش داده مي‌شود.

ولي اين روش جهت نمايش پيغامي پويا به كاربر مشكل دارد.
نياز است به ازاي هر پيغام پويا يكبار به نحوي اين اسكريپت به صفحه تزريق شود كه روش انجام كار در ASP.Net به صورت زير مي‌تواند باشد:

using System;
using System.Web.UI;
using System.Web;

public class CAddJqueryNotice
{
/// <summary>
/// نمايش يك پيغام بر اساس پلاگين نوتيس
/// </summary>
/// <param name="title">عنوان</param>
/// <param name="msg">پيغام</param>
/// <param name="rtl">راست به چپ؟</param>
/// <param name="duration">مدت زمان نمايش</param>
/// <param name="autoHide">به صورت خودكار بسته شود؟</param>
public static void Show(string title, string msg, bool rtl, int duration, bool autoHide)
{
string scriptBlock
= string.Format(@"<script type=""text/javascript"">
$(document).ready(function() {{
jQuery.noticeAdd({{
text: '<b>{0}</b><br/><div align=left dir={1}>{2}</div>',
stay: {3},
stayTime: {4}
}});
}});
</script>",
title,
(rtl ? "rtl" : "ltr"),
msg,
(autoHide ? "false" : "true"),
duration);

if (HttpContext.Current == null || HttpContext.Current.Handler == null) return;
Page page = HttpContext.Current.Handler as Page;
if (page != null)
page.ClientScript.RegisterStartupScript(
page.GetType(),
"script" + new Guid().ToString("N"),
scriptBlock,
false);
}

}
از آنجائيكه در يك كلاس ديگر خارج از صفحه اصلي مشغول به كار هستيم، دسترسي مستقيم به شيء Page و سپس متد ClientScript.RegisterStartupScript آن جهت تزريق اسكريپت خود به صفحه نداريم. اما با استفاده از HttpContext.Current.Handler مي‌توان به اين مقصود رسيد و مشكل حل مي‌شود.

براي آزمايش آن يك دكمه را در صفحه قرار داده و در روال رخ‌داد گردان كليك آن كد زير را اضافه كنيد:
CAddJqueryNotice.Show( "لطفا دوباره سعي كنيد", "مشكلي رخ داده است", true, 2000, true);

بديهي است قبل از استفاده از كد فوق، بايد چند سطر زير را به هدر master page سايت خود اضافه كنيد:
<script src="jquery-1.3.2.js" type="text/javascript"></script>
<link href="jquery.notice.css" type="text/css" media="screen" rel="stylesheet" />
<script src="jquery.notice.js" type="text/javascript"></script>

۱۳۸۸/۰۳/۱۴

استفاده از thickbox در بلاگر


Thickbox يكي از پلاگين‌هاي jQuery است كه جهت نمايش صفحات modal بكار مي‌رود.

روش استفاده بسيار ساده‌اي هم دارد:
الف) jquery.js بايد به صفحه معرفي شود.
ب) سپس thickbox.js بايد به صفحه الحاق شود.
ج) و فايل css آن يعني thickbox.css نيز بايد به صفحه افزوده شود.

براي استفاده از آن كافي است يك لينك به صفحه اضافه كنيد كه ويژگي class آن مساوي thickbox باشد. مثلا:
<a href="#TB_inline?height=155&width=300&inlineId=hiddenModalContent&modal=true" class="thickbox">Show hidden modal content.</a>
TB_inline و طول و عرض و غيره، جزو خواص استاندارد اين پلاگين است. inlineId جهت معرفي id يك div در صفحه بكار مي‌رود كه قرار است محتويات آن زمانيكه روي اين لينك كليك شد به صورت modal نمايش داده شود.
<a href="iframeModal.html?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=200&width=300&modal=true" title="add a caption to title attribute / or leave blank" class="thickbox">Open iFrame Modal</a>
و يا مانند مثال فوق مي‌تواند يك صفحه خارجي را نيز به صورت modal بارگذاري و نمايش دهد. Title بكارگرفته شده، همان عنوان صفحه Modal ما خواهد بود.
و مثال‌هاي ديگري از اين دست كه در صفحه رسمي آن موجود است و نيازي به تكرار آن‌ها نيست.

اما مشكلي كه در بلاگر وجود دارد اين است كه شما نمي‌توانيد اين ويژگي‌ها را در بسياري از موارد به صورت دستي تنظيم كنيد. يك ويجت ظاهر مي‌شود كه فقط به شما امكان ثبت يك عنوان و لينك مربوطه را مي‌دهد و همين.
براي انتساب ويژگي‌هاي thickBox به اين نوع لينك‌ها كه كنترلي روي آن نيست مي‌توان از خود jQuery كمك گرفت:
$(document).ready(function(){
$("a[href='http://www.mysite.com/page.htm?TB_iframe=true&height=340&width=530']").each(function(){
var obj = $(this);
obj.attr("title","Contact me");
obj.attr("class","thickbox");
}).bind("contextmenu",function(e){
return false;
});
});
در اينجا http://www.mysite.com/page.htm?TB_iframe=true&height=340&width=530 همان صفحه‌اي كه قرار است پس از كليك بر روي لينكي منتسب به آن در صفحه به صورت modal باز شود. با استفاده از جي‌كوئري آن‌را يافته (لينكي كه href آن مساوي مقدار ياد شده است) و سپس ويژگي‌هاي title و class آن را به صورت پويا تنظيم مي‌كنيم تا توسط thickbox قابل شناسايي شود.
همچنين در اينجا كليك راست نيز بر روي اين لينك بسته شده تا كاربر فقط كليك معمولي را انجام دهد (فقط روي همين يك لينك در صفحه اعمال مي‌شود و نه كل صفحه).

۱۳۸۸/۰۳/۱۳

فشرده سازي اطلاعات در SQL server 2008


علاوه بر فشرده سازي خودكار بك آپ‌ها كه پيشتر در مورد آن‌ها صحبت شد، اس كيوال سرور 2008 دو نوع فشرده سازي ديگر را نيز پشتيباني مي‌كند:

Row Compression :

حالت row compression نحوه‌ي ذخيره سازي فيزيكي داده‌ها را تغيير مي‌دهد. فعال سازي آن اثرات زير را خواهد داشت:
الف) متاديتاي هر ركورد را حداقل مي‌كند (منظور از متاديتا اطلاعاتي مانند اطلاعات ستون‌ها، طول و آفست و غيره است)
ب) داده‌هاي عددي و رشته‌هايي با طول ثابت، به صورت اطلاعاتي با طول متغير ذخيره خواهند شد، درست مانند varchar ها.

براي ايجاد جدولي كه row compression در آن به صورت پيش‌فرض فعال است، مي‌توان مانند مثال زير عمل كرد:
CREATE TABLE MyTable
(
ID int identity Primary key,
Name char(100),
Email char(100)
)
WITH (DATA_COMPRESSION = Row);

GO
و اگر جدول موجودي را مي‌خواهيد تغيير داده و اين خاصيت را بر روي آن فعال نمائيد، روش زير را اعمال كنيد:
Alter TABLE MyTable REBUILD WITH (DATA_COMPRESSION=Row, MAXDOP=2);
در اينجا MAXDOP مشخص مي‌كند كه از چند CPU بايد براي فشرده سازي استفاده شود. (اگر جدولي حجيم داريد، به اين صورت مي‌توان عمليات فشرده سازي را سريعتر به پايان رساند)


Page Compression :

در روش دوم فشرده سازي اطلاعات در اس‌كيوال سرور 2008 ، كه مهم‌ترين حالت موجود نيز مي‌باشد، اطلاعات مشترك، بين سطرهاي يك صفحه به اشتراك گذاشته مي‌شوند. اين روش از فناوري‌هاي زير استفاده مي‌كند:
الف) روش row compression كه در مورد آن صحبت شد جزئي از اين روش است.
ب) Prefix Compression : به ازاي هر ستون در يك صفحه، Prefix هاي تكراري يافت شده و در هدر مخصوص فشرده سازي ذخيره مي‌شوند (محل اين هدر پس از هدر صفحه است). سپس هرجايي كه به اين Prefix ها اشاره شده‌باشد، عدد منحصربفرد شناسايي كننده آن‌ها نسبت داده مي‌شود.
ج) Dictionary Compression : در اين حالت مقادير تكراري يك صفحه جستجو شده و در هدر فشرده سازي صفحه ذخيره مي‌شوند. حالت Prefix Compression فقط به يك ستون منحصر مي‌شود اما Dictionary Compression به كل صفحه اعمال مي‌گردد.

براي فعال سازي آن در يك جدول جديد به روش زير مي‌توان عمل نمود:
CREATE TABLE MyTable
(
ID int identity Primary key,
Name char(100),
Email char(100)
)
WITH (DATA_COMPRESSION = Page);
و براي اعمال آن به جدولي موجود از روش زير مي‌توان استفاده كرد:

Alter TABLE MyTable REBUILD WITH (DATA_COMPRESSION=Page, MAXDOP=2);
يك سري رويه‌هاي ذخيره شده سيستمي جديد نيز براي محاسبه حجم جداول، پيش و پس از فشرده سازي (بدون فشرده سازي واقعي) نيز در اين نگارش گنجانده شده‌اند كه به شرح زير هستند:
-- بررسي اينكه چه ميزان فضا با اعمال فشرده سازي صفحات قابل صرفه جويي خواهد بود
EXEC sp_estimate_data_compression_savings 'schemaname', 'TableName', NULL, NULL, 'PAGE';

-- بررسي اينكه چه ميزان فضا با اعمال فشرده سازي رديف‌ها قابل صرفه جويي خواهد بود
EXEC sp_estimate_data_compression_savings 'schemaname', 'TableName', NULL, NULL, 'ROW';

بنابراين قبل از اينكه فشرده سازي را فعال نمائيد، ابتدا بررسي كنيد آيا واقعا ميزان قابل توجهي اطلاعات فشرده خواهند شد و نتيجه حاصل رضايت بخش است يا خير. همچنين بايد درنظر داشت كه جداول و يا ايندكس‌هايي كه read و write بالايي دارند براي اين منظور مناسب نيستند. براي يافتن آن‌ها كوئري زير را اجرا كنيد:

USE dbName;
SELECT objectname = OBJECT_NAME(s.object_id),
indexname = i.name,
i.index_id,
reads = range_scan_count + singleton_lookup_count,
'leaf_writes' = leaf_insert_count + leaf_update_count + leaf_delete_count,
'leaf_page_splits' = leaf_allocation_count,
'nonleaf_writes' = nonleaf_insert_count + nonleaf_update_count +
nonleaf_delete_count,
'nonleaf_page_splits' = nonleaf_allocation_count
FROM sys.dm_db_index_operational_stats (DB_ID(), NULL, NULL, NULL) AS s
INNER JOIN sys.indexes AS i
ON i.object_id = s.object_id
WHERE OBJECTPROPERTY(s.object_id, 'IsUserTable') = 1
AND i.index_id = s.index_id
ORDER BY
leaf_writes DESC,
nonleaf_writes DESC

و جهت تكميل مبحث مي‌توان به مقاله بسيار جامع زير كه اخيرا توسط مايكروسافت منتشر شده است رجوع نمود:



۱۳۸۸/۰۳/۱۱

پرسش و پاسخ‌هاي متداول ايجاد يك وبلاگ بلاگري

هر از چندگاهي دوستان پيغام مي‌گذارند كه چگونه تاريخ وبلاگم را فارسي كنم يا يك قالب فارسي خوب را از كجا مي‌شود تهيه كرد و امثال آن. تمام اين‌ها را به صورت يك FAQ كوچك در اينجا قرار مي‌دهم تا براي عموم علاقمندان قابل استفاده باشد.

پرسش پاسخ
براي ايجاد يك وبلاگ بلاگري از كجا شروع كنم؟ با داشتن يك اكانت جي ميل، به آدرس زير مراجعه كرده و هر تعداد كه مايل بوديد مي‌توانيد وبلاگ ايجاد نمائيد:
قالب‌هاي پيش فرض گوگل چنگي به دل نمي‌زنند و بود و نبود آن‌ها احساس نمي‌شود! چه بايد كرد؟ براي تهيه قالب‌هاي فارسي به آدرس زير مراجعه نمائيد:
تاريخ فارسي را چه كنم؟ روش دوستان ، روش من
برنامه نويسم! كدهاي من يا نمايش داده نمي‌شود يا فرمت آن‌ها هنگام ارسال به هم مي‌ريزد. چه بايد كرد؟ روش مورد علاقه‌ي من ، روش مايكروسافت (+ و + و افزونه‌اي براي اين‌كار)
آخرين نظرات كاربران سايت را چگونه در ستون كناري سايت نمايش دهم؟ يكي از ويجت‌هاي پركاربرد گوگل در بلاگر، ويجت فيد است. هر بلاگ داراي دو فيد مطالب و نظرات است. ويجت فيد را اضافه كرده و سپس آدرس فيد نظرات سايت خود را به آن معرفي كنيد. هميشه آخرين 5 نظر ارسالي را نمايش مي‌دهد. اين ويجت كاربردهاي قابل توجهي مي‌تواند داشته باشد.
آمار مراجعان به سايت را بايد در كجا ملاحظه كرد؟ جاي پيش فرضي وجود ندارد! يك اكانت Analytics براي خود تهيه كرده و آن‌را به سايت اضافه كنيد. همچنين پس از آن يك اكانت فيد برنر را نيز براي خود تهيه كنيد. فيدبرنر اكنون جزيي از گوگل است و پس از معرفي آدرس فيد سايت خود به آن، يك آدرس جديد به همراه آيكوني براي نمايش در سايت به شما مي‌دهد كه مي‌توانيد تگ‌هاي آن تصوير ‌را توسط ويجت html نمايش دهيد. همچنين از همين طريق نيز مي‌توان اشتراك از طريق ايميل را به وبلاگ اضافه كرد.
كامنت‌هاي سايت من در بيرون از سايت باز مي‌شوند. چرا؟ به اين مطلب مراجعه نمائيد:
چگونه براي بلاگ خود قسمت ارسال نظرات را تهيه نمايم؟ من از سرويس فرم ساز Zoho‌ استفاده مي‌كنم كه در سال 2008 جزو برترين‌هاي وب شناخته شده بود. بعد از ايجاد فرم خود و دريافت كد مربوطه، يك مطلب جديد را ارسال كنيد و در بدنه‌ي آن ، كدي را كه Zoho به شما ارائه مي‌دهد قرار دهيد. سپس لينك اين مطلب را توسط يك ويجت html به كنار سايت اضافه كنيد تا هميشه در دسترس باشد.