۱۳۸۷/۱۱/۱۲

سازگار كردن GridView با افزونه‌هاي jQuery



افزونه‌ها/پلاگين‌هاي زيادي جهت كار با table استاندارد HTML وجود دارند و خروجي رندر شده‌ي يك ASP.Net GridView هم در نهايت يك جدول است. فرض كنيد قصد داريم افزونه زير را به GridView استاندارد ASP.Net اعمال كنيم.
jQuery quickSearch plug-in

ظاهرا بدون مشكل خاصي اعمال مي‌گردد. براي مثال در هدر صفحه داريم: (شبيه به مثال موجود در سايت اصلي آن، جهت اعمال به GridView1)

<script src="jquery.min.js" type="text/javascript"></script>
<script src="jquery.quicksearch.js" type="text/javascript"></script>

<script type="text/javascript">
$(document).ready(function() {
//جستجو در جدول
$('table#<%=GridView1.ClientID %> tbody tr').quicksearch({
position: 'before',
attached: 'span#attachSearch',
labelText: 'جستجو',
isFieldset: true,
loaderText: ' ... ',
fixWidths: true
});
});
</script>

براي اعمال بر:
(در اينجا محل قرارگيري تكست باكس مربوط به جستجو، در span ايي با id مساوي attachSearch تنظيم شده است، مي‌توانيد از ID خود GridView هم استفاده كنيد.)

<span id="attachSearch"></span>
<br />
<asp:GridView ID="GridView1" runat="server"></asp:GridView>

نكته:
1- همانطور كه در مقاله مربوط به ClientID ذكر شد، هيچ الزامي ندارد كه ID‌ مربوط به GridView‌ شما براي مثال دقيقا همان GridView1 جهت استفاده در سمت كلاينت باشد و بسته به container آن، اين نام تركيبي از ID شيء(هاي) در بر گيرنده و شيء مورد نظر مي‌باشد. به همين جهت از GridView1.ClientID استفاده گرديد تا اسكريپت ما با آن مشكلي نداشته باشد.

2- خصوصيات ظاهري افزونه فوق از سلكتور quicksearch فايل css شما دريافت مي‌شوند. براي مثال:
.quicksearch
{
width:190px;
}

مشكل!
پس از هر بار جستجو، header مربوط به GridView محو مي‌شود، اما نمونه موجود در سايت اصلي افزونه، اين مشكل را ندارد. چرا؟!
GridView‌ مربوط به ASP.Net پس از رندر شدن، جدولي است كه تگ‌هاي thead را ندارد. اگر به سورس صفحه سايت افزونه دقت نمائيد، هدر جدول با تگ‌هاي thead محصور شده است اما GridView استاندارد ASP.Net به صورت پيش فرض اين‌كار را انجام نمي‌دهد و خروجي آن چيزي شبيه به جدول زير است: (هدر با th مشخص مي‌شود و از تگ thead خبري نيست)

<table >
<tr >
<th scope="col">col1</th>
<th scope="col">col2</th>
<th scope="col">col3</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
.
.
.

حداقل دو راه حل براي رفع اين مشكل وجود دارد:
الف) راه حل سمت سرور
براي اضافه كردن thead بايد كمي كد نويسي كرد. پس از اينكه گريد شما بايند شد، چند سطر زير را اضافه كنيد:

//سازگار با افزونه‌هاي جي كوئري
if (GridView1.Rows.Count > 0)
{
//This replaces <td> with <th> and adds the scope attribute
GridView1.UseAccessibleHeader = true;

//This will add the <thead> and <tbody> elements
GridView1.HeaderRow.TableSection = TableRowSection.TableHeader;

//This adds the <tfoot> element.
//Remove if you don't have a footer row
//GridView1.FooterRow.TableSection = TableRowSection.TableFooter;
}

ب)راه حل سمت كلاينت
سطر مربوط به جستجو را به صورت زير هم مي‌توان نوشت:

$('table#<%=GridView1.ClientID %> tr:has(td)').quicksearch({

در اينجا به دنبال هرچي tr كه td دارد مي‌گرديم. به صورت پيش فرض در tr مربوط به هدر گريد، ما th داريم و نه td ، بنابراين مشكل محو شدن هدر به اين صورت حل خواهد شد.

نكته:
اگر مي‌خواهيد كه ناحيه مربوط به جستجوي افزونه فوق در پرينت صفحه ظاهر نشود به css صفحه چند سطر زير را اضافه كنيد:

@media print
{
.quicksearch
{
display: none;
}
}


تمرين!
افزونه جي كوئري زير را به يك ASP.Net GridView اعمال كنيد:
table sorter

۱۳۸۷/۱۱/۱۱

مشكل IIS6 و دريافت فايل‌هاي آفيس 2007


IIS6 فايل‌هايي را كه نشناسد، سرو نخواهد كرد. بنابراين اگر يكي از كاربران مثلا يك فايل docx آفيس 2007 را آپلود كرده باشد، به محض كليك بر روي لينك دريافت فايل، با خطاي زير متوقف خواهد شد:

HTTP Error 404 - File or directory not found

فايل بر روي سرور موجود است اما كاربر قادر به دريافت آن نيست.

براي شناساندن فرمت‌هاي جديد به IIS6 مي‌توان به يكي از دو روش زير عمل كرد:
الف) اضافه كردن mime-type جديد از طريق كنسول IIS
ب) ويرايش كردن فايل MetaBase.xml مربوط به IIS

در هر دو روش فوق نياز است تا با mime-type فايل‌هاي جديد آشنا بود. براي مثال ليست كامل mime-types مربوط به فايل‌هاي آفيس 2007 به صورت زير است:

.docm,application/vnd.ms-word.document.macroEnabled.12
.docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document
.dotm,application/vnd.ms-word.template.macroEnabled.12
.dotx,application/vnd.openxmlformats-officedocument.wordprocessingml.template
.potm,application/vnd.ms-powerpoint.template.macroEnabled.12
.potx,application/vnd.openxmlformats-officedocument.presentationml.template
.ppam,application/vnd.ms-powerpoint.addin.macroEnabled.12
.ppsm,application/vnd.ms-powerpoint.slideshow.macroEnabled.12
.ppsx,application/vnd.openxmlformats-officedocument.presentationml.slideshow
.pptm,application/vnd.ms-powerpoint.presentation.macroEnabled.12
.pptx,application/vnd.openxmlformats-officedocument.presentationml.presentation
.xlam,application/vnd.ms-excel.addin.macroEnabled.12
.xlsb,application/vnd.ms-excel.sheet.binary.macroEnabled.12
.xlsm,application/vnd.ms-excel.sheet.macroEnabled.12
.xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.xltm,application/vnd.ms-excel.template.macroEnabled.12
.xltx,application/vnd.openxmlformats-officedocument.spreadsheetml.template

روش ب)
ابتدا IIS6 را stop كنيد (در غير اينصورت قادر به ذخيره سازي تغييرات نخواهيد بود):
iisreset /stop
سپس فايل متابيس آن‌را در يك اديتور متني باز كنيد. اين فايل در آدرس زير قرار دارد:
C:\WINDOWS\system32\inetsrv\MetaBase.xml

تگ مربوط به IIsMimeMap را يافته و خطوط فوق را دقيقا به همين صورتيكه ملاحظه مي‌كنيد به آن اضافه نمائيد.



و در آخر IIS را راه اندازي كنيد:
iisreset /start

روش الف)
اين روش نيازي به stop و start وب سرور ندارد و به محض اضافه شدن، به صورت خودكار اعمال خواهد شد اما كمي طولاني‌تر است:
كنسول IIS را باز كنيد
بر روي web sites كليك راست كنيد. (منظور بالاترين سطح ممكن است)
گزينه properties‌ را انتخاب كرده و سپس به برگه http headers‌ مراجعه نمائيد.
در اينجا بر روي دكمه mime-types كليك كرده و در صفحه باز شده بايد تك تك موارد جديد را به صورت دستي وارد نمائيد (در اينجا نيازي به ذكر نقطه مربوط به پسوند فايل نيست)



لازم به ذكر است كه اين نوع mime-types به IIS7 اضافه شده‌اند.

۱۳۸۷/۱۱/۱۰

لينك‌هاي هفته‌ي دوم بهمن


وبلاگ‌ها ، سايت‌ها و مقالات ايراني (داخل و خارج از ايران)

ASP. Net

طراحي و توسعه وب

PHP

سي شارپ

عمومي دات نت

ويندوز
(ايكاش بجاي تمام اين‌كارها يك سيستم ساده‌تر توسعه‌ي پلاگين براي آن طراحي مي‌كردند ... يا به عبارتي يكي از مهم‌ترين دليل‌هاي اقبال مردم به فايرفاكس را به صورت بسيار كم رنگي دارد)


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

متفرقه

۱۳۸۷/۱۱/۰۹

مجموعه آموزشي رايگان workflow foundation از مايكروسافت

Intro to Windows Workflow Foundation (Part 1 of 7): Workflow in Windows Applications (Level 100)
This webcast is a code-focused introduction to developing workflow-enabled Microsoft Windows platform applications. We cover the basics of developing, designing, and debugging workflow solutions. Gain the knowledge and insight you need to be confident choosing workflow for everyday applications.


Intro to Windows Workflow Foundation (Part 2 of 7): Simple Human Workflow Using E-mail (Level 200)
Have you thought about how you might apply the workflow concept to e-mail? In this webcast New Zealand based regional director, Chris Auld, leads attendees through a simple worked example of the use of SMTP e-mail as part of a workflow solution. Chris demonstrates how to create custom activities to query Active Directory to retrieve user data, send e-mail, and wait for e-mail responses to continue the workflow process. This code-intensive session gives users taking their first steps with workflow a good grounding in some of the key extensibility concepts.


Intro to Windows Workflow Foundation (Part 3 of 7): Hosting and Communications Options in Workflow Scenarios (Level 300)
The session looks at options for hosting workflow applications. We cover managing events, instance tracking, and persistence, and provide a close look at the simple communications mechanisms that are available for you to use in your workflow applications.


Intro to Windows Workflow Foundation (Part 4 of 7): Workflow, Messaging, and Services: Developing Distributed Applications with Workflows (Level 300)
Web service technologies have typically taken a "do-it-yourself" approach to maintaining the interoperation state of services. Using workflow, developers now have tools that allow them to describe the long-running state of their services and delegate much of the state management to the underlying platform. Managing this state correctly becomes even more challenging in applications that coordinate work across multiple services either within an organization or at an Internet scale. This session looks at how developers who use either Microsoft ASMX or Microsoft's framework for building service-oriented applications, code-named "Indigo", can create workflow-oriented applications that are both faster to write and more manageable and flexible once deployed.


Intro to Windows Workflow Foundation (Part 5 of 7): Developing Event Driven State Machine Workflows (Level 300)
State machines used to be something that you had to first draw on paper and then implement in code. This session shows how to use technologies to create event-driven workflows and how to apply this to a typical programming problem. We introduce the concept of a flexible process and show how this can help with modeling real-world processes using state and sequential workflow. Plenty of coding is included to illustrate how you can seamlessly merge state machine design and your code.


Intro to Windows Workflow Foundation (Part 6 of 7): Extending Workflow Capabilities with Custom Activities (Level 300)
It is helpful to think of activities as controls within a workflow, similar to controls used with Microsoft ASP.NET Pages or Microsoft Windows Forms. You can use activities to encapsulate execution logic, communicate with the host and decompose a workflow into reusable components. This session examines the simple process of creating custom activities. If you want to expose activities to other developers designing workflows, you are likely to find this session valuable.


Intro to Windows Workflow Foundation (Part 7 of 7): Developing Rules Driven Workflows (Level 300)
Rules can be a powerful business tool when combined with workflow. In this session, learn how to develop more advanced activities that support the modeling of rich business behavior such as human workflow. Understand when to use rules for business logic, and see how rule policies allow for the description of sophisticated behavior in an integrated and flexible way. This session gives you an interesting insight into the power of using workflow at the core of a line of business application.

۱۳۸۷/۱۱/۰۸

پردازش فايل‌هاي XML با استفاده از jQuery


فرض كنيد مثال دريافت اطلاعات API فيدبرنر را بخواهيم با استفاده از jQuery پياده سازي كنيم، يعني امكان برنامه نويسي سمت سرور را نداريم و مي‌خواهيم با استفاده از جاوا اسكريپت، تعداد مشتركين فيد يك سايت را نمايش دهيم.
براي مثال آدرس دريافت اطلاعات مربوط به API فيدبرنر وبلاگ جاري به صورت زير است:

و در حالت كلي :
http://api.feedburner.com/awareness/1.0/GetFeedData?uri=<feeduri>

كه حاصل آن براي مثال يك فايل XML با فرمت زير مي‌باشد:

<rsp stat="ok">
<feed id="fhphjt61bueu08k93ehujpu234" uri="vahidnasiri">
<entry date="2009-01-23" circulation="153" hits="276" reach="10"/>
</feed>
</rsp>

همانطور كه مطلع هستيد چند روزي است كه jQuery 1.3.1 ارائه شده است. جهت استفاده از آخرين نگارش موجود آن تا اين زمان، مي‌توان از گوگل به عنوان هاست اين كتابخانه به صورت زير استفاده كرد:

<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js' type='text/javascript'></script>

نحوه خواندن مقدار circulation فايل xml ذخيره شده بر روي كامپيوتر:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>FeedBurner API</title>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js' type='text/javascript'>
</script>
<script type="text/javascript">
function parseXml(xml){
//find every entry and print the circulation
$(xml).find("entry").each(function(){
$("#output").append($(this).attr("circulation"));
});
}

$(document).ready(function(){
$.ajax({
type: "GET",
url: "GetFeedData_local.xml",
dataType: "xml",
success: parseXml
});
});
</script>
</head>
<body>
<div dir="rtl" style="font-family:tahoma; font-size:12px;">
تعداد مشتركين تغذيه خبري سايت:
<div id="output">
</div>
</div>
</body>
</html>

با استفاده از قابليت Ajax كتابخانه jQuery ، اطلاعات فايل محلي GetFeedData_local.xml دريافت شده و محتواي آن به تابع parseXml پاس مي‌شود (توسط قسمت success). سپس در اين تابع تمام تگ‌هاي entry يافت شده و مقدار circulation آن‌ها به يك div با ID معادل output اضافه مي‌شود.
مثال فوق در مورد خواندن اطلاعات از يك فايل xml مي‌تواند براي مثال اين كاربرد را در يك سايت داشته باشد:
نمايش اتفاقي سخن روز يا سخن بزرگان و امثال آن بدون برنامه نويسي سمت سرور جهت انجام اين كار از يك فايل xml تهيه شده، بدون نياز به استفاده از ديتابيس خاصي.

تا اينجاي كار مشكلي نيست. اما همانطور كه در مطلب مقابله با حملات CSRF نيز ذكر شد، مرورگرهاي جديد امكان ارسال يا دريافت اطلاعات به صورت Ajax را بين سايت‌ها ممنوع كرده‌اند (ماجرا هم از آنجا شروع شد كه يكبار جي‌ميل اين باگ امنيتي را داشته است). بنابراين اگر شما بجاي url قسمت Ajax فوق، آدرس سايت فيد برنر را قرار دهيد با خطاي زير متوقف خواهيد شد:

Access to restricted URI denied

تمام موارد ديگري هم كه در jQuery براي دريافت اطلاعات از يك فايل يا url موجود است (مثلا تابع load يا get و امثال آن) فقط به سايت جاري و دومين جاري بايد ختم شوند در غير اينصورت توسط مرورگرهاي جديد متوقف خواهند شد.

۱۳۸۷/۱۱/۰۷

تعيين اعتبار يك GUID در دات نت


GUID يا Globally unique identifier يك عدد صحيح 128 بيتي است (بنابراين 2 به توان 128 حالت را مي‌توان براي آن درنظر گرفت). از لحاظ آماري توليد دو GUID يكسان تقريبا صفر مي‌باشد. به همين جهت از آن با اطمينان مي‌توان به عنوان يك شناسه منحصربفرد استفاده كرد. براي مثال اگر به لينك‌هاي دانلود فايل‌ها از سايت مايكروسافت دقت كنيد، اين نوع GUID ها را به وفور مي‌توانيد ملاحظه نمائيد. يا زمانيكه قرار است فايلي را كه بر روي سرور آپلود شده، ذخيره نمائيم، مي‌توان نام آن‌را يك GUID درنظر گرفت بدون اينكه نگران باشيم آيا فايل آپلود شده بر روي يكي از فايل‌هاي موجود overwrite مي‌شود يا خير. يا مثلا استفاده از آن در سناريوي بازيابي كلمه عبور در يك سايت. هنگاميكه كاربري درخواست بازيابي كلمه عبور فراموش شده خود را داد، يك GUID براي آن توليد كرده و به او ايميل مي‌زنيم و در آخر آن‌را در كوئري استرينگي دريافت كرده و با مقدار موجود در ديتابيس مقايسه مي‌كنيم. مطمئن هستيم كه اين عبارت قابل حدس زدن نيست و همچنين يكتا است.

براي توليد GUID ها در دات نت مي‌توان مانند مثال زير عمل كرد و خروجي‌هاي دلخواهي را با فرمت‌هاي مختلفي دريافت كرد:

System.Guid.NewGuid().ToString() = 81276701-9dd7-42e9-b128-81c762a172ff
System.Guid.NewGuid().ToString("N") = 489ecfc61ee7403988efe8546806c6a2
System.Guid.NewGuid().ToString("D") = 119201d9-84d9-4126-b93f-be6576eedbfd
System.Guid.NewGuid().ToString("B") = {fd508d4b-cbaf-4f1c-894c-810169b1d20c}
System.Guid.NewGuid().ToString("P") = (eee1fe00-7e63-4632-a290-516bfc457f42)

تمام اين‌ها خيلي هم خوب! اما همان سناريوي مشخص ساختن يك فايل با GUID و يا بازيابي كلمه عبور فراموش شده را درنظر بگيريد. يكي از اصول امنيتي مهم، تعيين اعتبار ورودي كاربر است. چگونه بايد يك GUID را به صورت مؤثري تعيين اعتبار كرد و مطمئن شد كه كاربر از اين راه قصد تزريق اس كيوال را ندارد؟
دو روش براي انجام اينكار وجود دارد
الف) عبارت دريافت شده را به new Guid پاس كنيم. اگر ورودي غيرمعتبر باشد، يك exception توليد خواهد شد.
ب) استفاده از regular expressions جهت بررسي الگوي عبارت وارد شده

پياده سازي اين دو را در كلاس زير مي‌توان ملاحظه نمود:
using System;
using System.Text.RegularExpressions;

namespace sample
{
/// <summary>
/// بررسي اعتبار يك گوئيد
/// </summary>
public static class CValidGUID
{
/// <summary>
/// بررسي تعيين اعتبار ورودي
/// </summary>
/// <param name="guidString">ورودي</param>
/// <returns></returns>
public static bool IsGuid(this string guidString)
{
if (string.IsNullOrEmpty(guidString)) return false;

bool bResult;
try
{
Guid g = new Guid(guidString);
bResult = true;
}
catch
{
bResult = false;
}

return bResult;
}

/// <summary>
/// بررسي تعيين اعتبار ورودي
/// </summary>
/// <param name="input">ورودي</param>
/// <returns></returns>
public static bool IsValidGUID(this string input)
{
return !string.IsNullOrEmpty(input) &&
new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$").IsMatch(input);
}
}

}

سؤال: آيا متدهاي فوق ( extension methods ) درست كار مي‌كنند و واقعا نياز ما را برآورده خواهند ساخت؟ به همين منظور، آزمايش واحد آن‌ها را نيز تهيه خواهيم كرد:

using NUnit.Framework;
using sample;

namespace TestLibrary
{
[TestFixture]
public class TestCValidGUID
{

/*******************************************************************************/
[Test]
public void TestIsGuid1()
{
Assert.IsTrue("81276701-9dd7-42e9-b128-81c762a172ff".IsGuid());
}

[Test]
public void TestIsGuid2()
{
Assert.IsTrue("489ecfc61ee7403988efe8546806c6a2".IsGuid());
}

[Test]
public void TestIsGuid3()
{
Assert.IsTrue("{fd508d4b-cbaf-4f1c-894c-810169b1d20c}".IsGuid());
}

[Test]
public void TestIsGuid4()
{
Assert.IsTrue("(eee1fe00-7e63-4632-a290-516bfc457f42)".IsGuid());
}

[Test]
public void TestIsGuid5()
{
Assert.IsFalse("81276701;9dd7;42e9-b128-81c762a172ff".IsGuid());
}


/*******************************************************************************/
[Test]
public void TestIsValidGUID1()
{
Assert.IsTrue("81276701-9dd7-42e9-b128-81c762a172ff".IsValidGUID());
}

[Test]
public void TestIsValidGUID2()
{
Assert.IsTrue("489ecfc61ee7403988efe8546806c6a2".IsValidGUID());
}

[Test]
public void TestIsValidGUID3()
{
Assert.IsTrue("{fd508d4b-cbaf-4f1c-894c-810169b1d20c}".IsValidGUID());
}

[Test]
public void TestIsValidGUID4()
{
Assert.IsTrue("(eee1fe00-7e63-4632-a290-516bfc457f42)".IsValidGUID());
}

[Test]
public void TestIsValidGUID5()
{
Assert.IsFalse("81276701;9dd7;42e9-b128-81c762a172ff".IsValidGUID());
}
}

}

نتيجه اين آزمايش به صورت زير است:



همانطور كه ملاحظه مي‌كنيد حالت دوم يعني استفاده از عبارات باقاعده دو حالت را نمي‌تواند بررسي كند (مطابق الگوي بكار گرفته شده كه البته قابل اصلاح است)، اما روش معمولي استفاده از new Guid ، تمام فرمت‌هاي توليد شده توسط دات نت را پوشش مي‌دهد.


۱۳۸۷/۱۱/۰۶

تنظيمات پيشنهادي حداكثر حافظه‌ي مصرفي اس كيوال سرور


به صورت پيش فرض تنظيمات حافظه‌ي اس كيوال سرور به صورتي است كه به آن اجازه مي‌دهد تمامي حافظه‌ي مهياي سيستم عامل را مصرف كند! اگر شخصي با اين مساله آشنايي نداشته باشد احتمالا تصور خواهد كرد كه اس كيوال سرور نشتي حافظه دارد يا كلا مشكلي در سيستم روي داده است كه تا اين حد مصرف حافظه بالا رفته است.
براي مشاهده‌ي اين تنظيمات روي instance سرور مورد نظر كليك راست كرده و گزينه خواص را انتخاب كنيد. سپس در صفحه‌ي باز شده گزينه memory را مشاهده نمائيد.
البته اين‌كار را با استفاده از دستورات T-SQL هم مي‌توان انجام داد:

EXEC sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE

EXEC sp_configure 'max server memory (MB)'

EXEC sp_configure 'show advanced options', 0
RECONFIGURE WITH OVERRIDE

نتيجه‌ي آن بر روي سيستم برنامه نويسي من به صورت زير است:



كه البته عمدا آن‌را بر روي يك گيگ تنظيم كرده‌ام تا عملكرد سيستم مختل نشود. (چون اگر غير از اين باشد، تعارفي نداشته و هر آنچه را كه صلاح بداند مصرف مي‌كند!)
كمي در بلاگ‌هاي رسمي برنامه نويس‌هاي اس كيوال سرور در سايت MSDN در اين‌‌باره جستجو كردم و نتيجه آن به صورت زير است:

تنظيمات حداكثر حافظه‌ي مصرفي اس كيوال سرورهاي 2005 و 2008
براي يك سيستم عامل 64 بيتي:

Physical RAM MaxMem Setting
2GB 1500
4GB 3200
6GB 4800
8GB 6700
12GB 10600
16GB 14500
24GB 22400
32GB 30000
48GB 45000
64GB 59000


براي سروري 32 بيتي اين اعداد حداكثر را تقريبا منهاي 300 مگابايت نمائيد. (و البته همانطور كه مطلع هستيد در سيستم عامل‌هاي سرور 32 بيتي، اگر بيشتر از 2 گيگا بايت رم داشتيد سوئيچ 3GB و اگر بيشتر از 4 گيگابايت رم مهيا بود، سوئيچ PAE بايد در boot.ini تنظيم شوند. در غير اينصورت هزينه‌ي سخت افزاري بيهوده‌اي را متحمل شده‌ايد، زيرا استفاده‌ي بهينه‌اي از آن در يك سيستم عامل 32 بيتي نخواهد شد)

و اين اعداد را همانطور كه ذكر شد، در تنظيمات سرور مي‌توان وارد نمود ( از طريق management studio ) و يا با استفاده از دستورات T-SQL نيز اين امر ميسر است: (در مثال زير حداكثر حافظه مجاز مصرفي به 2300 مگابايت تنظيم مي‌شود)

EXEC sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE

EXEC sp_configure 'max server memory (MB)', 2300

EXEC sp_configure 'show advanced options', 0
RECONFIGURE WITH OVERRIDE

و البته لازم به ذكر است كه اعداد فوق براي حالتي پيشنهاد شده است كه سرور مورد نظر فقط يك كار و آن‌هم اجرا و سرويس دهي اس كيوال سرور را به عهده داشته باشد. بديهي است اگر از اين سرور استفاده‌هاي ديگري هم مي‌شود اين اعداد را بايد كمتر نيز در نظر گرفت.


براي مطالعه‌ي بيشتر
http://sqlnerd.blogspot.com/2006/07/memory-use-in-sql-server.html
http://blogs.msdn.com/axperf/archive/2008/03/10/welcome-database-configuration-checklist-part-1.aspx
http://technet.microsoft.com/en-us/library/bb124810.aspx

۱۳۸۷/۱۱/۰۵

خواندن اطلاعات API فيدبرنر


مطلبي را در سايت راديكال 2 در مورد نمايش تعداد خواننده يك فيد ديدم كه پياده سازي آن با سي شارپ و xml serialization به صورت زير است:

using System;
using System.Xml;
using System.Xml.Serialization;

namespace Test
{
/// <summary>
/// كلاسي جهت نمايش تعداد خواننده فيد وبلاگ شما
/// <example>CFeedBurner data = new CFeedBurner { FeedID = "fhphjt61bueu08k93ehujpu234" };
/// MessageBox.Show(data.Circulation().ToString());</example>
/// </summary>
class CFeedBurner
{
/// <summary>
/// آي دي فيد شما زمانيكه به فيد برنر لاگين كرده‌ايد در تايتل صفحه مربوطه
/// </summary>
public string FeedID { get; set; }

/// <summary>
/// نگاشت فيد به يك كلاس
/// </summary>
/// <returns>كلاس متناظر با فيد</returns>
/// <exception cref="Exception">لطفا شماره شناسايي فيد را وارد كنيد</exception>
rsp deserializeFromXML()
{
if (FeedID == null)
throw new Exception("لطفا شماره شناسايي فيد را وارد كنيد");

XmlSerializer deserializer =
new XmlSerializer(typeof(rsp));
using (XmlReader reader = XmlReader.Create(
string.Format("https://feedburner.google.com/api/awareness/1.0/GetFeedData?id={0}", FeedID)))
{
return (rsp)deserializer.Deserialize(reader);
}
}

/// <summary>
/// دريافت تعداد خواننده فيد
/// </summary>
/// <returns>آمار فيد</returns>
/// <exception cref="Exception">اطلاعات فيد شما قابل دريافت نيست</exception>
public int Circulation()
{
rsp data = deserializeFromXML();
if (data == null || data.feed == null || data.feed.Length == 0)
throw new Exception("اطلاعات فيد شما قابل دريافت نيست");

if (data.feed[0].entry == null || data.feed[0].entry.Length == 0)
throw new Exception("اطلاعات فيد شما قابل پردازش نيست");

return int.Parse(data.feed[0].entry[0].circulation);
}
}
}

كلاس rsp از فايل xml فيد استاندارد سايت فيدبرنر درست شده است. روش توليد آن‌را قبلا توضيح داده بودم. به سادگي اجراي دو سطر زير است:

xsd.exe GetFeedData.xml
xsd.exe GetFeedData.xsd /c

دريافت فايل‌هاي كلاس‌هاي نامبرده شده.

۱۳۸۷/۱۱/۰۴

ويديوهاي رايگان آموزش ساخت workflow براي SharePoint 2007


يك سري ويديوي رايگان ايجاد و همچنين برنامه نويسي workflow هاي SharePoint 2007 در سايت آقاي shelton موجود است كه متاسفانه اين سايت با اينترنت داتك باز نمي‌شود (يا ازون طرف يا از اين طرف فيلتر شده! يا مشكل DNS اينترنت داتك است، نمي‌دونم).
براي راحتي دريافت آن‌ها يك mirror از اين ويديوها ايجاد شد:

Enabling incoming/outgoing email for MOSS 2007, download

Extracting Document Details with SharePoint Workflow's, download

Extracting email addresses & Sending emails with SharePoint Workflow, download

Programmatically creating user tasks with SharePoint Workflow, download

Programmatically escalating Overdue Tasks , download

Building Basic Approval Workflow, download

Building a Multilevel Approval Workflow, download

Using Active Directory Searching/Lookup in a SharePoint/MOSS 2007 Workflow, download

همچنين يك سري ويديوي آموزشي رايگان ديگر نيز در مورد workflow foundation در اين آدرس قابل دريافت است.

۱۳۸۷/۱۱/۰۳

لينك‌هاي هفته‌ي اول بهمن


وبلاگ‌ها ، سايت‌ها و مقالات ايراني (داخل و خارج از ايران)

Visual Studio


ASP. Net


طراحي و توسعه وب


اس‌كيوال سرور


سي شارپ


عمومي دات نت


ويندوز


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


متفرقه

۱۳۸۷/۱۱/۰۲

Anti CSRF module for ASP.NET


CSRF يا Cross Site Request Forgery به صورت خلاصه به اين معنا است كه شخص مهاجم اعمالي را توسط شما و با سطح دسترسي شما بر روي سايت انجام دهد و اطلاعات مورد نظر خود را استخراج كرده (محتويات كوكي يا سشن و امثال آن) و به هر سايتي كه تمايل دارد ارسال كند. اين‌كار عموما با تزريق كد در صفحه صورت مي‌گيرد. مثلا ارسال تصويري پويا به شكل زير در يك صفحه فوروم، بلاگ يا ايميل:

<img src="http://www.example.com/logout.aspx">

شخصي كه اين صفحه را مشاهده مي‌كند، متوجه وجود هيچگونه مشكلي نخواهد شد و مرورگر حداكثر جاي خالي تصوير را به او نمايش مي‌دهد. اما كدي با سطح دسترسي شخص بازديد كننده بر روي سايت اجرا خواهد شد.

روش‌هاي مقابله:
  • هر زمانيكه كار شما با يك سايت حساس به پايان رسيد، log off كنيد. به اين صورت بجاي منتظر شدن جهت به پايان رسيدن خودكار طول سشن، سشن را زودتر خاتمه داده‌ايد يا برنامه نويس‌ها نيز بايد طول مدت مجاز سشن در برنامه‌هاي حساس را كاهش دهند. شايد بپرسيد اين مورد چه اهميتي دارد؟ مرورگري كه امكان اجازه‌ي بازكردن چندين سايت با هم را به شما در tab هاي مختلف مي‌دهد، ممكن است سشن يك سايت را در برگه‌اي ديگر به سايت مهاجم ارسال كند. بنابراين زمانيكه به يك سايت حساس لاگين كرده‌ايد، سايت‌هاي ديگر را مرور نكنيد. البته مرورگرهاي جديد مقاوم به اين مسايل شده‌اند ولي جانب احتياط را بايد رعايت كرد.
براي نمونه افزونه‌اي مخصوص فايرفاكس جهت مقابله با اين منظور در آدرس زير قابل دريافت است:

  • در برنامه خود قسمت Referrer header را بررسي كنيد. آيا متد POST رسيده، از سايت شما صادر شده است يا اينكه صفحه‌اي ديگر در سايتي ديگر جعل شده و به برنامه شما ارسال شده است؟ هر چند اين روش آنچنان قوي نيست و فايروال‌هاي جديد يا حتي بعضي از مرورگرها با افزونه‌هايي ويژه، امكان عدم ارسال اين قسمت از header درخواست را ميسر مي‌سازند.
  • برنامه نويس‌ها نبايد مقادير حساس را از طريق GET requests ارسال كنند. استفاده از روش POST نيز به تنهايي كارآمد نيست و آن‌را بايد با random tokens تركيب كرد تا امكان جعل درخواست منتفي شود. براي مثال استفاده از ViewStateUserKey در ASP.Net . جهت خودكار سازي اعمال اين موارد در ASP.Net، اخيرا HTTP ماژول زير ارائه شده است:

تنها كافي است كه فايل dll آن در دايركتوري bin پروژه شما قرار گيرد و در وب كانفيگ برنامه ارجاعي به اين ماژول را لحاظ نمائيد.

كاري كه اين نوع ماژول‌ها انجام مي‌دهند افزودن نشانه‌هايي اتفاقي ( random tokens ) به صفحه‌ است كه مرورگر آن‌ها را بخاطر نمي‌سپارد و اين token به ازاي هر سشن و صفحه منحصر بفرد خواهد بود.

براي PHP‌ نيز چنين تلاش‌هايي صورت گرفته است:
http://csrf.htmlpurifier.org/


مراجعي براي مطالعه بيشتر
Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helper
Cross-site request forgery
Top 10 2007-Cross Site Request Forgery
CSRF - An underestimated attack method

۱۳۸۷/۱۱/۰۱

چگونه Regex سريعتري داشته باشيم؟


نكاتي را در هنگام كار با عبارات با قاعده در دات نت بايد رعايت نمود تا بتوان به حداكثر كارآيي و سرعت دست يافت:
  • 1- ايجاد اشياء Regex هزينه بر هستند. براي مثال اگر متد شما كه در آن شيء Regex را ايجاد كرده‌ايد مرتبا فراخواني مي‌شود، اين شيء را به صورت يك متغير محلي خارج از بدنه تابع تعريف كنيد. يا به همين صورت هرگز در يك حلقه اشياء Regex را بارها و بارها ايجاد نكنيد.
  • 2-از گزينه RegexOptions.Compiled استفاده كنيد. با اينكار زمانيكه برنامه شما اجرا مي‌شود، عبارت باقاعده در حافظه كامپايل شده و به بهبود كارآيي 30 درصدي دست خواهيد يافت. اگر از اين گزينه استفاده نشود، هر بار كه شيء Regex مورد استفاده قرار مي‌گيرد، عبارت باقاعده شما همانند يك اسكريپت بايد مجددا تفسير شود.
  • 3- اشياء Regex را از نوع static readonly تعريف كنيد تا بازهم كارآيي را افزايش دهيد (اشيايي ثابت در زمان اجرا و همچنين اشاره‌گري هستند به آن شيء و نه مقدار آن).

خلاصه موارد فوق:

private static readonly Regex _valueFormatMatch = new Regex(@"[0-9]", RegexOptions.Compiled);

بعلاوه اگر نمي‌خواهيد Regex شما هر بار در حين اجراي برنامه (در اولين باري كه برنامه بارگذاري مي‌شود)، كامپايل شود، مي‌توانيد آنرا به درون يك اسمبلي نيز كامپايل كنيد ( Precompilation ). روش انجام اينكار را در اين مقاله مي‌توانيد مشاهده نمائيد.

۱۳۸۷/۱۰/۳۰

مونيتور كردن ميزان مصرف CPU در اس كيوال سرور


در اين مقاله قصد داريم نحوه مونيتور كردن ميزان مصرف CPU توسط اس كيوال سرور را بررسي كنيم. براي بدست آوردن ميزان CPU مصرفي اس كيوال سرور مي‌توان به اسكريپت زير رجوع كرد:

DECLARE @CPU_BUSY int, @IDLE int
SELECT @CPU_BUSY = @@CPU_BUSY, @IDLE = @@IDLE WAITFOR DELAY '000:00:01'
SELECT (@@CPU_BUSY - @CPU_BUSY)/((@@IDLE - @IDLE + @@CPU_BUSY - @CPU_BUSY) *1.00) *100 AS 'CPU Utilization by sqlsrvr.exe'

ماخذ

در ادامه قصد داريم، هر 5 دقيقه به صورت خودكار بررسي كنيم كه آيا ميزان مصرف CPU در اس كيوال سرور بالاي 50 درصد است؟ و اگر بله، ايميلي را به مسؤول مربوطه جهت بررسي ارسال كنيم.

بنابراين اولين كاري كه بايد صورت گيرد، فعال سازي Database Mail در اس كيوال سرور است كه به صورت پيش فرض غيرفعال است. براي اين منظور تنها كافي است اسكريپت زير را بر روي سرور اجرا كنيد:

USE [master]
GO
sp_configure 'show advanced options',1
GO
RECONFIGURE WITH OVERRIDE
GO
sp_configure 'Database Mail XPs',1
GO
--RECONFIGURE
GO
-- Create a New Mail Profile for Notifications
EXECUTE msdb.dbo.sysmail_add_profile_sp
@profile_name = 'DBA_Notifications',
@description = 'Profile for sending Automated DBA Notifications'
GO
-- Set the New Profile as the Default
EXECUTE msdb.dbo.sysmail_add_principalprofile_sp
@profile_name = 'DBA_Notifications',
@principal_name = 'public',
@is_default = 1 ;
GO
-- Create an Account for the Notifications
EXECUTE msdb.dbo.sysmail_add_account_sp
@account_name = 'SQLMonitor',
@description = 'Account for Automated DBA Notifications',
@email_address = 'nasiri@site.net', -- Change This
@display_name = 'SQL Monitor',
@mailserver_name = 'mail.site.net' -- Change This
GO
-- Add the Account to the Profile
EXECUTE msdb.dbo.sysmail_add_profileaccount_sp
@profile_name = 'DBA_Notifications',
@account_name = 'SQLMonitor',
@sequence_number = 1

GO

ماخذ

اين اسكريپت براي اس كيوال سرورهاي 2005 به بعد طراحي شده و تنها دو سطر آن‌را پيش از اجرا بايد ويرايش كنيد. سطر مربوط به email_address و mailserver_name . آدرس ايميل درحقيقت آدرس ايميل قسمت from پيغام ارسالي را تشكيل مي‌دهد. نام سرور ميل هم، منظور آدرس smtp server شما در شبكه است.

يا اگر علاقمند بوديد كه اين‌كار را توسط ويزاردهاي management studio انجام دهيد (كه در نهايت هيچ تفاوتي با اسكريپت فوق نخواهد داشت)، مي‌توان به اين مقاله رجوع كرد.

پس از اجراي اسكريپت فوق، براي بررسي صحت عملكرد فوق مي‌توان دستور زير را اجرا كرد:

--test
EXECUTE msdb.dbo.sp_send_dbmail
@recipients = 'nasiri@site.net', -- Change This
@Subject = 'Test Message generated from SQL Server DatabaseMail',
@Body = 'This is a test message from SQL Server DatabaseMail'

ساير پارامترهاي اين دستور را در MSDN مي‌توان ملاحظه نمود.

تا اينجا اس كيوال سرور براي ارسال ايميل آماده شد. در ادامه قصد داريم يك job جديد در اس كيوال سرور ايجاد كنيم تا تمام موارد فوق را لحاظ كند.


مطابق تصوير فوق ابتدا يك job جديد را آغاز خواهيم كرد.



در ادامه اسكريپت زير را جهت اجرا به آن معرفي مي‌كنيم. توسط اين اسكريپت، ميزان جاري مصرف CPU اس كيوال سرور محاسبه شده و اگر اين ميزان بيشتر از 50 بود، يك ايميل به مسؤول مربوطه با ذكر ميزان CPU usage ارسال مي‌گردد.

DECLARE @CPUUsage INT
DECLARE @CPU_BUSY INT,
@IDLE INT

SELECT @CPU_BUSY = @@CPU_BUSY,
@IDLE = @@IDLE

WAITFOR DELAY '000:00:01'
SELECT @CPUUsage = (@@CPU_BUSY - @CPU_BUSY) / ((@@IDLE - @IDLE + @@CPU_BUSY - @CPU_BUSY) * 1.00)
* 100 -- CPU Utilization by sqlsrvr.exe


IF @CPUUsage > 50
BEGIN
DECLARE @msg NVARCHAR(1000)
SET @msg = 'Please check SQL server, CPU usage is ' + CAST(@CPUUsage AS NVARCHAR(50))
+ '%.'

EXECUTE msdb.dbo.sp_send_dbmail
@recipients = 'nasiri@site.net', -- Change This
@copy_recipients = 'nasiri@site.net', -- Change This
@Subject = 'CPU overload',
@Body = @msg
,@importance = 'High'
END



و در آخر زمان اجراي آن را به هر روز، هر 5 دقيقه يكبار تنظيم خواهيم كرد.

اگر نياز به راه حلي پخته‌تر و بررسي متوسط چندين مقدار قبلي ، مقايسه آن‌ها و سپس ارسال ايميل داشتيد، مي‌توان به فصل 14 كتاب Super SQL Server Systems مراجعه كرد.

۱۳۸۷/۱۰/۲۹

استفاده از لوله‌هاي ياهو در بلاگر!


داشتم به دنبال راهي براي نمايش محبوب‌ترين پست‌ها در وبلاگ جاري مي‌گشتم، اين جستجو به لوله‌هاي ياهو ختم شد!
يكي از پركاربردترين ويجت‌هاي بلاگر، ويجت نمايش فيد است (با نام "عناوين خبري" ترجمه شده است). براي مثال همين ليست آخرين نظرها در سايت، با استفاده از فيد استاندارد كامنت‌هاي سايت درست شده است. 5 كامنت آخر سايت را نمايش مي‌دهد كه البته اين يك ايراد هم هست و بيشتر از اين تعداد را قبول نمي‌كند. يا دقيقا همان زمان ارسال كامنت به روز نمي‌شود. به نظر در ساعات مشخصي از روز اين به روز رساني صورت مي‌گيرد.

جهت "نمايش ليست مطالبي با بيشترين كامنت" مي‌توانيد به آدرس زير مراجعه كنيد:
Popular Posts/Most Commented Widget for Blogger Blogs

آدرس بلاگ خود را وارد كنيد (بدون http البته). عدد دلخواهي را كه بيانگر تعداد ركورد بازگشت داده شده است نيز وارد نمائيد (هر چند بلاگر فقط 5 آيتم را نمايش خواهد داد) و سپس بر روي دكمه run كليك كنيد. در همانجا روي more options كليك كرده و لينك فيد rss آن‌را دريافت كنيد. در حقيقت با استفاده از لوله‌هاي ياهو يك سري پردازش روي فيد كامنت‌هاي سايت صورت گرفته و آمار نهايي به صورت يك فيد جديد به شما ارائه خواهد شد كه از آن مي‌توانيد در ويجت مربوط به عناوين خبري يا همان فيدهاي بلاگر، استفاده كنيد.






و يا نمايش ليست برترين كامنت گذاران!
Top Commentators Widget for Blogger




در اينجا روي لينك clone كليك كنيد تا يك نمونه مخصوص شما كپي شود (بهتر است به اكانت ايميل خود در ياهو لاگين كرده باشيد). اكنون مي‌توانيد آن را اديت كرده و بر روي آن تغييرات دلخواه را اعمال كنيد (وارد كردن لينك فيد كامنت‌هاي سايت مطابق شكل). سپس بر روي دكمه ذخيره كليك كرده و نهايتا فيد rss آن‌را دريافت كنيد.

موارد ديگري هم از همين دست در سايت لوله‌هاي ياهو موجود است:
http://pipes.yahoo.com/pipes/search?q=blogger&x=6&y=9

۱۳۸۷/۱۰/۲۸

مقايسه مجوزهاي سورس باز


احتمالا هميشه براي شما سؤال بوده است كه مجوزهاي گوناگون سورس باز با هم چه فرقي دارند، يا اينكه اگر روزي خواستم پروژه‌ي خود را به صورت سورس باز ارائه كنم، كداميك از مجوزهاي موجود مناسب‌تر است و همچنين وقت مطالعه مقالات طولاني يا كتاب‌هايي چند صد صفحه‌اي در اين مورد را نداشته‌ايد.
جدول زير كار مقايسه اين مجوزها (موارد رايج‌تر) را به صورت مختصر و مفيد و بر اساس سؤالات رايج كاربران، انجام مي‌دهد:

نام مجوز آيا به كار مشتق شده از پروژه اصلي، مي‌توانم نامي ديگر بدهم؟ آيا بايد حتما كار مشتق شده سورس باز باقي بماند؟ آيا مي‌توانم براي كار مشتق شده مجوزي جديد انتخاب كنم؟ آيا مي‌توانم كار مشتق شده را بفروشم و كسب درآمد كنم؟

Apache License 2.0
بله خير بله بله

Common Development and Distribution License (CDDL)
بله خير بله (به مجوزهاي سازگار ديگري از همين دست) بله

GNU General Public License 2.0 (GPLv2)
بله، اما حتما بايد ليست تغييرات انجام شده نسبت به پروژه اصلي را نيز
ارائه بدهيد.
بله بله (به مجوزهاي سازگار ديگري از همين دست يا توافق با نويسنده اصلي) بله

GNU Library General Public License (LGPL)
بله بله، اما امكان استفاده از كتابخانه‌هاي كامپايل شده يك پروژه سورس باز
تحت اين مجوز در يك پروژه سورس بسته نيز وجود دارد.
بله (به مجوزهاي سازگار ديگري از همين دست) بله

Microsoft Public License (Ms-PL)
بله، اما نمي‌توانيد از علامت تجاري خود استفاده كنيد. خير خير بله

Microsoft Reciprocal License (Ms-RL)
بله، اما نمي‌توانيد از علامت تجاري خود استفاده كنيد. بله خير بله

Mozilla Public License 1.1 (MPL)
بله خير خير بله

BSD License
بله خير بله بله

MIT License
بله خير بله بله



همچنين لازم به ذكر است كه
مجوزهاي كار اصلي و كار مشتق شده هر دو بايد ذكر شوند.
پسنديده است كه از نويسندگان كار اصلي، نامبرده شده و قدرداني گردد.
هيچكدام از اين مجوزها مسؤوليتي را در قبال كار انجام شده نمي‌پذيرند!

جهت مطالعه بيشتر:
http://khason.net/blog/open-source-licenses-comparison-table/
http://developer.kde.org/documentation/licensing/licenses_summary.html
http://en.wikipedia.org/wiki/Comparison_of_free_software_licences

۱۳۸۷/۱۰/۲۷

JQuery 1.3 ارائه شد


روز قبل، نگارش رسمي و نهايي jQuery 1.3 ارائه شد و بلافاصله هم فايل مخصوص آن جهت بكارگيري intellisense ويژوال استوديو، توسط علاقمندان تهيه و عرضه گرديد.

تازه‌هاي اين نگارش:
  • Sizzle : يك موتور CSS selector قدرتمند (400 درصد بهبود سرعت نسبت به عملكرد كتابخانه قبلي در اين مورد)
  • بازنگري در نحوه مديريت رخدادها
  • موتور تزريق HTML‌ بسيار سريع (تا 15 برابر سريعتر نسبت به كتابخانه قبلي)
  • موتور بسيار سريع موقعيت يابي
  • تشخيص نوع مرورگر در آن متوقف شده و بجاي آن از تشخيص ويژگي‌ها براي ماندگاري بيشتر اين كتابخانه در سال‌هاي آتي استفاده گرديده است. (بجاي بررسي userAgent ، از باگ‌هاي شناخته شده يا ويژگي‌هاي خاص، جهت تشخيص مرورگر استفاده مي‌شود تا بازه وسيعي از محصولات مشابه را بتوانند پوشش دهند)
ليست كامل اين تغييرات را در اين آدرس مي‌توانيد ملاحظه نمائيد.
  • جهت مشاهده و آزمايش بهبود كارآيي اين كتابخانه لطفا به اين صفحه مراجعه كنيد. (ليست كامل اين آزمايشات در انتهاي صفحه ليست تغييرات، قابل دسترسي است)
همچنين تيم مربوطه در پي آن است تا در طي يكي دو هفته آينده، نگارش jQuery 1.3.1 را نيز بر اساس بازخوردهاي جديد جامعه برنامه نويس‌ها ارائه دهد.

مانند هميشه اين كتابخانه در دو نگارش فشرده شده (جهت استفاده در سايت‌ها) و نگارش عادي و حجيم‌تر (جهت برنامه نويسي و ديباگ كردن كدها) ارائه شده است. چون كدها در Google code هاست شده احتمالا دسترسي به آن مشكل خواهد بود. اين مجموعه را از اين آدرس مي‌توانيد دريافت كنيد.

توصيه مي‌شود از سرورهاي سريع گوگل بعنوان هاست كتابخانه جي‌كوئري سايت‌هاي خود استفاده كنيد. براي اين منظور از آدرس زير مي‌توان استفاده كرد:
http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js


۱۳۸۷/۱۰/۲۶

لينك‌هاي هفته‌ي آخر دي


وبلاگ‌ها ، سايت‌ها و مقالات ايراني (داخل و خارج از ايران)


Visual Studio


ASP. Net



طراحي و توسعه وب



PHP


اس‌كيوال سرور


سي شارپ


عمومي دات نت


ويندوز


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


متفرقه


۱۳۸۷/۱۰/۲۵

ليستي از برگه‌هاي مرجع


اخيرا سايت dzone ، تعدادي برگه مرجع رايگان (يا همان برگه تقلب سابق!) را منتشر كرده است.
مشاهده صفحه مربوطه

فقط بايد عضو شد و به ازاي هر فايل pdf يك ايميل دريافت كرد! كه كمي دشوار و وقت گير است. ليست فايل‌هاي pdf آن‌را از اينجا مي‌توانيد دريافت كنيد.


موفق باشيد

۱۳۸۷/۱۰/۲۴

مشكل ي و ك فارسي و عربي در يك ديتابيس اس كيوال سرور


ديروز به من اطلاع دادند كه در يكي از برنامه‌ها دو تا گروه "تاسيسات مكانيكي" پيدا شده!!
تاسيسات مكانيكي
تاسيسات مکانیکی

استاندارد اين شركت، استفاده از kbdfa.dll مخصوص و نسبتا قديمي است. بنابراين استاندارد مورد استفاده همان ي و ك عربي است. (كاري ندارم خوب است يا بد، يا بايد اينطور باشد يا نه، بحث اين است كه فعلا اينطور است و قرار نيست چيزي عوض بشود!)
در مثال فوق، ي و ك عبارت دوم فارسي است. يعني نصب kbdfa.dll روي ويندوز تازه نصب شده، فراموش شده بوده.

راه حل‌ها:
الف) قبل از ثبت، يكسان سازي صورت گيرد. يعني اجراي متدي شبيه به متد زير بر روي هر ورودي متني فارسي:

public string SafeFarsiStr(string input)
{
return input.Replace("ی", "ي").Replace("ک", "ك");
}

ب) خوب، الان كه اين يكسان سازي صورت نگرفته چه بايد كرد؟
اسكريپتي را تهيه كرده‌ام (مخصوص SQL Server 2005 به بعد) به صورت زير كه اين تبديل را براي شما انجام مي‌دهد.
به صورت خودكار تمامي فيلدهاي متني كليه جداول ديتابيس جاري شما را يافته و ي و ك آن‌ها را يكسان مي‌كند. البته همانطور كه عرض شد، مطابق استاندارد اين شركت و استفاده از فايل kbdfa.dll قديمي مورد استفاده، تمام ي و ك هاي فارسي به عربي تبديل مي‌شوند.

--اسكريپتي براي يك دست سازي ي و ك در تمامي ركوردهاي تمامي جداول ديتابيس جاري
-- اسكريپت زير ي و ك فارسي را به عربي تبديل مي‌كند
-- در صورت نياز به حالت عكس ، جاي مقادير عددي يونيكد را تعويض نمائيد

USE TestDb;

DECLARE @Table NVARCHAR(MAX),
@Col NVARCHAR(MAX)

DECLARE Table_Cursor CURSOR
FOR
--پيدا كردن تمام فيلدهاي متني تمام جداول ديتابيس جاري
SELECT a.name, --table
b.name --col
FROM sysobjects a,
syscolumns b
WHERE a.id = b.id
AND a.xtype = 'u' --User table
AND (
b.xtype = 99 --ntext
OR b.xtype = 35 -- text
OR b.xtype = 231 --nvarchar
OR b.xtype = 167 --varchar
OR b.xtype = 175 --char
OR b.xtype = 239 --nchar
)

OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @Table,@Col
WHILE (@@FETCH_STATUS = 0)
BEGIN
EXEC (
'update [' + @Table + '] set [' + @Col +
']= REPLACE(REPLACE(CAST([' + @Col +
'] as nvarchar(max)) , NCHAR(1740), NCHAR(1610)),NCHAR(1705),NCHAR(1603)) '
)

FETCH NEXT FROM Table_Cursor INTO @Table,@Col
END CLOSE Table_Cursor DEALLOCATE Table_Cursor

توضيحات و نكاتي در مورد اسكريپت فوق:
الف) براي آشنايي با انواع XType Datatype مورد استفاده در كوئري فوق به اين آدرس مراجعه نمائيد.
ب) همانطور كه در مطالب قبلي اين وبلاگ نيز ذكر شد، امكان استفاده از تابع replace بر روي فيلدهاي text و ntext وجود ندارد. هيچ اشكالي ندارد! تمام آن‌ها به nvarchar از نوع max دار cast شده و اين مشكل به اين صورت حل مي‌شود.
ج) اس كيوال سرور اجازه تعريف يك جدول يا فيلد را به صورت متغير بكار رفته در يك كوئري T-SQL نمي‌دهد. براي حل اين موضوع بايد عبارت SQL مورد نظر را به صورت يك رشته درآورد و سپس exec كرد.
د) مجبور شدم از معاد‌ل‌هاي عددي براي دقت بيشتر كار استفاده كنم



(در كل از تابع UNICODE اس كيوال سرور براي بدست آوردن اين اعداد مي‌توان استفاده كرد)

تذكر: اين اسكريپت بر روي يك ديتابيس كاري تست شده و نتيجه رضايت بخش بوده؛ اما اگر شما روزي خواستيد از آن استفاده كنيد، حتما full backup را قبل از اجراي آن فراموش نكنيد و پس از اجرا، تابع SafeFarsiStr فوق را براي ادامه كار حتما لحاظ نمائيد يا از يك kbdfa.dll هماهنگ استفاده كنيد.


۱۳۸۷/۱۰/۲۳

نمايش حداكثر اندازه مجاز فايل قابل آپلود به كاربر، در ASP.Net


گاهي از اوقات قبل از درگير شدن با كاربران (!)، بهتر است حداكثر اندازه مجاز فايل قابل ارسال به سرور را به آن‌ها نمايش داد. درغيراينصورت بايد پاسخگوي اين باشيد كه چرا فايل 100 مگابايتي كه من ارسال كردم، ذخيره نشده و برنامه كار نمي‌كنه!
خطاي دريافتي اين خواهد بود: Maximum request length exceeded
در ASP.Net اگر هيچ تنظيم خاصي صورت نگرفته باشد، حداكثر اندازه فايل قابل ارسال به سرور، 4 مگابايت است. اين مورد را در machine.config و يا در web.config مي‌توان تغيير داد.
براي مثال، جهت بالا بردن اندازه فايل قابل ارسال به سرور در وب كانفيگ برنامه به 39 مگابايت، مي‌توان سطر زير را به قسمت system.web اضافه كرد.
<httpRuntime executionTimeout="1200" maxRequestLength="39936" />

البته در اين حالت بهتر است executionTimeout را نيز تنظيم نمود (بر اساس ثانيه) تا يك فايل حجيم را بتوانند آپلود كنند و در اين حين مشكل timeout رخ ندهد (در اينجا به 20 دقيقه تنظيم شده است).

اما يك نكته را هم بايد درنظر داشت. اگر هاست مورد استفاده شما فايل machine.config را قفل كرده باشد (كه از لحاظ امنيتي توصيه مي‌شود)، سطر فوق در web.config هيچ تاثيري نخواهد داشت.

به همين منظور كلاس زير را تهيه كرده‌ام كه تمامي اين موارد را لحاظ مي‌كند.
ابتدا مقدار پيش فرض 4 مگابايت درنظر گرفته خواهد شد.
سپس سعي مي‌شود كه مقدار مجاز MaxRequestLength از فايل machine.config خوانده شود. همچنين وضعيت قفل بودن آن نيز دريافت مي‌شود.
اگر اين قسمت قابل خواندن بود و همچنين قفل نشده بود، مقدار تنظيم شده maxRequestLength در وب كانفيگ، دريافت و استفاده خواهد شد.
و در آخر، اندازه دريافتي، كه بر اساس KB است به شكلي قابل خواندن بازگشت داده مي‌شود.

using System;
using System.Configuration;
using System.Web.Configuration;

/// <summary>
/// كلاسي جهت نمايش اندازه مجاز فايل قابل ارسال به سرور
/// </summary>
public class CMaxLimit
{
/// <summary>
/// اندازه مجاز فايل قابل ارسال به سرور
/// </summary>
/// <returns></returns>
public static string MaxFileUploadSizeLimit()
{
//مقدار پيش فرض
int resultKB = 4096;

//machine.config
Configuration mConfig =
WebConfigurationManager.OpenMachineConfiguration();
bool mConfigIsLocked = false;
HttpRuntimeSection section =
mConfig.GetSection("system.web/httpRuntime") as HttpRuntimeSection;
if (section != null)
{
resultKB = section.MaxRequestLength;
mConfigIsLocked = section.ElementInformation.IsLocked;
}

//web.config
if (!mConfigIsLocked)
{
HttpRuntimeSection httpRuntimeSection =
WebConfigurationManager.GetSection("system.web/httpRuntime") as HttpRuntimeSection;
if (httpRuntimeSection != null)
{
resultKB = httpRuntimeSection.MaxRequestLength;
}
}

return
SizeToString(resultKB * 1024);
}

/// <summary>
/// نمايش اندازه يك فايل به صورتي قابل درك
/// </summary>
/// <param name="len">اندازه فايل</param>
/// <returns></returns>
public static string SizeToString(long len)
{
int order = 0;
string[] sizes = new[] { "B", "KB", "MB", "GB" };
while (len >= 1024 && order + 1 < sizes.Length)
{
order++;
len = len / 1024;
}
return String.Format("{0:0.##} {1}", len, sizes[order]);
}
}

۱۳۸۷/۱۰/۲۲

تغيير ابعاد يك TextArea با استفاده از jQuery


اگر به سايت stackoverflow دقت كنيد، اندازه textarea ايي كه كاربران امكان ارسال مطلب دارند، قابل تغيير است:



شايد براي شما جالب باشد كه بدانيد به چه صورتي اينكار را انجام داده‌اند. اينكار با استفاده از افزونه TextArea Resizer صورت گرفته است. (دريافت كتابخانه به همراه مثال)

البته حالت عمومي‌تري نيز توسط jQuery-UI استاندارد پشتيباني مي‌شود (امكان تغيير اندازه يك المان با قابليت تغيير اندازه در حالت كلي). براي مثال به صفحه‌ي ساده‌ي ASP.Net زير دقت بفرمائيد:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm5.aspx.cs" Inherits="testWebForms87.WebForm5" %>
<!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="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.5.3/jquery-ui.min.js" type="text/javascript"></script>

<script type="text/javascript">
$(function() {
$("#resizableArea").resizable({
handles: "s"
})
.find("textarea").height("100%").width("100%");
});
</script>

</head>
<body>
<form id="form1" runat="server">
<div id="resizableArea" style="width:300px; height:200px" >
<asp:TextBox ID="TextBox1" runat="server" TextMode="MultiLine" ></asp:TextBox>
</div>
</form>
</body>
</html>

در اينجا با استفاده از jQuery-UI ابتدا div ايي با id مساوي resizableArea پيدا مي‌شود و تابع resizable به آن اعمال مي‌گردد. سپس در اين div ، تمامي عناصر textarea موجود يافت شده و طول و عرض آن‌ها به اندازه‌ي جديد تغيير يافته div تنظيم خواهد شد. در مورد تنظيم‌هاي ديگري مانند نمايش ناحيه تغيير يافته به صورت animation مي‌توان به راهنماي آن مراجعه نمود.
براي مثال با استفاده از اين روش مي‌توان يك GridView با قابليت تغيير اندازه ايجاد كرد و امثال آن. يا براي نمونه شايد با مثال‌هايي كه به گريد نمايش داده شده اسكرول بار اضافه مي‌كنند برخورده باشيد:

<div id="resizableArea" style="overflow:auto;height:200px;">
My Grid view ...
</div>

و يا استفاده از يك پنل:

<asp:Panel ID="pnlScroll" runat="server" Width="391px" Height="282px" ScrollBars="Vertical">
My Grid view ...
</asp:Panel>

با استفاده از روش عمومي فوق، مي‌توان به اين div امكان تغيير اندازه را نيز اضافه كرد و آن‌را از حالت غيرقابل تغيير بودن خارج نمود.

۱۳۸۷/۱۰/۲۱

آشنايي با آزمايش واحد (unit testing) در دات نت، قسمت 6


ادامه آشنايي با NUnit

فرض كنيد يك RSS reader نوشته‌ايد كه فيدهاي فارسي و انگليسي را دريافت مي‌كند. به صورت پيش فرض هم مشخص نيست كه كدام فيد اطلاعات فارسي را ارائه خواهد داد و كداميك انگليسي. تشخيص محتواي فارسي و از راست به چپ نشان دادن خودكار مطالب ‌آن‌ها به عهده‌ي برنامه نويس است. بهترين روش براي تشخيص اين نوع الگوها، استفاده از regular expressions است.
براي مثال الگوي تشخيص اينكه آيا متن ما حاوي حروف انگليسي است يا خير به صورت زير است:

[a-zA-Z]

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

[\u0600-\u06FF]
[ا-یءئ]

در مورد اينكه بازه يونيكد فارسي استاندارد از كجا شروع مي‌شود مي‌توان به مقاله‌ي آقاي حاج‌لو مراجعه نمود (به صورت خلاصه، بازه مصوب عربي يونيكد، همان بازه يونيكد فارسي نيز مي‌باشد. يا به بيان بهتر، بازه‌ي فارسي، جزئي از بازه‌اي است كه عربي نام گرفته است). البته بازه‌ي مصوب ديگري هم در مورد ايران باستان وجود دارد به نام old Persian كه مورد استفاده‌ي روزمره‌اي ندارد!

كلاس زير را در مورد استفاده از اين الگوها تهيه كرده‌ايم:

using System.Text.RegularExpressions;

namespace sample
{
public static class CDetectFarsi
{
public static bool ContainsFarsiData(this string txt)
{
return !string.IsNullOrEmpty(txt) &&
Regex.IsMatch(txt, "[ا-یءئ]");
}

public static bool ContainsFarsi(this string txt)
{
return !string.IsNullOrEmpty(txt) &&
Regex.IsMatch(txt, @"[\u0600-\u06FF]");
}
}
}

همانطور كه ملاحظه مي‌كنيد در اينجا از extension methods سي شارپ 3 جهت توسعه كلاس پايه string استفاده شد.
اكنون مي‌خواهيم بررسي كنيم آيا اين الگوها مقصود ما را برآورده مي‌سازند يا خير.

using NUnit.Framework;
using sample;

namespace TestLibrary
{
[TestFixture]
public class TestFarsiClass
{
/*******************************************************************************/
[Test]
public void TestContainsFarsi1()
{
Assert.IsTrue("وحيد".ContainsFarsi());
}

[Test]
public void TestContainsFarsi2()
{
Assert.IsTrue("گردان".ContainsFarsi());
}

[Test]
public void TestContainsFarsi3()
{
Assert.IsTrue("سپيدTest".ContainsFarsi());
}

[Test]
public void TestContainsFarsi4()
{
Assert.IsTrue("123بررسي456".ContainsFarsi());
}

[Test]
public void TestContainsFarsi5()
{
Assert.IsFalse("Book".ContainsFarsi());
}

[Test]
public void TestContainsFarsi6()
{
Assert.IsTrue("۱۳۸۷".ContainsFarsi());
}

[Test]
public void TestContainsFarsi7()
{
Assert.IsFalse("Здравствуйте!".ContainsFarsi()); //Russian hello!
}


/*******************************************************************************/
[Test]
public void TestContainsFarsiData1()
{
Assert.IsTrue("وحيد".ContainsFarsiData());
}

[Test]
public void TestContainsFarsiData2()
{
Assert.IsTrue("گردان".ContainsFarsiData());
}

[Test]
public void TestContainsFarsiData3()
{
Assert.IsTrue("سپيدTest".ContainsFarsiData());
}

[Test]
public void TestContainsFarsiData4()
{
Assert.IsTrue("123بررسي456".ContainsFarsiData());
}

[Test]
public void TestContainsFarsiData5()
{
Assert.IsFalse("Book".ContainsFarsiData());
}

[Test]
public void TestContainsFarsiData6()
{
Assert.IsTrue("۱۳۸۷".ContainsFarsiData());
}

[Test]
public void TestContainsFarsiData7()
{
Assert.IsFalse("Здравствуйте!".ContainsFarsiData()); //Russian hello!
}
}
}

در كلاس فوق هر دو متد را با آزمايش‌هاي واحد مختلفي بررسي كرده‌ايم، انواع و اقسام حروف فارسي، تركيبي از فارسي و انگليسي، تركيبي از فارسي و اعداد انگليسي، عبارت كاملا انگليسي، عدد كاملا فارسي و يك عبارت روسي! (در يك كلاس عمومي با متدهاي عمومي بدون آرگومان از نوع void)
كلاس CDetectFarsi در برنامه اصلي قرار دارد و كلاس TestFarsiClass در يك پروژه class library ديگر قرار گرفته است (در اين مورد و جدا سازي آزمايش‌ها از پروژه اصلي در قسمت‌هاي قبل بحث شد)
همچنين به ازاي هر عبارت Assert يك متد ايجاد گرديد تا شكست يكي، سبب اختلال در بررسي ساير موارد نشود.
نتيجه اجراي اين آزمايش واحد با استفاده از امكانات مجتمع افزونه ReSharper به صورت زير است:



منهاي يك مورد، ساير آزمايشات ما با موفقيت انجام شده‌اند. موردي كه با شكست مواجه شده، بررسي اعداد كاملا فارسي است كه البته در الگوي دوم لحاظ نشده است و انتظار هم نمي‌رود كه آن‌را به اين شكل پشتيباني كند.
براي اينكه در حين اجراي آزمايشات بعدي اين متد در نظر گرفته نشود، مي‌توان ويژگي Test آن‌را به صورت زير تغيير داد:

[Test,Ignore]

نكته: مرسوم شده است كه نام متدهاي آزمايش واحد به صورت زير تعريف شوند (با Test شروع شوند، در ادامه نام متدي كه بررسي مي‌شود ذكر گردد و در آخر ويژگي مورد بررسي عنوان شود):

Test[MethodToBeTested][SomeAttribute]

ادامه دارد...

۱۳۸۷/۱۰/۲۰

نمايش خودكار آيكون لينك‌هاي سايت‌هاي خارجي با استفاده از jQuery


اگر دقت كرده باشيد در كنار هر لينك خارجي (هر لينك ختم شده به خارج از سايت) در اين وبلاگ، آيكون آن سايت هم به صورت خودكار نمايش داده مي‌شود. از نظر من جالب بوده (خصوصا جهت مشخص كردن وجود يك لينك در ميان انبوهي متن، يا براي نمايش ليستي از لينك‌ها)، نظر شما رو نمي‌دونم!
اين‌كار در ادامه‌ي مطلبي است كه در مورد نوشتن اسكريپت‌هاي گريس مانكي چندي قبل منتشر كردم. البته بهبود يافته‌ي آن است. براي ايجاد يك چنين قابليتي در سايت فقط كافي است چند سطر اسكريپت زير را به هدر سايت خود اضافه كنيد.

<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js' type='text/javascript' />
<script type="text/javascript">
$(document).ready(function(){
$("a").each(function(){
var $a = $(this);
var href = $a.attr("href");
// see if the link is external
if (href && href.match(/^http/))
if (!href.match(document.domain)) {
var domain = href.replace(/<\S[^><]*>/g, "").split('/')[2];
var image = '<img src="http://' + domain +
'/favicon.ico" width="0" ' +
' onload="this.width=16;this.height=16;this.style.paddingLeft=\'3px\';this.style.paddingRight=\'1px\';" ' +
' style="border:0" ' +
' onerror="this.src=\'http://vahid.nasiri.googlepages.com/weblink.gif\';" />';
$(this).prepend(image);
}
});
});
</script>

توضيحاتي در مورد جزئيات برنامه نويسي آن:
با استفاده از jQuery ، زمانيكه document ما ready شد ( document.ready )، تمام لينك‌هاي موجود در صفحه را پيدا مي‌كنيم (يك به يك). سپس مقدار href آن‌ها را مي‌خوانيم (ببينيد با jQuery انجام اين نوع كارها چقدر ساده شده است). اكنون روي لينك دريافت شده بايد پردازش صورت گيرد و نام دومين آن جدا شود (اگر ختم به خارج از سايت بود). سپس بر اساس اين دومين ، يك تگ img منتهي به آيكون آن سايت طراحي و نمايش داده خواهد شد (به قبل از لينك اضافه مي‌شود).
عموما هر پروژه‌اي هر چند كوچك و به ظاهر كم اهميت، نكات خاصي را به همراه دارد.
براي مثال، در ابتداي كار width=0 در نظر گرفته نشد. مشكلي را كه ايجاد كرد اين بود كه يك سايت ممكن است اصلا favicon.ico نداشته باشد. فايرفاكس محترم اصلا به روي مبارك هم نخواهد آورد و شما متوجه نخواهيد شد كه در صفحه كمبود تصويري وجود دارد. اما در IE حتما جاي خالي آيكون و تصوير به نحوه واضحي گوشزد مي‌شود. بنابراين در ابتداي كار قرار نيست چيزي را نمايش دهيم (width=0). سپس در رخ‌داد onload تگ img، اگر تصوير واقعا وجود داشت و بارگذاري شد، طول و عرض آن‌را 16 در 16 قرار خواهيم داد (اين مورد هم لازم است. چون بعضي از سايت‌ها اندازه‌هاي بسيار بزرگي را براي آيكون خود در نظر مي‌گيرند كه اصلا مقصود ما را برآورده نخواهند كرد).
اين مورد (عدم نمايش تصاويري كه وجود ندارند) مشكلي را كه در ادامه ايجاد خواهد كرد، عدم يكنواختي در سايت است. يك سري از لينك‌هاي خارجي آيكون دارند و يك سري خير. نكته جالبي كه در مورد تگ img وجود دارد رخ‌داد onerror آن است. اگر مرورگر نتواند تصوير مورد نظر را پيدا يا بارگذاري كند، اين روال رخ‌داد‌ گردان فراخواني مي‌شود. همينجا از موقعيت استفاده شده و src تصوير جاري به يك آيكون مشخص و از قبل تعيين شده تنظيم مي‌شود.

۱۳۸۷/۱۰/۱۹

لينك‌هاي هفته سوم دي


وبلاگ‌ها ، سايت‌ها و مقالات ايراني (داخل و خارج از ايران)

ASP. Net

  • ويديويي درباره‌ي ASP.Net 4 (بهبودهاي حاصل شده در web forms از جهت كار با اسكريپت‌ها خصوصا با تاكيد بر jQuery و همچنين ذكر اينكه با آمدن ASP.Net MVC ، وب فرم‌ها كهنه نشده‌ و همچنان توسعه و بهبود داده خواهند شد)، يا مقاله‌اي در اين مورد

طراحي و توسعه وب

PHP

اس‌كيوال سرور

سي شارپ

عمومي دات نت

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

متفرقه