DCSIMG
January 2007 - Posts - Justin myJustin = new Justin( Expriences.Current );

January 2007 - Posts

Question from Tapuz .Net forum: Updating ASP.Net Page display without refreshing

שאלה:

אני כותב ממשק הזנה לDB. משתמש ב gridview. עם asp.net2.
יש רשימת לקוחות ולכל לקוח יש רשימת פרוייקטים. כשבוחרים לקוח רשימת הפרוייקטים מסתננת לפי הבחירה.

מה הדרך הכי טובה להשתמש ליישם סינון אינטרקטיבי? (ajax? javascript? )
 למרות שאין לי זמן להכנס לזה, כנראה שאצטרך להשתמש ב AJAX. יש כל מיני מחלקות ותוספים לעבודה עם AJAX, על איזה אתם ממליצים?

 

תשובה:

ב-Microsoft AJAX קיים פקד חדש בשם UpdatePanel. בדיוק כמו Panel רגיל הוא מכיל בתוכו פקדים אחרים, אך בנוסף ליכולות של Panel רגיל יש לו יכולות AJAXיות.
כל פקד שנמצא בתוך ה-UpdatePanel יכול להתרפרש בצורה דינמית ע"י טריגרים מסויימים.
טריגרים לדוגמה ל-UpdatePanel שיגרמו לתוכן שלו להתרפרש: לחיצה כל כפתור, שינוי טקסט ב-TextBox, סימון CheckBox וכמו ששאלת בחירת ערך ב-DropDownList.
בתוך האירועים שמתאימים לטריגרים שמים את הקוד שרוצים שישנה את הפקדים בתוך ה-Panel.
למשל, במקרה שלנו יהיה לנו מחוץ ל-UpdatePanel פקד DropDownList רגיל לחלוטין.

        <asp:DropDownList ID="DropDownList1" runat="server">

            <asp:ListItem>www.JustinAngel.Net</asp:ListItem>

            <asp:ListItem>blogs.Microsoft.co.il</asp:ListItem>

        </asp:DropDownList>

 

נרצה ששינוי של ערך ב-DropDownList יגרום לשינוי כלשהו בדף ונרצה שהוא יהיה AJAXי ולכן נשנה קלות את הקוד של ה-DropDownList שישקף זאת

       <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">

            <asp:ListItem>www.JustinAngel.Net</asp:ListItem>

            <asp:ListItem>blogs.Microsoft.co.il</asp:ListItem>

        </asp:DropDownList>

נוסיף לדף UpdatePanel שאמרנו שנרצה שהפקדים בו ישתנו עם שינוי הערך הנבחר ב-DropDownList.

        <asp:UpdatePanel ID="UpdatePanel1" runat="server">

            <Triggers>

                <asp:AsyncPostBackTrigger ControlID="DropDownList1" EventName="SelectedIndexChanged" />

            </Triggers>

        </asp:UpdatePanel>

 

נכניס לתוך ה-UpdatePanel שלנו GridView שהמטרה שלה היא להציג לנו את הערך שנבחר כרגע ב-DropDownList:

        <asp:UpdatePanel ID="UpdatePanel1" runat="server">

            <Triggers>

                <asp:AsyncPostBackTrigger ControlID="DropDownList1" EventName="SelectedIndexChanged" />

            </Triggers>

            <ContentTemplate>

                <asp:GridView runat="server" ID="GridView1" />

            </ContentTemplate>

        </asp:UpdatePanel>

 

נדאג כי האירוע SelectedIndexChanged יקושר ל-GridView כך שידאג לשנות אותו לערך הנבחר:

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)

    {

        GridView1.DataSource = new string[] {DropDownList1.SelectedItem.Text};

        GridView1.DataBind();

    }

 

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

 

קישור: http://www.tapuz.co.il/tapuzforum/main/Viewmsg.asp?forum=831&msgid=91951541

Exprienced .Net developer looking for work (Résumé / CV included)

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

 

Question from Tapuz .Net forum: Using log4net logging in multiple projects at the same solution

שאלה:

שלום שלום לכולם,
אני בדיוק מקנפג באפליקציה כלשהי מערכת רישום אירועים (logging), ספציפית
אני משתמש ב-log4net אבל השאלות שעלו במוחי הן כלליות יותר.
את מודול רישום האירועים מקנפגים לרוב בקובץ הקונפיג' של האתר web.config.
לעתים תכופות יש באתר מודולים חיצוניים (בזמן פיתוח אילו פרוייקטים נוספים,
לאחר מכן אילו DLLים באתר. למשל מודול להצפנה שהוא פרוייקט נפרד לחלוטין. גם הוא רוצה לרשום אירועים.

שאלותיי הן: [שאלות ותשובות שזורות בתשובה לנוחות קריאה]

 

תשובה:

שאלה 1) האם מבחינה טכנית מודולים חיצוניים יוכלו לגשת ישירות להגדרות web.config? למשל  דרך ConfigurationManager?

מבחינה טכנית, קיימת ירושה בין קבצי קונפיגיורציה ברמות שונות. למשל קובץ ה-Web.config של כל אפליקציה יורש בהכרח את הקונפיגיורציה של ה-machine.config.
 
כל ספריית קוד יורשת את הקובץ קונפיגיורציה של הספריות קוד מעליה.
ולכן למשל, באפליקציית ASP.Net עם קובץ web.config או באפליקציה חלונאית עם קובץ App.config כל הכיוונים בקבצי קונפיגיורציה יהיו זמינים בגישה ל-App.config של הספריות שהן תלויות בהן. גם אם הקובץ קונפיוגרציה של הספריות התלויות לא קיים בפועל, עדיין תתקיים הירושה הזו.

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

 

מבחינת ארכיטוקטורה נהוג ליצור שכבת Common שנגישה לכל הפרוייקטים ב-Solution ושם לשים את ה-Logging.
כמובן שאם הלוגר הוא יותר ממחלקה אחת אלא מערך לוגי מורכב, עדיף ליצור פרוייקט שיהיה בשימוש ע"י ה-Common ויכיל את לוגיקת הלוגינג.

ב-log4net צריך ליצור מחלקה סטטית עם מופע סטטי של הלוגר לפי קובץ הקונפיגיורציה.

namespace Common

{

    public static class Log

    {

        public static ILog logger = log4net.LogManager.GetLogger(typeof(Log));

        private static ILog log

        {

            get

            {

                return logger;

            }

        }

        public static void Error(string message, System.Exception e)

        {

            if (log.IsErrorEnabled)

                log.Error(ReturnCallStrackInformation(message), e);

        }

    }

}

 

כמו כן, אישית, אני מעדיף שהמידע של אסמבליס חיצוניות לא יישב ב-Custom Sections בתוך ה-web.config שלי מחשש ששינוי בקונפיוגרציה לא חיונית יגרום לאתחול האפליקציה. למשל ב-ASP.Net אני יוצר קובץ Log4net.xml שיכיל את הקונפיגיורציה של log4net ולטעון אותו דרך application_start עם Watcher שידאג לטעון את השינויים אם יש כאלו.

    // in global.asax

    void Application_Start(object sender, EventArgs e)

    {

        DOMConfigurator.Configure(new System.IO.FileInfo(Server.MapPath("~/App_Data/log4net.xml")), true);

    }

 

בעבודה עם log4net וספריות תוכנה שונות, יש אפשרות לאתחל לוגרים שונים לאפליקציות שונות. כלומר, שלכל אפליקציה יהיה לוגר משלה לפי איזה לוגר היא מנסה לאתחל. למשל, הספרייה NHibenrate מנסה לאתחל לוגר בשם NHibernate ואם זה לא קיים מסתמכת על הברירת מחדל של Log4net (קונפיוגרציית root).

צריך לשקול את הצורך לבצע צעד כזה מול הצורך האמיתי לקבוע רמות לוגינג שונות לחלקים שונים של האפליקציה כנגד העלות התחזוקתית שתיווצר (מחלקות לוגינג שונות לכל חלק מהאפליקציה ולא לוגר מרכזי). למשל באמת במקרה של NHibernate באמת צריך תמיד לדאוג שהלוגר שלו יהיה מכובה אם רוצים שהאפליקציה תרוץ.

<root>

    <level value="Error"/>

    <appender-ref ref="MainAppender" />

</root>

<logger name="NHibernate" additivity="false">

    <level value="FATAL"/>

    <appender-ref ref="SomeLogAppender"/>

</logger>

 

קישור (המשך הדיון מומלץ בחום): http://www.tapuz.co.il/tapuzforum/main/Viewmsg.asp?forum=831&msgid=91944467

Question from Tapuz .Net forum: How to start an ASP.Net Async process from the Client?

שאלה:

בשעת הלחיצה אני יוצר thread שמפעיל פונקציה במחלקה אחרת , לפני הפעלת ה thread אני מגדיר delegate + ManualResetEvent ,עכשיו המשתמש יכול מצידו לסגור את הדף הזה אך כמובן להשאר באפליקציה.
הבעיה שלי היא שאני לא יודע באיזהאני אני אוכל לתפוס את הEvent שה Thread סיים ולהציג למשתמש הודעה?

 

תשובה:

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

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

Microsoft AJAX עושה בדיוק את מה שאתה מבקש.
AJAX מאפשר לך גישה א-סינכרונית לצד שרת למתודות ברמת הדף או ב-Webservice והוא דואג לביצוע הא-סינכרוני.

דבר ראשון תתקין Microsoft AJAX מהאתר ajax.asp.net (ההתקנה של Microsoft AJAX Library ושל December CTP).

תוסיף לדף <asp:ScriptManager>.

תוסיף מתודה ב-Code Behind שלך שתבצע את העבודה בצד-שרת.

    // in myPage.aspx.cs

    [WebMethod()]

    public static bool DoSomeHeavyLifiting()

    {

        // Do some very long calculations

        Thread.Sleep(10000);

        return true;

    }

עכשיו תצטרך לפנות למתודה הזו בצד-שרת מתוך ג'אווה סקריפט.
חלק א' יהיה להוסיף קריאה למתודה צד-שרת באמצעות לחיצה על למשל כפתור בצד-לקוח.
חלק ב' יהיה לתפוס את התוצאה מהצד שרת.

// in myPage.aspx

<asp:Button ID="btn1" runat="server" OnClientClick="CallPageMethod(); return false;" />

<script type="text/javascript">

function CallPageMethod()

{

   PageMethods.DoSomeHeavyLifiting(onFinishedHeavyLifting);

}

function onFinishedHeavyLifting(result)

{

   alert(result);

}

</script>

מה שקיבלנו למעשה זה את היכולת לדבר עם המתודות בצד-שרת מתוך ג'אווה סקריפט צד-לקוח וכל זה קורה כברירת מחדל בצורה א-סינכרונית.

עוד על תקשורת בין צד-שרת לצד-לקוח יהיה ניתן לשמוע בהרצאה שלי ב-31 לינואר כחלק מאירוע הענק של מיקרוסופט ה-Devleoper Academy.
ההרשמה לאירוע ולהרצאות חינם, אך מספר המקומות מוגבל ל-2,500 איש.

 

קישור: http://www.tapuz.co.il/tapuzforum/main/Viewmsg.asp?forum=831&msgid=91942269