DCSIMG
May 2008 - Posts - שחר.נט

שחר.נט

בלוגים שאני קורא

ספרים מומלצים

May 2008 - Posts

טיהור מים מיוני עופרת באמצעות צמחי מים (מקום שני בתחרות המים)

לפני שעות ספורות, חזרתי מאוניברסיטת תל אביב, מהגמר של תחרות פרס המים (מטעם התחרות העולמית בשטוקהולם) בישראל.
הפרוייקט שאני, ביחד עם ידיד אלגאוי ובהנחיית ד"ר מרדכי ליבנה מאוניברסיטת בר אילן עשינו, הוא מחקר בנושא טיהור מים מיוני עופרת (אחת המתכות הרעילות ביותר) באמצעות צמחי מים, כאשר השתמשנו בצמחי מים מיובשים - פיסטיה וסלביניה שאותם השרינו (לעיתים בשילוב הקרנה בתנור מיקרוגל) בתוך תמיסת עופרת מימית בריכוזים שונים (וכמויות שונות של צמחים) ובדקנו את הכמות עופרת שסולקה באמצעות טיטרציה קומפלקסומטרית עם EDTA.

במסגרת המחקר, גילינו שניתן לסלק עד 100% מכמות יוני העופרת (מתכת רעילה מאד) הנמצאים במים, ולמעשה לטהר אותם כמעט לחלוטין מיוני עופרת, באמצעות צמחי מים מיובשים תוך דקה אחת של הקרנה במיקרוגל (שמאיץ תהליכים כימיים אורגניים).

היתרונות בשימוש בצמחי מים מיובשים הוא עלותם הנמוכה, ידידותיות לסביבה ופעולה מהירה מאד.

במסגרת הגמר, שנמשך מספר שעות (שרובן, בסופו של דבר, עבר בהמתנה - אבל היה שווה את זה), הצגנו את הפרוייקט ל-3 קבוצות של שופטים, ובטקס הסיום הוענקו הפרסים. מסתבר, שזכינו במקום השני בתחרות (מה שאומר כבוד, תהילה ו-250$ לכל אחד מאיתנו).

אז.... שיהיה לנו במזל טוב.

שחר.

התאמת Dynamic Data Web Applications

התאמה אישית של Dynamic Data Web Applications

הקדמה

Service Pack 1 עבור Visual Studio 2008 ו-.NET Framework 3.5 יצא היום בגרסאת בטא ראשונה. בין השדרוגים הכלולים בו, נמנה גם הוספת ה Dynamic Data Web Applications, שעד עכשיו הופצו כגרסאות CTP כחלק מה ASP.NET 3.5 Extensions, ואילו ב Service Pack 1 התווספו כחלק אינטגרלי ל Framework.

בניגוד לגרסאות הCTP, אפשרויות ההתאמה אישית (קסטומיזציה) בגרסא הכלולה ביחד עם הבטא של SP1, רחבות הרבה יותר. הסיבה העיקרית לכך, היא שלא מדובר בסט חדש של controls המתבססים על ה controls המוכרים של ה Web Forms, אלא, אנחנו עובדים עם אותם WebForms controls מוכרים, כאשר מנגנון ה Dynamic Data מתווסף כשכבה נוספת.

במידה ואין לכם ניסיון עם Dynamic Data Web Applications בגרסא זו, מומלץ לצפות קודם לקריאת המאמר ב Screencast הזה.

התאמה אישית

את ההתאמה אישית של Dynamic Data Web Applications, ניתן לחלק למספר רמות. החל מפריט המידע הבודד, ועד לפרוייקט בכללותו. בפוסט זה, אני אציג את הנקודות השונות בהם ניתן להתערב ולהתאים אישית את הפרוייקט.

לא לחולל הכל אוטומטית

כאשר יוצרים את הפרוייקט, ומוסיפים את שכבת הDAL, אנחנו רושמים ב global.asax את מודל הנתונים. בשלב הזה, ניתן להחליט האם אנו רוצים יצירה אוטומטית של מסכי הניהול או לא.
השלב הראשון, בקבלת השליטה והאפשרות לביצוע קאסטומיזציה, יהיה להגיד למנגנון ה Dynamic Data שאני לא מעוניין שיחולל לי מסכי ניהול עבור כל אובייקט שמופה לי לטבלה ב DB, אלא אני רוצה להחליט בעצמי. ניתן לגשת לזה בשתי דרכים שונות:

הראשונה - לקבוע שמראש, לא יווצר שום דבר אוטומטית, ורק אם אני אצור זה יהיה קיים. את זה עושים ע"י שינוי השורה בקובץ global.asax.cs שכתבנו ב screencast, ולוודא שה property ששמו ScaffoldAllTables הוא false:

   25 model.RegisterContext(typeof(NortwhindDataContext), new ContextConfiguration() { ScaffoldAllTables = true });

כעת, עד שלא ניצור בעצמנו דפים עבור כל אובייקט נתונים, לא יהיה לו ייצוג משלו ומסכי ניהול אוטומטיים משלו.

הדרך השנייה- להשאיר ב global.asax.cs את ה property הזה כשהוא שווה ל true, אבל פשוט ליצור בעצמנו את הממשק הWEB-י, והוא יחליף אוטומטית את זה שנוצר ע"י מנגנון ה Dynamic Data.

ליצור דפי ניהול משלי עבור טבלה מסויימתimage_thumb4

אחרי שהבנו איך למנוע יצירה אוטומטית ע"י מנגנון ה Dynamic Data, אנחנו יכולים עכשיו ליצור את דפי הניהול משלנו עבור אובייקטים מסויימים בשכבת הנתונים, במקרה של הפרוייקט שלי, LINQ to SQL.
כדי לעשות זאת,  נסתכל על מבנה הפרוייקט כפי שנוצר לי אוטומטית.
ניתן לראות, שיש שתי תיקיות שצבעתי:
PageTemplates - מכיל תבניות לדפים שמשמשים לייצור אוטומטי של ממשק הניהול ה WEB-י לאובייקטים של מסד הנתונים. כאשר צריך איפשהו לייצר באופן אוטומטי, הוא יעשה לפי התבנית הזאת.

מנגד, CustomPages, משמש אותי כדי לשים חלופות שלי לאותן תבניות ברירת מחדל. אם עבור כל האובייקטים בDB צריך להיות סגנון מסויים של דפי ניהול, אני אשים אותם בדפים של התבניות הקבועות. את החריגים ויוצאי הדופן, אני אשים ב CustomPages. מנגנון ה Dynamic Data יידע לגשת לדפים ששמתי ב CustomPages עבור האובייקטים ממסד הנתונים שאני אקבע, ולא לעבוד עם התבניות הקבועות.

כדי לעשות זאת, יש להוסיף תיקייה לתיקייה CustomPages, שנושאת את שם אובייקט מסד הנתונים (במקרה שלנו, טבלה) שאנו רוצים לציין שתיקייה זאת תכיל את הדפים המיוחדים עבורו.
אני יצרתי תיקייה בשם Products, שתחליף את התבניות ברירת המחדל רק עבור הטבלה Products.

בתוך התיקייה הזאת אני אצור Web Form חדש בשם ListDetails.aspx (חשוב שזה יהיה בשם הזה, כי כך נקבע בניתובים בקובץ global.asax). בינתיים הוא יהיה ריק ויכיל רק כותרת. עכשיו, כשאני אכנס ב browser ואלך במסך הראשי בתפריט ל Products, אגיע לדף המותאם שלי עם הכותרת.

image_thumb5

העבודה עם הנתונים עצמם

מה שיש לי בינתיים, זה כותרת. אבל אני ארצה גם לשים פה קוד שיאפשר לנהל את הנתונים. בגרסאות הקודמות, כולל עד הCTP האחרון, היו controls מיוחדים. פשוט הייתי שם אותם, וישר הם היו עובדים. היתרון היה שזה היה קל וללא עבודה. החיסרון היה, שיכולת ההתאמה של זה, הייתה נמוכה יחסית ולשלב את זה בפרוייקט קיים היה מלאכה כמעט בלתי אפשרית.
לכן, בגרסא הזאת, עובדים עם אותם ה controls הרגילים לעבודה עם Data ועם control חדש נוסף, בשם Dynamic Data Manager.

למעשה, אם נסתכל על הקוד ב Design, נראה את הדבר הבא (לחצו להגדלה):

    5  <h1>

    6         Products</h1>

    7     <asp:DynamicDataManager ID="DynamicDataManager1" runat="server" EnableQueryStringSelection="true"

    8         AutoLoadForeignKeys="true" />

    9     <asp:GridView ID="GridView1" runat="server" DataSourceID="GridDataSource" AutoGenerateSelectButton="True"

   10         AutoGenerateEditButton="True" AutoGenerateDeleteButton="true" AllowPaging="True"

   11         AllowSorting="True" CssClass="gridview" AlternatingRowStyle-CssClass="even">

   12         <PagerStyle CssClass="Footer" />

   13     </asp:GridView>

   14     <asp:LinqDataSource ID="GridDataSource" runat="server" EnableDelete="true" EnableUpdate="true">

   15     </asp:LinqDataSource>

 

כפי שניתן לראות, מדובר בקוד סטנדרטי לחלוטין, הכי פשוט שאפשר (לא כללתי validators וכו'). הדבר היחיד שמקשר בין זה ל Dynamic Data זה ה DynamicDataManaget. למעשה, ב code-behind באירוע Page_Init, אני משתמש במתודה RegisterControl ומעביר אליה את ה GridView1 כדי לרשום אותו.

מאחורי הקלעים, ה DynamicDataManager עושה את כל העבודה השחורה - מבין באיזה context נמצאים ומידע של איזה טבלה רוצים לקבל ומעביר אותו. כשמבצעים איזושהי פעולה, הוא יודע לקבל אותה ולעדכן בפועל בDB, הוא למעשה מנהל הכל.
היתרון הוא, שבכך שאנחנו משתמשים ב controls רגילים, נפתחים לנו כל מיני אפשרויות חדשות: החל משימוש ב controls מעוצבים של צד שלישי שקיימים כבר כחלק מה Dynamic Data Application ועד היכולת לשלב בקלות Dynamic Data גם באפליקציות קיימות.

Fields

המנגנון של Dynamic Data משתמש ב user controls כדי לקבוע את דרך התצוגה של שדות שונים בDB. ה user controls הללו מאוכסנים בתיקייה FieldsTemplate, וניתן לשנות אותם. ניתן לשנות את הקיימים, או להוסיף שדות חדשים. כאשר, במידה ומוסיפים user control חדש, ורוצים לקבוע שתצוגה של type מסויים תהיה באמצעות ה user control הזה, משתמשים ב RenderHintAttribute, שאותו שמים מעל ה partial class שיוצרים לאובייקט שמייצג את הטבלה שבה אנו רוצים לקבוע זאת.

למשל, ניצור user control פשוט שנקבע שהוא זה שיציג שדות טקסט. ניצור user control שיורש מ FieldTemplateUserControl, ה base class ממנו יורשים כל ה Dynamic Fields.

    1 <%@ Control Language="C#" CodeBehind="RedText.ascx.cs" Inherits="dynamicdemo.RedTextField" %>

    2 

    3 <font color="red"><%# FieldValueString %></font>

למעשה, מה שאנחנו עושים זה רק להדפיס את הטקסט בצבע אדום. עכשיו, נגיד שזה ישתלב בתצוגה של Products, באמצעות UIHintAttribute. במקום לשים את ה Attribute ישר מעל ההצהרה של ה class בקבצים של LINQ to SQL, ניצור partial class שעליו נשים את ה MetadataTypeAttribute כדי לציין את השינויים שעשינו ב class אחר כשינויים שאמורים להשתלב:

    1 using System.ComponentModel.DataAnnotations;

    2 

    3 namespace dynamicdemo

    4 {

    5     [MetadataType(typeof(ProductMetaData))]

    6     public partial class Product

    7     {

    8 

    9     }

   10     public class ProductMetaData

   11     {

   12         [UIHint("RedText")]

   13         public string ProductName { get; set; }

   14     }

   15 }

כפי שניתן לראות בקוד, ההגדרה שלנו היא שהמידע שנמצא ב ProductMetaData ישתלב בתצוגה של Product.

בנוסף, אנו אומרים שהרינדור של השדה ProductName, יתבצע עם ה user control שנקרא RedText. ובאמת, אם נציג הכל, נראה שהטקסט של שם המוצר מוצג באדום:

 

image_thumb19

כדי להקל הוספת Field משלכם, ישנו Item Template של Dynamic Field.

התאמת הנתונים המוצגים

באמצעות הטריק שהראינו קודם, אנחנו יכולים לשלוט גם על אילו שדות מהאובייקטים השונים יוצגו. בדוגמא הבאה, הוספתי לproperty של ProductName את ה ScaffoldAttribute והגדרתי שיהיה שווה ל false. זה יגרום לכך שבעוד שכל נתוני הטבלה יוצגו, הנתון של שם המוצר, לא יוצג:

    5 [MetadataType(typeof(ProductMetaData))]

    6     public partial class Product

    7     {

    8 

    9     }

   10     public class ProductMetaData

   11     {

   12         [Scaffold(false)]

   13         public string ProductName { get; set; }

   14     }

באפשרותנו, כמובן, ללכת בכיוון ההפוך. להגדיר ב global.asax, כאשר אנחנו רושמים את המודל שלנו, שה Scaffold יהיה false, ולאפשר אך ורק לתצוגה את השדות שאנחנו מעוניינים בהם.
בצורה הזאת, ניתן להסיר נתונים מתצוגה, בלי להסיר אותם בפועל משכבת הDAL.

התאמה ברמת ה Master Page והCSS

פעמים רבות, אין באמת צורך לבצע התאמה לוגית, או התאמת תצוגה ברמה מתקדמת כפי שעשינו עכשיו. לעיתים, נרצה רק קצת לשנות את העיצוב, אולי להטמיע את החלקים הללו בתוך אתר אחר. במקרה זה, ניתן לערוך רק את ה Master Page וקובץ הCSS.

סיכום

גרסאת ה Dynamic Data הכלולה ב Service Pack 1 עבור .NET 3.5 ו-Visual Studio 2008 מאפשרת לנו קאסטומיזציה ברמה גבוהה יותר מגרסאות קודמות.
בגלל שהעבודה בגרסא זו אינה באמצעות DynamicControls מיוחדים, אלא מול ה controls ה"רגילים", העבודה הרבה יותר גמישה, ההתאמה האישית הרבה יותר פשוטה ושילוב באפליקציה קיימת הופך להיות קל מבעבר.

בהצלחה!

Screencast: איך ליצור Dynamic Data Web Application

Dynamic Data, המוכר לנו מ ASP.NET 3.5 Extensions, עבר מספר שינויים, וכעת הוא חלק מ .NET 3.5 Service Pack 1, שהושק בתאריך 12 במאי בגרסאת בטא ראשונה לציבור.
ב Screencast הזה, מוסבר נושא יצירת Dynamic Data Web Application, יתרונות השימוש בו, האפשרות לעבוד הן מול LINQ to SQL והן מול ADO.NET Entities Framework והסבר קצר בנושא קאסטומיזציה.
 
לצפייה בסרטון (10 דקות) לחץ כאן.

Visual Studio 2008 & .NET 3.5 Service Pack 1 יצא בגרסאת beta

לפני דקות ספורות, הוכרז על יציאת גרסאת הבטא הראשונה ל Service Pack 1 עבור .NET 3.5 ו- Visual Studio 2008.
חבילת השירות הזו, לא משנה שום דבר קיים ולא שוברת תאימות כלל. אולם, היא מוסיפה מספר כלים חדשים, שעד עכשיו היו בגרסאות CTP כחלק מחבילות שונות - כמו למשל Dynamic Data Applications ו- ADO.NET Entity Framework.

בנוסף, נוספו מספר assemblies חדשים, חלקם כחלק מהפיצ'רים שהוזכרו קודם, וחלקם ככלים שניתנו למפתחים (למשל, System.Web.Routing).

ניתן להוריד ולהתקין את Service Pack 1 בגרסאת beta מכאן.
מומלץ בחום, להתקין רק על מחשב שישמש לטסטינג, או לחלופין, על Virtual PC. להזכירכם, מדובר בגרסאת בטא, שלא מתיימרת להיות יציבה.

בהצלחה.

שילוב URL Rewriting ע"י System.Web.Routing

URL Rewriting המבוסס על System.Web.Routing

מבוא

System.Web.Routing הוא אחד מה assemblies החדשים שהתווספו כחלק מ Visual Studio 2008 & .NET 3.5 Service Pack 1.
מדובר במנגנון המבוסס על זה שקיים בגרסאות ה preview של ASP.NET MVC, שהופרד ממעטפת הMVC, כך שיוכל לשמש באופן עצמאי גם באפליקציות Web Forms.
בנוסף, מנגנון הניתוב שפועל ב Dynamic Data Applications שהתווספו גם הם כחלק מחבילת שירות זאת מבוסס על  System.Web.Routing.

בפוסט זה נלמד כיצד לבנות, צעד אחר צעד, מנגנון URL Rewriting המובסס על System.Web.Routing.

המטרה

המטרה בפוסט הזה, זה להדגים בניית מנגנון URL Rewrtiting שפועל בצורה מאד פשוטה - בעת עליית האפליקציה הוא טוען מהDB את המיפויים המבוקשים, מי מפנה למי.
המיפויים האלה, הם אלה שישמשו את האפליקציה שלנו. בנוסף, נרצה דרך נוחה לעבוד מהעמודים שקיבלו את ההפנייה עם הנתונים השונים.

למה צריך URL Rewriting?

כאשר בונים כיום אפליקציות WEB, מקובל להתייחס לנושא שבעבר לא זכה להתייחסות רבה - SEO (ר"ת Search Engine Optimizing), ובשפת הקודש - מיטוב (שיפור) למען מנועי חיפוש. בעבר, כתובות אתרים רבות היו מכילות שורות פרמטרים שהועברו ב QueryString שהפכו את השימוש בכתובת לפחות ידידותי למנועי החיפוש.למשל, הכתובת הזאת:

http://www.MyOnlineShop.com/product.asp?action=buy&productId=1010&referrer=5060

מנוע החיפוש, לא יכול לקבל הרבה מידע מכתובת כזאת, וגם למשתמש שרוצה, מסיבה זו או אחרת, לזכור את הכתובת, יהיה הרבה יותר קשה לזכור אותה. לעומת זאת, כתובת כזאת, תהיה למשתמש הרבה יותר נוחה, ובעיקר, תתאים יותר למנוע החיפוש:

http://www.MyOnlineShop.com/Product/ProductName/Buy - תהיה הרבה יותר ידידותית.

עד היום, כדי לעשות זאת, היה לא פעם צריך לעבוד קשה. באמצעות System.Web.Routing, העבודה הופכת לקלה הרבה יותר.

התיאוריה

כשאנחנו מדברים על בניית מנגנון ניתוב (URL Rewriting) המבוסס על System.Web.Routing, אנחנו מדברים על HttpModule שפועל עבורנו מאחורי הקלעים.
למעשה, System.Web.Routing מכיל מנגנון שיודע "לתפוס" את הפניות ולבצע ברמת השרת את הפעולות שאנחנו מגדירים.
כלומר, אם אנחנו רוצים, ניתן לעשות כל מיני פעולות נוספות, חוץ מההפנייה. במאמר זה, נתמקד בעיקר בהפניות פשוטות.

כדי לממש מנגנון הפנייה, אנחנו צריכים לבצע מספר פעולות:

  1. להודיע לשרת שאנחנו עובדים עם המנגנונים של System.Web.Routing
  2. לרשום את הניתובים (מי מפנה למי)
  3. לממש את מנגנון הניתוב בצורה שיתאים לנו.

המעשה

1. הוספת ה HttpModule המתאים ב web.config

לפני הכל, אנחנו חייבים להגדיר ב web.config, במקטע של HttpModules שאנחנו מעוניינים לעבוד עם הראוטינג.
<add name="urlRouting" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing" />

2. הגדרת מסד הנתונים

מסד הנתונים שלי מכיל טבלה אחת בלבד, שמכילה 3 שדות: ID, מקור ולאן להפנות. את העבודה מול מסד הנתונים אני עושה באמצעות LINQ to SQL.

3. קביעת המיפויים

את קביעת המיפויים עצמה, אנחנו מבצעים בקובץ global.asax, ב event של Application_Start. קוד קביעת המיפויים נראה כך :

   15 protected void Application_Start(object sender, EventArgs e)

   16         {

   17             using (var db = new RoutingDataContext())

   18             {

   19                 foreach (var item in db.Routes)

   20                 {

   21                     RouteTable.Routes.Add(item.ID.ToString(), new System.Web.Routing.Route

   22                         (item.OriginalUrl.Trim(), new SampleRoutingHandler(item.RouteTo.Trim())));

   23                 }

   24             }

   25             RouteTable.Routes.RouteExistingFiles = true;

   26         }

למעשה, באמצעות LINQ to SQL, הקוד עובר על כל הערכים בטבלה Routes, ומכניס אותם ל RouteTable. הטבלה Routes נראית כך:

image

השדה OriginalUrl מכיל את מבנה הכתובת כפי שאני מצפה שהמשתמש יקיש אותו, כאשר שמות המוקפים בסוגריים מסולסלים, משמע שמות של פרמטרים. כלומר, אני מצפה שהמשתמש יגיע לכתובת Account/4 או כל מספר אחר, כאשר את ה-4 אני רוצה לקבל בתור פרמטר שה value שלו 4 וה key הוא id.
אני מעוניין שהדף שייקח את האחריות על המידע במקרה הזה, הוא MyPage.aspx.

הלוגיקה

System.Web.Routing, לא מספק מנגנון הפנייה מלא, אולם הוא מספק את כל מה שנדרש תשתיתית לבניית מנגנון URL Rewriting שיתאים לצרכינו, כפי שתיארנו אותם בהתחלה.
כדי באמת לבנות את פעולת ההפנייה עצמה, אנחנו צריכים ליצור class שיורש מ System.Web.Routing.IRouteHandler. לאינטרפייס הזה, יש רק מתודה אחת שאנחנו צריכים לממש, GetHttpHandler שמקבלת אובייקט System.Web.Routing.RequestContext ומחזירה IHttpHandler.

RequestContext, מאפשר לנו גישה לנתונים שהועברו לדף המקורי, כלומר, ל HttpContext שלו, ובנוסף מאפשר לנו לגשת ל RouteData, נתוני ההפנייה.

System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath

המתודה הסטטית הזאת, היא עיקר הלוגיקה שלנו.למעשה, היא מקבלת שני פרמטרים: string שמציין את הנתיב הוירטואלי של הרכיב WEB (במקרה שלנו, דף) שלו נרצה לעשות build ופרמטר שמציין את ה Type של אותו רכיב WEB, במקרה שלנו, ה type של Page.

הקוד של המחלקה שיורשת מ IRouteHandler

למעשה, ברמה הבסיסית, ככה צריך להיראות ה Class שלנו שמכיל את לוגיקת ה Routing (לחצו להגדלה):

   11 public class SampleRoutingHandler : IRouteHandler

   12     {

   13         private string WhereToRoute;

   14 

   15         public SampleRoutingHandler(string dest)

   16         {

   17             WhereToRoute = dest;

   18         }

   19 

   20         #region IRouteHandler Members

   21 

   22         public IHttpHandler GetHttpHandler(RequestContext requestContext)

   23         {

   24 

   25             return (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath

   26                 (WhereToRoute, typeof(Page));

   27 

   28         }

   29 

   30         #endregion

   31     }

 

הקוד הזה, בהחלט מכיל כל מה שנחוץ להפנייה בסיסית, אבל לא עונה לנו על כל הצרכים. אין לנו פה שום התייחסות לפרמטרים שמועברים לכתובת ידידותית.
אבל לפני שנדאג לזה, בואו נבין מה עושה הקוד - ביצירת המופע של המחלקה הזאת, הקוד מקבל למעשה את הנתיב האמיתי שאמור להיות מורץ. כלומר, את הכתובת שאליה מפנים. מובן, שהמשתמש לא יראה שלמעשה מורץ דף אחר ושהכתובת אליה הוא נכנס לא באמת קיימת, זה מתרחש מאחורי הקלעים, ובסופו של דבר, הוא באמת מקבל תשובה מהכתובת הידידותית.
במתודה GetHttpHandler, אני למעשה מריץ את הדף האמיתי שאמור להיות מורץ, ובסופו של דבר מחזיר את תוצאות ההרצה.

עכשיו, אחרי שהבנו מה עושה הקוד הזה נרצה להוסיף תמיכה בפרמטרים. לצורך העניין, נשנה את הקוד קצת, כך שעכשיו הוא נראה כך:

 

   11 public class SampleRoutingHandler : IRouteHandler

   12     {

   13         private string WhereToRoute;

   14 

   15         public SampleRoutingHandler(string dest)

   16         {

   17             WhereToRoute = dest;

   18         }

   19 

   20         #region IRouteHandler Members

   21 

   22         public IHttpHandler GetHttpHandler(RequestContext requestContext)

   23         {

   24             foreach (var item in requestContext.RouteData.Values)

   25             {

   26                 requestContext.HttpContext.Items.Add(item.Key, item.Value);

   27 

   28             }

   29             return (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath

   30                 (WhereToRoute, typeof(Page));

   31 

   32         }

   33 

   34         #endregion

   35     }

 

הקוד שהוספנו, למעשה רץ בלולאה על כל הפרמטרים שהגיעו לכתובת הידידותית, אלה שבטבלאת המיפויים הקפתי את שמותיהם בסוגריים מסולסלות, ומוסיף אותם ל HttpContext.Items, שישמש את הדף שיקבל את האחריות על ביצוע הפעולות שרציתי, זה שנקבע שאליו ימופו הכתובות הידידותיות.

השלב האחרון, זה לכתוב דף שישתמש במידע. נכתוב דף בשם Search.aspx, שאחראי על החיפוש, שיעבוד עם אותם הפרמטרים:

image

כאשר נריץ את הדף הזה עכשיו, נראה את הפלט הבא:

image image (גם בעברית)

ניתן לראות שזה עובד - הצלחנו לקבל את הפרמטרים שמועברים באמצעות הכתובת הידידותית, ביצוע הפעולה הועבר לדף Search.aspx מאחורי הקלעים, בלי שהמשתמש ירגיש (ובסופו של דבר, לא באמת "העברנו", אלא החזרנו את ה build של הדף Search.aspx כתשובה לכתובת החדשה והידידותית).

סיכום

במאמר הזה ראינו איך ניתן בשלבים פשוטים לבנות מנגנון ניתוב כתובות שיאפשר למשתמשים שלנו (ובעיקר למנועי החיפוש) לעבוד מול כתובות ידידותיות.
ראינו איך ניתן לבסס את המנגנון הזה על מסד הנתונים, ואיך לבנות class שיורש מ System.Web.Routing.IRouteHandler כדי לממש לוגיקה לפעולת הניתוב.

אתם יכולים להוריד את Visual Studio 2008 & .NET 3.5 Service Pack 1 בגרסאת beta ולהתנסות.

בהצלחה!

מחשב חדש והתרסקות ראשונה של ויסטה

קיבלתי היום את המחשב החדש שלי. Quad Core Q6600 עם 4GB RAM. מחשב, שלכל הדעות חייב להטיס ויסטה, Visual Studio וכל מה שאני אעמיס עליו.
מיד כשהוא הגיע, הבהרתי לו את זה. אמרתי שאני לא אסבול עיכובים. הוא חייב לטוס, עם המפרט הזה ו Vista Ultimate 64 bit (ששיבחו אותה פה). כנראה, שלא הייתי ברור מספיק שהטיסה צריכה להיות במבנה הנורמלי - ממריאים בהתחלה, טסים ישר (קצת תיקוני גובה לכל היותר), ורק כשאני אומר לו לכבות את עצמו, עושים נחיתה מסודרת.
הוא לא ממש הבין את זה, ולראייה, הוא אירגן לי התרסקות. לכל המשמיצים והמלעיזים, אני משתמש בויסטה הרבה לפני שהיא בכלל יצאה בבטא. וזאת הפעם הראשונה שיש לי התרסקות (מסך כחול, כתיבת dump לדיסק, ואתחול אוטומטי של המחשב - קלאסה).

אולי לא צריך לשפוט על סמך התרסקות אחת (שבדיעבד, אני משער שנבעה מהתקנת עדכון לדרייבר של המאיץ הגרפי), אבל לדקה וחצי חלף לי הרהור לגבי העניין הזה של מערכת 64 ביט. על העובדה שאפילו האינטרנט אקסגפלורר, מגיעה בשתי גרסאות - 32 ביט ו-64 ביט, בתוך המערכת 64 ביט. הסיבה? ה 64 ביט לא ממש תומך בפלאש ויש לו עוד כל מיני מוזרויות משלו. אמנם, האקספלורר 32 ביט עובד מעולה. אבל....

בכל אופן, למעט הבעייה המסויימת הזאת, עושה רושם שבהחלט המערכת טסה. איזה כיף שה Visual Studio מחכה לי לפעולות ולא להיפך :-)

גיליון הMSDN Pulse החדש + מאמר בנושא חידושים ב C# 3.0

גיליון MSDN Pulse החדש, של מאי, יצא. כפי שגיא פרסם בבלוג שלו, בעתיד יישלח הגיליון רק לאלה שנרשמו לקהילת המפתחים ולגיליון. מומלץ לוודא כבר עכשיו שנרשמתם כנדרש.
הגיליו הנוכחי מכיל טיפ שכתבתי, ובנוסף, מקשר למאמר שמתפרסם במסגרת אתר המאמרים החדש של מיקרוסופט ישראל בנושא פיתוח.
נושא המאמר הוא חידושים ב C# 3.0, מומלץ במיוחד לאלה שעוד לא יצא להם להתנסות בגרסא החדשה.