יצירת מנגנון shortcut url באמצעות מנגנון ה – routing של asp.net

21 בנובמבר 2009

6 תגובות

 


יחד עם ה – MVC הגיע dll מאוד נחמד ששמו System.Web.Routing, הוא משמש מנגנון מאוד מרכזי ב – MVC כדי להפנות לדף המתאים לפי הבקשה .

היות שהוא כל כך מוצלח ניתן להשתמש בו גם ב – asp.net לצרכים אחרים.

 

(חשוב לציין שיכול שמן הסתם רוב הלינקים בפוסט לא יעבדו – אלא הם הדגמה למה אפשר לעשות)

 

לדוגמא – אפשר להשתמש בו כדי לייצר מנגנון של Shortcut url – כלומר במקום שיצטרכו לכתוב http://www.sela.co.il/syl/syllabus.aspx?CourseCode=c2&CategoryID=165 אפשר לכתוב http://www.sela.co.il/url/syllabus/c2

 

או אפילו אפשר לייצר קיצורי דרך לאתרים שהם לא בדומיין שלנו – לדוגמא במקום להגיע לבלוג שלי עם הלינק http://blogs.microsoft.co.il/blogs/shlomo/ אפשר להגיע אליו דרך http://www.sela.co.il/url/shlomo

 

אז כמובן שמן הסתם תהיה מערכת ניהול ויש לנו בסיס נתונים או קובץ XML שבו נשמרים כל קיצורי הדרך ולהיכן זה צריך להגיע – אבל מה שחשוב זה מנגנון ה – routing ואיך זה עובד.

(בשבוע הקרוב אני אעלה בעז"ה ל – CODE PLEX פרויקט של ה – routing יחד עם מנגנון הניהול שלו – כשזה יעלה אני אפרסם את הלינק)

 

לבנתיים נראה איך ה – routing עובד

 

אז ככה – דבר ראשון יש להוסיף לפרויקט שלכם שני reference

1. System.Web.Abstractions

2. System.Web.Routing

 

לאחר מכן ב – Global.asax בארוע Application_Start צריך לרשום מי יהיה אחראי לטפל בבקשות שיגיעו

 


protected void Application_Start(object sender, EventArgs e)
{
    List<string> titleData = Dal.GetAllTitles();
 
    WebFormRouteHandler webFormRouteHandler = new WebFormRouteHandler();
 
    RouteTable.Routes.Add("4D81C761-A6ED-450f-8618-618A17EFBA99", 
        new Route("4D81C761-A6ED-450f-8618-618A17EFBA99", webFormRouteHandler));
 
    for (int i = 0; i < titleData.Count; i++)
    {
        RouteTable.Routes.Add(titleData[i], new Route(titleData[i], webFormRouteHandler));
    }
}

 

ואני אסביר –

בשלב ראשון אני מקבל מבסיס הנתונים את כל קיצורי הדרך – לדוגמא syllabus/c2.

 

אני יוצר מופע של WebFormRouteHandler (עוד מעט נראה אותו).

 

נתעלם כרגע מהשורה הבאה ונדלג לללואה. (נתייחס לזה בהמשך)

 

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

 

 

בפועל מה שהקוד עושה זה, להגדיר כשיגיע request שמכיל ב – url את קיצור הדרך (בדוגמה שלנו – syllabus/c2) מי שיטפל בבקשה זה לא המנגנון הרגיל של asp.net אלא המחלקה שיצרנו – כלומר המופע של WebFormRouteHandler).

 

 

כעת נראה את הקוד של המחלקה WebFormRouteHandler

 


public class WebFormRouteHandler : IRouteHandler
{
    #region IRouteHandler Members
 
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new RoutingHandler();
    }
 
    #endregion
}

 

כמו שאנחנו רואים – אין בו הרבה קוד, בסך הכל מימוש של interface בשם IRouteHandler (שזה מה שה – RouteTable מקבל) ובמימוש שלו צריך להחזיר מישהו שמממש את IHttpHandler – כשלמעשה אנחנו מחזירים מופע של RoutingHandler)

הנה המחלקה

 


public class RoutingHandler : UrlRoutingHandler
{
    protected override void VerifyAndProcessRequest(IHttpHandler httpHandler, 
                                                    HttpContextBase httpContext)
    {
        string tempTitle = httpContext.Request.Url.AbsolutePath;
 
        if (tempTitle.Contains("4D81C761-A6ED-450f-8618-618A17EFBA99"))
        {
            Global.Register();
            return;
        }
 
        tempTitle = tempTitle.Remove(0, 1);
        tempTitle = tempTitle.Substring(tempTitle.IndexOf('/') + 1);
 
        string titleData = Dal.GetUrl(tempTitle);
 
        httpContext.Response.Redirect(titleData);
    }
}

 

המחלקה יורשת מ – UrlRoutingHandler שמממשת את IHttpHandler – אנחנו נעשה override ל – VerifyAndProcessRequest שהיא המתודה שצריכה להחליט לאיפה לנווט ומה להחזיר כתשובה לבקשה.

 

בהתחלה אני לוקח את ה – absolutePath.

 

נדלג כרגע על הבדיקה עם ה – GUID (נתייחס בהמשך)

 

נניח שהבקשה תהיה http://www.sela.co.il/url/syllabus/c2

 

 המשתנה tempTitle יהיה שווה ל – url/syllabus/c2/ (זה ה – absolutePath)

 

אני מעיף את תו ה – / הראשון. ואז את כל השאר עד תו ה – / השני – כלומר אני אשאר עם syllabus/c2 (שזה כזכור קיצור הדרך)

 

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

 

 

כמעט סיימנו – נשארו דברים.

הראשון איך אומרים ל – IIS שאנחנו מטפלים בבקשות – כלומר, כשמגיעה בקשה לשרת שנראית: http://www.sela.co.il/url/syllabus/c2 אזי IIS אמור לחפש תיקייה שנקראת c2 תחת תיקייה שנקראת syllabus בתוך ה – virtual directory שנקרא url – וכמובן הוא לא ימצא, ולכן אנחנו צריכים להגדיר ל – IIS שלא הוא מטפל בבקשות אלא אנחנו.

 

כדי לעשות זאת זה תלוי האם מדובר ב – IIS 7 או בגרסה קודמת, במידה שמדובר ב – IIS 7 זה הגדרה פשוטה בקובץ הקונפיג, בחלק התחתון של ה – web.config יש מקטע שנקרא system.webServer בתוכו יש מקטע שנקרא modules, צריך להוסיף זם את הקוד הבא:

 


<add name="UrlRoutingModule" 
     type="System.Web.Routing.UrlRoutingModule, 
            System.Web.Routing, Version=3.5.0.0, 
            Culture=neutral, 
            PublicKeyToken=31BF3856AD364E35" />

 

 

בנוסף במקטע של handlers צריך להוסיף את הקוד הבא:

 


<add name="UrlRoutingHandler" 
     preCondition="integratedMode" 
     verb="*" 
     path="UrlRouting.axd" 
     type="Routing.RoutingHandler, Routing"/>

 

כשצריך לשים לב לחלק של ה – type שזה צריך להיות האובייקט שלנו והשם של ה – namespace שלנו.

 

וזה יעבוד.

 

במידה ומדובר על גרסאות קודמות של IIS (הגרסה הכי מוקדמת שזה יכול לעבוד זה על server 2003 – צריך לקנפג את זה גם בקונפיג וגם ב – IIS.

בקונפיג תחת המקטע של httpHandlers צריך להוסיף

 


<add verb="*" path="*" type="Routing.RoutingHandler" />

 

ב – IIS  (אין לי כרגע windows server 2003 אז הייתי צריך לחפש את התמונות בגוגל – ולכן תתעלמו מהעיגולים האדומים או מההגדרות שיש בתמונות ותתיחסו רק למה שאני כותב).

 

שלב ראשון אחרי הגדרת ה – virtual directory נלחץ על configuration

configuration

 

(העיגול מסביב ל – Script and Execute הגיע מהתמונה המקורית – אין לזה קשר על מה שאנחנו מדברים כרגע)

 

נקבל את החלון הבא:

wildcard

 

נלחץ על Insert כדי להגדיר ל – IIS מי מטפל בבקשות שנכנסות

wildcard

 

יש להכניס ב – execute את הנתיב של asp.net כמדומני שזה C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll אבל אני לא בטוח – אפשר תמיד לבדוק מה הנתיב של הסיומת של ה – aspx בחלון ה – Configuration.

לא לשכוח לוודא ש – Verify taht file exists לא מסומן.

 

 

הדבר האחרון שאני צריך להסביר – מה העניין עם ה – GUID ב – Applicatuin_Start וב – VerifyAndProcessRequest.

העניין הוא כזה – היות שאנחנו רושמים את כל קיצורי הדרך בזמן Application_Start, בזמן שנוסיף קיצורי דרך בבסיס הנתונים מנגנון ה – Routing לא יודע מזה ולכן זה לא ירשם ב – RouteTable עד שהאפליקצייה לא תמות (או שנעשה iisreset) ולכן הפיתרון היה לרשום ב – RouteTable מספר מיוחד שבמידה ומגיעים איתו זה ירענן את ה – RouteTable,

למעשה הקוד

 


RouteTable.Routes.Add("4D81C761-A6ED-450f-8618-618A17EFBA99",
    new Route("4D81C761-A6ED-450f-8618-618A17EFBA99", webFormRouteHandler));

 

גרם לכך שבמידה ויגיעו ל – http://sela.co.il/url/4D81C761-A6ED-450f-8618-618A17EFBA99 (כמובן שזה לא המספר האמיתי) – אנחנו נגיע לקוד הבא

 


string tempTitle = httpContext.Request.Url.AbsolutePath;
 
if (tempTitle.Contains("4D81C761-A6ED-450f-8618-618A17EFBA99"))
{
    Global.Register();
    return;
}

הקוד יושב במתודת VerifyAndProcessRequest הוא יבדוק האם ההפנייה היא עם ה – GUID – במידה וכן נפעיל מתודה סטטית ב – Global.asax שמעדכנת את ה – routeTable מבסיס הנתונים.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

6 תגובות

  1. גיא22 בנובמבר 2009 ב 13:33

    פוסט מאוד מעניין וחשוב.

    אני תוך כדי עבודה עם isapi filter שעושה url rewiting וקצת הסתבכתי עם זה בגלל כל ה-regular expressions שם ורציתי אולי לעבור לעבוד עם הפתרון הזה אבל אצלי זה דינמי ואני לא יכול לעשות IISReset כדי שהטבלה של ה-Routing תתעדכן. לא בדיוק הבנתי את העניין הזה של ה-GUID. מה זו הפונקציה Register ב-Global? אתה מתכוון לכך שאתה מאפס זאת באופן ייזום ע"י כך שאתה קורא לכתובת עם ה-GUID הנ"ל ב-url?

    תודה
    גיא

    הגב
  2. גיא22 בנובמבר 2009 ב 13:36

    הפוסט מאוד מעניין וחשוב.

    אני עובד עכשיו עם isapi filter שמצאתי ב-Code Plex וקצת הסתבכתי איתו וחשבתי לעבוד עם הריון הזה.

    אצלי הטבלה היא דינמית ולא הגיוני לעשות IISRESET כל פעם על מנת שהיא תתעדכן. לצערי לא הבנתי עד הסוף מה הריון של ה-GUID? אתה פונה לדף איתו באופן יזום על מנת לעדכן את הטבלה? מי יפנה לדף עם ה-GUID הזה?

    תודה
    גיא

    הגב
  3. shlomo22 בנובמבר 2009 ב 15:28

    בהחלט, הרעיון הוא שבאופן יזום תגלוש לאתר שלך עם ה – GUID וזה למעשה יפעיל מתודה מסויימת שתעדכן את ה – RouteTable מבסיס הנתונים

    הגב
  4. גיא23 בנובמבר 2009 ב 22:17

    קצת בעייתי לטעמי אבל מה לעשות שזהו המנגנון.
    אם כך אני ממליץ להשתמש ב-isapi filter שקיים ב-Codeplex שעושה דבר דומה אבל לא מצריך אתחול של האפליקציה.

    תודה

    הגב
  5. Shlomo24 בנובמבר 2009 ב 9:28

    זה לא מאתחל את האפליקצייה זה רק מרפרשר את ה – RouteTable
    חוץ מזה זה הרבה יותר נוח מ – isapi-filter
    מדובר בקוד דוטנטי – אפשר למשל לבדוק סטיסטיקות וכו'

    הגב
  6. Moshe L2 בדצמבר 2009 ב 14:15

    הבעיה היא שהמודל הזה זולל לא מעט משאבים בשרת ויש לו Overhead לא קטן.

    הגב