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

November 2007 - Posts

Question from Tapuz .Net forum: Dynamically loaded UserControls disappear on PostBack

שאלה:

פקדי מסוג UserControls שהוספתי לדף נעלמים ב-PostBack, למה זה ומה ניתן לעשות כדי למנוע את זה?

 

תשובה:

(נכתבה בדוא"ל חצי שנה לפני שאלת השאלה, ציטוט מדוייק מתוך אוטלוק)

בהמשך למה שדיברנו אתמול על טעינה דינמית של User Controls  לדף.

אם לחזור על מה שאמרנו ועל הבעיה הספציפית:
1. יש לך בדף כפתור.
2. בלחיצה על הכפתור נטען UC1 דינמית.
3. בתוך UC1 יש כפתור.
4. בלחיצה על הכפתור בריצה בחזרה לשרת, אין שום דרך לזכור שבשלב "2" נוצר UC1 דינמי.
5. ולכן כתוצאה של "4" נקבל שאחרי ה-PostBack אחרי הלחיצה אין UC1 על הדף.

הבעיה הכללית יותר שלך הייתה ליצור UC בתוך UC.

תן לי להציע פתרון כללי – לבנות תשתית קטנה שתתלבש על הירושה מ-Page או UserControl שהתפקיד שלה יהיה לדאוג לבנות מחדש פקדים דינמיים.
כלומר, שלא תצטרך ידנית ברמת הדף להוסיף כל פעם מחדש את הפקדים שהוספת לפני PostBack.

נתחיל מדף ASP.Net פשוט:

image

כפתור, שלוחצים עליו – רץ קוד בשרת.

image

הקוד מוסיף UC שנטען דינמית.
ככה הדף נראה לפני לחיצה:

clip_image006[4]

וככה אחרי:

clip_image008[4]

שורה ראשונה: הפקד מדפיס את ה-ClientID.
שורה שנייה: סתם טקסט ב-Label וכפתור שנגיע עליו עוד שנייה.
שורה שלישית: TextBox וסתם כפתור שגורם PostBack (אין אירוע בצד השני)

אין שום דבר מיוחד ב-ASP.Net declarative של ה-UC:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" EnableViewState="true" Inherits="WebUserControl" %>
<div style="border: solid 5px black; padding: 5px; margin: 5px;">
<asp:Label EnableViewState="true"  ID="lblClientID" runat="server" Text="Label">Client ID: </asp:Label>  <br />
<asp:Label EnableViewState="true"  ID="Label1" runat="server" Text="Label">Hello world</asp:Label>
<asp:Button runat="server" ID="btnAddNewSonControlInPostack" OnClick="myBtn1_Click" Text="Add New Son Control In Postack"/><br />
<asp:TextBox runat="server" ID="tbx1" />
<asp:Button runat="server" ID="btnSomeButton" Text="Write something and textbox, press me and see what happends..." />
<br /></div>

נכניס קצת טקסט לתוך ה-TextBox ונלחץ על הכפתור לידו:

clip_image010[4]

ובטעינה חזרה השם שלי עדיין מופיע שם.

clip_image012[4]

שימו לב, לחצנו על כפתור ש"סתם" גורם ל-Postback (אין שום מתודה שנרשמה ללחיצה על הכפתור), היה PostBack מלא, לא כתבנו קוד ספציפי לטעון מחדש את ה-UC והוא נשאר על הדף עם ערכים של ViewState ו-PostBack.

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

נראה את הקוד שירוץ אם נלחץ Add New Son Controls In PostBack (הכפתור בשורה השנייה)

clip_image014[4]

יצירה של UC מקונן חדש (בתוך UC קיים), נתנו לו ID שאנחנו יודעים שלא חוזר על עצמו והוספנו לילדים של הפקד.
נלחץ על Add New Son Control In Postback (הכפתור בשורה השנייה) ונקבל:

clip_image016[4]

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

clip_image018[4]

לפי ה-ClientID אנחנו יכולים לראות שיש כאן רמות של קינון בין הפקד ההורה, לפקדים בנים ולפקדי בנים-של-בנים וגם בנים-של-בנים-של-בנים ואפשר להמשיך ככה לנצח.

אז מה הקסם מאחורי זה שיש לנו עדיין את אותם פקדים אחרי PostBack מלא?
קומפלט עם מידע שבא מה-ViewState ולטעון לתוכם מידע מה-PostBack?

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

image

ובצד השני, בטעינה של מידע Viewstate נראה: image

לא חשוב הקוד הספציפי, אלא חשוב שכאן ב-LoadViewState אנחנו קוראים את הערך שהכנסנו ב-SaveViewState.

מה קורה כאן מאחורי הקלעים?
נכניס "איזהשהו" ערך שמייצג את היררכיית ה-UC על הדף לתוך ה-ViewState, היה PostBAck, נקרא את אותו ערך ולפיו נבננה מחדש את היררכיית ה-UC בדף.

נראה מחלקה קטנה ופשוטה:

image

בעזרת המחלקה הזו נתעד UC – את הנתיב שבעזרתו טענו את קובץ ה-ASCX ואת ה-ID שלו על הדף.
בנוסף, נרשום בתוכו אם יש UCים נוספים מקוננים.

אז איך עובד ה-Save?

    private UserControlHierachy GetUserControlHierachy(UserControl controlToRebuildAndCheckIfHasNestedUserControls)

    {

        UserControlHierachy ReturnValue = new UserControlHierachy();

        ReturnValue.Path = controlToRebuildAndCheckIfHasNestedUserControls.AppRelativeVirtualPath;

        ReturnValue.ID = controlToRebuildAndCheckIfHasNestedUserControls.ID;

 

        foreach (Control controlToCheckIfUserControl in controlToRebuildAndCheckIfHasNestedUserControls.Controls)

        {

            if (controlToCheckIfUserControl is UserControl)

            {

                ReturnValue.NestUserControls.Add(GetUserControlHierachy(controlToCheckIfUserControl as UserControl));

            }

        }

 

        return ReturnValue;

    }

נקבל UC שנרצה להוסיף להיררכיה הסופית.
ניצור מחלקת מידע חדשה שתחזיק את ה-ID שלו ואת ה-Path שלו (ונשתמש בהם אחר-כך כדי ליצור אותו מחדש).

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

איך נראה ה-Load?
בדיוק הפוך.

    private void RebuildUserControlHierachy(UserControlHierachy hierachyToRebuildItsControls, Control parent)

    {

        UserControl newUserControl = (UserControl)LoadControl(hierachyToRebuildItsControls.Path);

        newUserControl.ID = hierachyToRebuildItsControls.ID;

        parent.Controls.Add(newUserControl);

 

        foreach (UserControlHierachy hierachyToRebuildItsControlsInCurrentHierachy in hierachyToRebuildItsControls.NestUserControls)

        {

            RebuildUserControlHierachy(hierachyToRebuildItsControlsInCurrentHierachy, newUserControl);

        }

    }

אנחנו מקבלים מחלקת מידע חדשה והורה לקונן לתוכה את ה-UC שניצור.
נטען אותו לפי נתיב ASCX ו-ID ונוסיף להורה.

אז נעבור על כל ה-UCים המקוננים שלו וניצור גם אותם מחדש בתוכו.

 

כמה הערות חשובות:

1. זה סה"כ POC להראות איך ניתן להשתמש ב-ViewState כדי לשמור על היררכיית פקדים אוטומטית.
מקרים שלא טיפלנו כאן: טעינה ושמירה פקדים דינמיים שהם לא UC, איך מבדילים בין פקד דינמי לפקד רגיל שנוצר ב-ASP.Net Declarative, מה קורה אם באמצע ההיררכיה יש סתם Container Control כמו Panel או PlaceHolder.

2. יש כאן בעיית אבטחה שצריך לשים עליה את הדעת שלפי ה-ViewState נטען ASCX, עדיף כאן לעבוד עם משהו מבוסס Tokenים (1 מייצג moshe.ascx, 2 מייצג shlomo.ascx, ...)

3. זה לא נבדק מול UpdatePanel, אבל היות וכל מחזור הדף רץ שם לא אמורה להיות בעיה.

4. ייתכן וכי יש צורך להריץ פעמים את Base.LoadViewState, פעם אחת כדי לקבל ViewState של המחלקת מידע ופעם אחת לטעון לתוך המחלקות החדשות את ה-ViewState אחרי שנוצרו.

5. עדיף כמובן (כמו שציינתי) להוסיף את הקוד הספציפי לפתרון התשתיתי הזה לתוך BasePage או BaseUserControl.

 

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

קוד של שתי הדפים האלו:  http://www.JustinAngel.Net/files/DynamicUserControls.zip

 

 

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

Validation Application Block with Strippers: ObjectCollectionValidator (Overview of all VAB Validators)

 image

 

סדרת לומדים Validation Application Block עם חשפניות

1. קדם דבר: למה צריך וולידציה? (או: "קופים. פשוט קופים."), פורסם ב-26.6.2007

2. חלק ראשון: הפתרון הקיים והמצוי ב-Winforms, Console ו-ASP.Net (או: "איך קוראים לך ובת כמה את?"), פורסם ב-8.7.2007

3. חלק שני: שימוש ישיר ב-Validatorים של VAB (או: "איך לגרום לקוד יחסית קריא להפוך להיות ארוך ומעיק"), פורסם ב-9.7.2007

4. חלק שלישי: הכנסת נתוני הוולידטורים לתוך מחלקות (או: "ממלכתי עבור וולידטור ג'נארי"), פורסם ב-10.7.2007

5. חלק רביעי: אינטגרציה בסיסית עם ה-GUI ו-וולידציה מתוך קבצי קונפיוגרציה (או: "קצת יותר Drag&Drop, קצת פחות קוד"), פורסם ב-11.7.2007

6. חלק רביעי המשך: אינטגרציה בסיסית עם ה-GUI ו-וולידציה מתוך קבצי קונפיוגרציה (או: "קצת יותר Drag&Drop, קצת פחות קוד"), פורסם ב-12.7.2007

7. StringLengthValidator - בודקים שהכניסו שם חשפנית, פורסם ב-15.7.2007

8. RangeValidator - נו, תן ציון ל-Lap dance שקיבלת, פורסם ב-16.7.2007

9. DateTimeRangeValidator - מתי ביקרת אצלנו?, פורסם ב-17.7.2007

10. ContainsCharctersValidator ו-Negated - איך קוראים לך?, פורסם ב-18.7.2007

11. RelativeDateTimeValidator - מתי היום-הולדת שלך?, פורסם ב-22.7.2007

12. PropertyComparisonValidator ושני וולידטורים על אותו מאפיין - נבדוק שהמבקר נולד לפני שהוא ביקר במועדון, פורסם ב-24.7.2007

13.  RegexValidator - בודקים את הדוא"ל של המבקר , פורסם ב-26.7.2007

14. DomainValidator - מה הסוג משקה אלכוהולי האהוב עלייך?, פורסם ב-29.7.2007

15. ObjectValidator - מה המספר פלאפון שלך?, פורסם ב-31.7.2007

16. ObjectCollectionValidator - מה המספרי פלאפון של החברים שלך?, פורסם ב-22.11.2007

 

ObjectCollectionValidator - מה המספרי פלאפון של החברים שלך?

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

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

מה נעשה בשביל זה? ניצור אוסף (גם באנגלית: Collection) שיכיל רשימה של פלאפונים השייכים לחברים.

        private List<CellPhone> _friendsCellPhones = new List<CellPhone>();

 

        public List<CellPhone> FriendsCellPhones

        {

            get { return _friendsCellPhones; }

            set { _friendsCellPhones = value; }

        }

נרצה איכשהו, שבדומה ל-ObjectValidator נוכל להריץ גם את כללי הוולידציה של CellPhone על FriendsCellPhones.

בדיוק בשביל צורך זה נכתב הוולידטור ObjectCollecitonValidator שמאפשר לנו להריץ את כללי הוולידציה של אוסף ישויות עסקיות.

        private List<CellPhone> _friendsCellPhones = new List<CellPhone>();

        [ObjectCollectionValidator(typeof(CellPhone))]

        public List<CellPhone> FriendsCellPhones

        {

            get { return _friendsCellPhones; }

            set { _friendsCellPhones = value; }

        }

ל-ObjectCollectionValidator ניתן את הטיפוס של שביחס אליו נרצה שכל האלמנטים באוסף יבדקו.

אם היינו רוצים להוסיף את ההגדרה של ObjectCollectionValidator דרך עורך הקונפיגיורציה הגרפי הינו עושים זאת כך.

image_thumb52

image_thumb53

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

image_thumb54

נראה איך ה-XML שקיבלנו בקובץ BL.config מהוספת ה-ObjectCollectionValidator:

    <type defaultRuleset="default" assemblyName="BL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"

      name="BL.VisitRating">

      <ruleset name="default">

        <properties>

            ...

          <property name="FriendsCellPhones">

            <validator targetType="BL.CellPhone, BL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"

              targetRuleset="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.ObjectCollectionValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

              name="Object Collection Validator" />

          </property>

        </properties>

      </ruleset>

    </type>

ב-Winforms כנאמר נוסיף שלושה שדות:

image_thumb55

נביט על המאפיינים של אחד מהם:

image_thumb56

נוכל לראות שהוולידציה מתבצעת כנגד האוסף FriendsCellPhones שהוא מסוג <List<CellPhone.
זה בזמן שאנחנו מבצעים את הוולידציה על TextBox.Text שהוא מסוג string, ולכן נצטרך להמיר בין string ל-<List<CellPhone.

נתחבר לאירוע ה-ValueConvert ונבצע את ההמרה:

        private void VisitRatingValidation_ValueConvert(object sender, ValueConvertEventArgs e)

        {  

            ...

            if (e.TargetType == typeof(List<CellPhone>))

            {

                List<CellPhone> convertedValue = new List<CellPhone>();

 

                convertedValue.Add(new CellPhone(e.ValueToConvert.ToString()));

 

                e.ConvertedValue = convertedValue;

            }

        }

קיבלנו כאן מחרוזת כ-e.ValueToConvert ו"המרנו" אותה ל-<List<CellPhone שנכנס לתוך e.ConvertedValue.

בצורה דומה, ב-ASP.Net אנחנו גם מקבלים מחרוזת ורוצים לבצע וולידציה על <List<CellPhone.

image_thumb57

נתחבר לאירוע ה-ValueConvert של שני ה-PropertyProxyValidators האלו ו"נמיר" מ-string ל-<List<CellPhone.

        protected void objectCollectionValidator_ValueConvert(object sender, ValueConvertEventArgs e)

        {

            List<CellPhone> convertedValue = new List<CellPhone>();

 

            convertedValue.Add(new CellPhone(e.ValueToConvert.ToString()));

 

            e.ConvertedValue = convertedValue;

        }

נראה את ה-ObjectCollectionValidator רץ ב-GUIים:

image_thumb58

image_thumb59

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

 

נחזור לדוגמת ה-FirstClass, SecondClass ו-ThirdClass ממוקדם.

    public class FirstClass

    {

        private SecondClass _second = new SecondClass();

        [ObjectValidator()]

        public SecondClass Second

        {

            get { return _second; }

            set { _second = value; }

        }

    }

 

    public class SecondClass

    {

        private ThirdClass _third = new ThirdClass();

        [ObjectValidator()]

        public ThirdClass Third

        {

            get { return _third; }

            set { _third = value; }

        }

    }

 

    public class ThirdClass

    {

        private string _maxThreeLetterString;

        [StringLengthValidator(3)]

        public string MaxThreeLetterString

        {

            get { return _maxThreeLetterString; }

            set { _maxThreeLetterString = value; }

        }

    }

נשנה את SecondClass.Third שיהיה אוסף מסוג <List<ThirdClas.

    public class SecondClass

    {

        private IList _third = new List<ThirdClass>();

 

        public IList Third

        {

            get { return _third; }

            set { _third = value; }

        }

    }

נרצה שכל וולידציה על SecondClass תגרור גם ווליציה על כל המחלקות ThirdClass בתוך Third.

    public class SecondClass

    {

        private IList _third = new List<ThirdClass>();

        [ObjectCollectionValidator(typeof(ThirdClass))]

        public IList Third

        {

            get { return _third; }

            set { _third = value; }

        }

    }

נראה איך נוכל להשתמש במחלקות אלו כעת.
כרגיל נאתחל מופע של FirstClass ונדפיס את תוצאות הוולידציה שלו.

            FirstClass firstClassWithNonValidString = new FirstClass();

 

            ValidationResults results = Validation.Validate(firstClassWithNonValidString);

            Console.WriteLine(results.IsValid);

נוסיף גם מופיע אחד וולידי של ThirdClass ומופע אחד לא וולידי של ThirdClass.

            FirstClass firstClassWithNonValidString = new FirstClass();

 

            ThirdClass nonValid = new ThirdClass();

            nonValid.MaxThreeLetterString = "hello world";

            firstClassWithNonValidString.Second.Third.Add(nonValid);

 

            ThirdClass valid = new ThirdClass();

            valid.MaxThreeLetterString = "123";

            firstClassWithNonValidString.Second.Third.Add(valid);

 

            ValidationResults results = Validation.Validate(firstClassWithNonValidString);

            Console.WriteLine(results.IsValid);

ובהרצה נקבל באמת שיש שגיאות בוולידציה של FirstClass:

image_thumb61

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

 

Question from the Silverlight forums: Silverlight keeps asking to be installed

Question:

I am using Blend to create Silverlight application. But Silverlight is behaving quite strange.
I have installed  Silverlight alpha  refresh.  When I browse other sites with silverlight content I can view them without any issue. However when I try to execute my application from blend it opens the browser and just displays the logo to download Silverlight.

 

Answer:

Let's get it clear on what the problem is before we solve it.

Working with Silverlight today we often see these buttons prompting us to download Silverlight when opening an existing Silverlight application:

image

image  image image

 

There are some reported cases of customers clicking these buttons, downloading Silverlight, installing it and still seeing these "Please install Silverlight" notices. Which is to say the least - highly problematic.

These messages appear based on settings in our "Silverlight.js" file.
That file we all add just because Microsoft tells us too is actually the file responsible to identify what version the user has installed, gets the version needed for the application, determines is the version is present and if it isn't displays this link to the download page. 

In the header of every "Silverlight.js" the version it's intended for is listed.
So let's open a few of these "Silverlight.js" files and see it's really written these and I'm not just making this up:

 image

 image

 image

Additionally each Silverlight application when initialized asks for a specific version:

image

What happens is that sometimes the application asks for the wrong version.
Or more frequently - We've got the wrong "Silverlight.js" file in our application.

You should check your "Silverlight.js" version number and you'll probably find it belongs to a different version then the one you're trying to run, or an older version. (like the 1.0 Beta/RC)
Copying the appropriate new "silverlight.js" file to your project will cause the logo to disappear. You can get the approprite "Silverlight.js" file by opening a new project from the right version and just taking it from there. Due make sure to check the version number listed in it matched what you need.

 

Link: http://silverlight.net/forums/p/5980/18336.aspx

Question from Tapuz .Net forum: Session State storage hardcore explanation

שאלה:

יש לי מערכת די גדולה, ואני משתמשת בה בSessions.

ה sessions שלי מאחסנים גם משתנים פשוטים (כמו int לID של המשתמש) וגם משתנים מורכבים (כמו DataSet של כל הפרטים שלו או של תוכן סל הקניות שלו וכדו').

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

 

תשובה:

Sessions מתאפסים מהרבה מאוד סיבות.
כמה לדוגמה:

1. הגעת לגבול העליון מבחינת זכרון שמוקצה ל-Sessions. פיזית ב-RAM יש מקום שמוקדש ל-Sessions. המקום הזה הוא חלק מאותו מקום שמוקצה ל-HTTP Cache. כברירת מחדל מדובר על 800 מגה (ולא ניתן ולא מומלץ להגדיל את המקס' זכרון הזה) פר מעבד בשרת. כלומר, אם יש יותר מ-800 מגה של נתונים ב-Cache ה-Session גם יתחיל להתנהג מוזר.

2. ה-AppDomain עצמו של השרת אותחל. זה יכול לקרות ממספר סיבות - אתחול של ה-IIS, שגיאת StackOverflow / OutOfMemoryException ועוד שגיאה כזו, שינוי של קבצי ה-config שגורמים ישר לאתחול של האתר וכך הלאה.

3. ה-Session עצמו פג תוקף ביחס לקריטריונים של השרת. הקריטריון הבסיסי הוא כמה מקסימום זמן להחזיק את ה-Session בחיים. אך אם השרת נאלץ לפנות זכרון ב-Cache למשל הוא ישתמש במדיניות LRU (מייצג: Last Recently Used) שאומר שהוא ינקה את ה-Sessionים הישנם ביותר. אז גם אם קבעת 20 דקות פג-תוקף ל-Session, יכול להיות שאחרי 5 דקות השרת יחליט להרוג את ה-Session הכי "זקן" של האתר.

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

כפתרון - עדיף לעבור לצורת אחסון שהיא לא InProc. מצ"ב קישור למאמר שמסביר על האפשרויות:
SessionState בקובץ web.config

 

שאלת המשך #1: (על פרגמנטציה ב-RAM של ה-Cache)

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

 

תשובה המשך #1: 

כן, אני בטוח.
פר מעבד על המכונה ה-RAM של ה-Cache לא יכול לעבור 800 מגה.

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

בוא נסביר למה הגבול הזה קיים.

מערכת ההפעלה לא יודעת לנהל פרגמטציה על ה-RAM בצורה אופטימלית. (עוד רגע על למה ומה זה בכלל)
לשנות מודל פרגמנטציה בחלונות ישבור בצורה דרסטית Backward comptability לכל אפליקציה בעולם.

יש מערכות הפעלה עם ניהול RAM הרבה יותר טוב משל חלונות מהבחינה האקדמאית של "יותר טוב".
למשל יש מערכת הפעלה בשם VAX וספציפית VMS שיודעת לנהל זכרון מצויין. מערכת הפעלה מבערך שנות ה-80, שאפשר לעבור שנה בלי לאתחל. למה? כי ניהול הזכרון שלהם בשילוב עם GC (בשם Cics) אגרסיבי וסוציומט יודע איך למנוע פרגמנטציה על הדיסק. רק מה? בגלל המודל הזה אי-אפשר כמעט לפתח אפליקציות על המערכת הפעלה הזאת כי היא כל הזמן דופקת לך הפניות זכרון.

מה זה למעשה פרגמנטציה של ה-RAM?
נגיד ואני רוצה לכתוב עכשיו 4096 בתים על ה-RAM.
אז באתי וכתבתי "שלום עולם 1" על ה-RAM.
אז ישר באתי וכתבתי "שלום עולם 2", "שלום עולם 3" ו-"שלום עולם 4".
סה"כ תפסתי 4 פעמים 4KB סה"כ = 16KB.

עכשיו באתי ואמרתי, תפנה בבקשה את "שלום עולם 2".
אז עכשיו יש לי פיזית מקום על ה-RAM שנראה ככה:
4KB תפוס, 4KB לא תפוס, 4KB תפוס, 4KB תפוס.

ועכשיו אני רוצה 16KB על ה-RAM למשהו יחסית גדול.
אז אני אתפוס מקום ישר אחרי ה-"שלום עולם 4" שלי.

אבל רגע - יש לי 4KB פנוי במרכז שם! ובכל זאת שהייתי צריך 16KB ביקשתי את כל ה-16KB ולא 12KB!

למה זה? כי הפניות לזכרון הן פיזית הפניות לנקודה ספציפית בזכרון.
OS נורמלי לא יודע איך לכווץ שטח ב-RAM עם שטח פנוי בתוכו כך שיהיה רק השטח בשימוש.
אם תנסה למשל להעביר את "שלום עולם 3" למקום של "שלום עולם 2", כל ההפניות זכרון אליו ישברו.

מה שה-CICS הזה שהזכרתי עושה זה כן לבצע את ההעברה הזאת ב-RAM ובעקרון הגישה הייתה "אני מעביר, תשימו לב, מקסימום אתם קורסים".

עכשיו למה זה בכלל קשור ל-Cache של ASP.Net?
בוא נגיד ובמקום "שלום עולם X" שמרתי את רשומת לקוח X ב-Cache.
ואז באתי ואמרתי "רגע רגע,  לקוח מספר 2 הוא Expire ב-1.1.2008 ולקוח מספר 50 Expire שהרשומה במסד משתנה.".
כנ"ל ה-Session גם עובר תהליך דומה של Expiration לפי פרמטרים של זמן או ניהול אחר.

אז מה קורה לנו? אנחנו מקבלים ב-ASP.Net Cache גם זכרון שיש בו הרבה פרגמנטציה.
כלומר, יש הרבה מקום פנוי שפשוט אי-אפשר לבקש מחדש בין מקום שכן בשימוש.
האחוזים בין סה"כ מקום למקום שלא בשימוש הוא אמפירית 60%.
כלומר 40% מה-ASP.Net Cache הוא לרוב בשימוש.

ולמה זה מעניין בכלל? כי  ביחס למערכת ארכיטקטורת מעבדים יש גבול של 2GB על כל הזכרון של Process.
ככה אם יש לי גבול של 2GB שמתוכה ידוע ש-60% הוא זכרון ריק, אני אגביל את הזכרון בשימוש ל-800 מגה.

יש מקומות בקונפיוגרציה שאפשר לשנות את זה (ברמת ה-web.config או ה-app.config) ב-<processmodal memorylmit> ו-<cache privateBytesLimit>. אבל סה"כ, אבל לראות פיזית את הפרגמנטציה בזמן אמת, להבין על מה מביטים, אסור לגעת בזה. כיוון לא טוב של הנתון הזה (או אפליקציה שיוצרת יותר מדי פרגמנטציה על ה-RAM של ה-Cache) תגרום ל-OutOfMemoryException שתפיל הכל.

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

עוד סיבה מעבר לפרגמנטציה של ה-RAM הוא זה שה-GC נכנס לחרדת נטישה שה-Process מתקרב לגבול העליון של ה-Virtual RAM Claim והופך להיות מאוד אגרסיבי. ארגסיביות של ה-GC גורמת לו לעשות הרבה מעברים על עץ האובייקטים שפיזית לוקח הרבה מאוד CPU וגם יכולה לדפוק את ה-Cache גם ככה בזה שהיא מוציאה ממנו אלמנטים מחוץ ל-Expiration Policy.

סה"כ הגבול הגיוני ואמור להיות שם.

 

שאלת המשך #2: (על שמירת נתונים InProc/OutProc/Sql)

לגבי מה שלא InProc, זה פיתרון נחמד להרבה מאוד דברים, אבל קח בחשבון שאין כמו לגשת לזיכרון הזמין ביותר בשרת, זה תמיד יותר מהיר מSQL או אפילו שרת יעודי לנושא.

 

תשובת המשך #2:

לא מדוייק.

כשה-RAM עובד פרגמנטציה פיזית הוא מתחיל גם להיות איטי, מעאפן ולא אמין.
למה באמת יש את ההגבלה הזאת של 800 מגה על ה-Cache פר מעבד?
ה-RAM הוא פיזית מכות חשמל של 0 ו-1 על חתיכת פלסטיק מתוחכם.
מסתבר שיש יותר מדי מידע שלנו שם, המידע מתחיל להיות מעורבב, לא ברור ואף במקרים קיצוניים לא אמין. אז הוא הופך לאיטי.
אז כאן יש גורם חזק של האטה על ה-RAM.

ה-OutProc יכול גם לשבת על ה-RAM של אותה מכונה, אבל לתת הקצאה נפרדת של RAM ספציפית רק ל-Session בלי קשר לדוט נט וגם לא להיות תלויה ב-IIS וב-AppDomain של האתר.
אז אתה מקבל כאן את הטוב של שתי העולמות.

בנושא ה-SQL שלכאורה איטי ביחס ל-RAM. אפשר תמיד לקנות לשרת RAM Disk (מה שנקרא: flash ram disk בעגה מיסחרית), להוסיף עליו Data file של סיקוול סרבר שכל מה שהוא עושה זה להחזיק את הטבלה של ה-Session ולסגור עניין.
ואז אתה גם עובד עם מהירות של RAM ומקבל את הנוחות של Persistent Memory.
אגב, זה בכלל גם הפתרון הנכון שיש לך כמה טבלאות ספציפיות ש"נטחנות".
אם יש לך כמה טבלאות של High Volume ולכאורה מסד נתונים עובד עליהן יותר מדי לאט, אפשר כמוצא אחרון להתקין RAM Disk על השרת, לבודד את הטבלאות ל-Data File שיושב על אותו דיסק ופתאום הכל מתחיל לטוס. מניסיון, זה פתרון אדיר שמומלץ בחום למצבים ספציפיים.

ומעבר לזה, ייתכן גם כאשר הנתונים יושבים ב-SQL לבצע ל-Custom Session Provider אופטימזציה שהוא ישתמש באיזה מנגנון Caching פנימי בסגנון MRU/LUR (קיצור ל: Most/Last Recently Used) שידע איזה מידע להחזיק בזכרון ואיזה מידע להחזיק בדיסק. זה אגב, בדיוק מה שמסדי נתונים מבצעים לעצמם והם יודעים לעשות לעצמם את האופטימיזציה הזאת.

וגם אם מדובר על OutProc/Sql שיושב על שרת מרוחק, תמיד אפשר לעבוד בפרוטוקול UDP שהופך את הגישה למאוד מאוד מהירה.

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

 

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

Question from the Silverlight forums: Limiting TextBlock text rendering to a specific region

Question:

I've got this XAML code in my application:

<Canvas Height="25" Width="75" Canvas.Top="250" Canvas.Left="250" Background="LightGray">

    <TextBlock Width="75" FontSize="12" Text="This is a long line"></TextBlock>

</Canvas>

Problem is eventually the text goes beyond border of canvas. Ideally I want text string be cut right by canvas border.

I though about using text wrapping. But the TextBlock would wrap the text and continue on next line which is outside of canvas as well.

image

Does anyone know how to do that with Silverlight?

 

Answer:

If you need an absolute border on a TextBlock just add a Clipping region around it.
The primitive way is setting the "Clip" property to the path of the region you'd like to border the TextBlock with.
The clipping region just "removes" all rendering the belongs to that element that is outside the region.

image

 

However, The more "blendy" way of doing that is drawing the shape you want to border the TextBlock and position it as a border.

image


Make sure the border is selected.

 image

Select the TextBlock (using Ctrl + select) so both the TextBlock and region are selected.

image

Through the file menu select "object --> path --> make clipping path".

image 

And that will automatically create populate the Clip path with the region you've drawn.

image 

 

Let's add some more text into our TextBlock so we could see the text wrapping being cut.

image

    <TextBlock Width="184" Height="64" Canvas.Left="80" Canvas.Top="77" Text="Hello world. Hello world. Hello world. Hello world. Hello world. Hello world. Hello world. Hello world. Hello world. Hello world. Hello world. " TextWrapping="Wrap" Clip="M0.5,0.5 L143.5,0.5 L143.5,48.5 L0.5,48.5 z"/>

And in our browser we'll see our TextBlock has a hard-border around it and no text can be rendered outside of it:

image

 

We can also use the Clip property in order to place a definitive border on many other elements, like the Root canvas of a page.

 

Link: http://silverlight.net/forums/p/5976/18338.aspx

Question from Tapuz .Net forum: Development machine recommended specification

שאלה:

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

 

תשובה:

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

 

מעבד: Core 2 Duo. מבחינת מהירות, הכי מהיר שתוכל למצוא ולהרשות לעצמך, יש תמיד עקומת מחיר עם הדגם הכי מהיר. בגדול 2.13, 2.33 יתאימו מאוד.
לי יש היום Core 2 Duo עם 2.0.

קצת על הבדלים בין מעבדים: מעבד יחיד היום למשל עם 3.4Ghz לא מגיע לביצועים של מעבד Core Duo עם 2.0Ghz לכל מעבד.
Core 2 Duo יותר מהיר ב-30% מאשר Core Duo.
ככה שפנטיום 4 או פנטיום M של 3Ghz מעבד מול מעבד 2.33Ghz Core 2 Duo זה בערך 200% יותר מהירות ל-Core 2 Duo. מהותי.

במחשבים נייחים, יש כבר Core Quad, אבל לא קיים עדיין בניידים נכון לעכשיו.

זכרון: 2GB מינימום.
Visual Studio + Sql Server + Outlook + Internet explorer זה כבר מעל ג'יגה של RAM והגיוני במחירים של היום לקחת 2GB.

יותר אם אתה רוצה להריץ Virtual Machines (למשל, אם יש לך מכונה ווירטואלית שמריצה התקנת סיקוול 2000, עוד אחת שמריצה התקנת 2005, עוד אחת שמריצה TFS, עוד אחת שמריצה VS2008 וכך הלאה) שכל מכונה כזאת זה חצי גיגה RAM אם אין ממשק גרפי (למשל בשרת TFS)  עד גיגה RAM שצריך ממשק גרפי (למשל התקנה של VS2008). שמורידים ממיקרוסופט את ה-VMים שלהם הסיקוול 2005 מגיע עם חצי גיגה קונפיג וה-VS2008 מגיע עם 712 מגה RAM קונפיג.

חשוב להביט על fbs (מהירות bus) של הזכרון. זה מהותי. המינימום שאתה יכול לסבול זה 667Mhz, פחות מזה לא משנה כמה RAM יהיה לך אתה תרגיש איטיות. היום כבר יש 1000+ Mhz, וזה עדיף בהרבה על דגמי ה-DDR2 עם 667Mhz.
לי יש היום 4GB 667Mhz.
המהירות fbs היא המהירות שבו ה-CPU מעביר מידע ל-RAM ובחזרה. גם אם תפציץ ב-RAM וב-CPU, אבל ה-fbs נמוך תקבל מחשב יחסית איטי.

היום כבר יש DDR3 עם עד 1333fbs ב-PCים.

הארד-דיסק: מינימום של 120GB.
כל התקנה של Visual Studio + קבצי ה-MSDN של אותה גירסה זה לפחות 10GB.
ככה ש VS2003 + VS2005 + VS2008 בהתקנה נקייה זה 30GB בפני עצמו.

היות ומדובר במחשבי פיתוח אז תמיד יש המון תוכנות נלוות (Sql Server, Expression, FireFox וכך הלאה) שלוקחות עד כמה עשרות גיגה וזה לפני שבכלל התחלת לעבוד.

כמו שאמרתי, אם אתה מתכנן להריץ VMים זה גם מסתבך כי כל VM הוא התקנה של ה-OS בפני עצמו אז VM בממוצע הוא לפחות 10 גיגה. לי יש 4 VMים שאני עובד איתם על בסיס יום-יומי, ועוד 10 על הארד-דיסק חיצוני.

חשוב להביט על ה-RPMים של ההארד-דיסק. ה-RPMים זה מהירות הסיבוב של הדיסק שקובעת ישירות כמה מהר אפשר לקרוא ולכתוב מהדיסק. שאתה עושה Build לפרוייקט תזכור שכל הקבצים צריכים להיקרא מהדיסק ואז הוא כותב DLLים שלהם ומה לא. אם יש לך HD עם RPMים חלשים אתה תרגיש שכל BUILD הכי קטן זה חמש-שש שניות ו-BUILD לפרוייקט אמיתי בין חצי דקה לדקה, לא מדבר על Rebuildים בכלל.
RPMים זה לפחות 7200RPM היום לפי דעתי.
יש 4200, 5600, 7200 ו-10,000. מרגישים בהבדל ברור בזמנים ובקפיאה של VS עם Build ביחס למהירות ההארד-דיסק.
לי יש HD של 100GB עם 7,200RPM.

עוד משהו שחשוב לזכור, ה-HD של המחשב גם אם זה המחשב הביתי - לא להתקין עליו תוכנות P2P בכלל ובטח לא להשתמש בו ל-TEMPים או הורדות סופיות. אם אתה רוצה עמדת P2P או שתקנה מחשב ישן באלף שקל ותשים בפינה שיוריד קבצים וזהו, או\ו שתתקין הארד-דיסק חיצוני והכל יילך אליו.
לי יש לאפטופ ישן בן ארבע שנים שכל מה שהוא עושה זה להוריד קבצים ו-Skype מחובר להארד-דיסק נייד של WD עם 1Tara.

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

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

אם זה לאפטופ אז 15.4" Widenscreen. ה-Screen Real estate שעובדים עם VS זה הדבר הכי יקר שיש.
אני מעדיף קונפיגיורציה של מסך אחד כי ככה אני יכול לעבור ממקום למקום עם לאפטופ בלי להרגיש שיש לי עמדה יותר טובה בבית.

מקלדת ועכבר: הכי טובים. אל תתקמצן כאן כי חמישים שקל שחוסכים על מקלדת זה בדיוק איך תוכניתנים מקבלים Carpel Tunnel. אני קיבלתי מתנה את העכבר האופטי של מיקרוסופט Laserpoint 6000 (יותר טוב מ-Laserpoint 3000 אבל לא יקר כמו ה-Laserpoint 9000, אם לצטט את דוגברט) ואני מאוד מרוצה. העיקר שהוא מתאים לך.
חשוב לזכור - ארגונומטריה. משטח ג'ל לפני המקלדת ומשטח ג'ל לפני העכבר.

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

 

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

Question from Tapuz .Net forum: Any good obfuscation product?

שאלה:

האם קיימת תוכנת obfuscator טובה ככה שלא יהיה ניתן לקרוא בכלל את הקוד של התוכנה שלי?

 

תשובה:

אני לא מאמין שקיים כזה דבר.

לא ניתן ליצור Obfuscation טוב לדוט נט.

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

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

לפי דעתי, obfuscation זה מאמץ סמלי ומספיק להשתמש במשהו ממוצע+ שיעצור את התוכניתן המומחה וההאקר המתחיל.
יש את ה-Community obusfactor שמגיע עם כל התקנת Visual Studio, מהבחינה של מאמץ סמלי - זה נחשב.

הדרך היחידה לבצע באמת obfuscation זה לא להשאיר קוד MSIL, ולהריץ את הקוד הדוט נטי דרך Linker שייצור EXE בינארי טהור של מערכת ההפעלה בלי צורך בדוט נט פריימורק (על ה-CLR, JIT וה-GC שלה). הבעיה שלי עם הפתרון הזה שעוד לא מצאתי Linker שמוכיח באופן וודאי שהביצועים שלהם משתווים לביצועים של ה-CLR. לפי דעתי, בסופו של דבר לא ניתן ליצור Linker אמיתי לדוט נט שלא יפרוס גירסה זו או אחרת של הדוט נט פריימוורק עם ה-EXE של האפליקציה.

אם לסכם את העניין - לא ניתן להצפין MSIL בצורה חד כיוונית.
זה בדיוק הנקודה - בסופו של דבר ה-CLR עדיין חייב להריץ משהו.
אם ה-MSIL מוצפן בצורה חד כיוונית -ה-CLR לא מריץ קוד ואז למרות ש"ניצחת" והצפנת את התוכנה באופן סופי - אין לך שום תוכנה להריץ.

 

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

Question from Tapuz .Net forum: Writing an Excel File

שאלה:

איךאפשר  ליצור קובץ בשם DestPath="c:\1.xls" ולשים ב A1 ערך 20 וב A2 ערך 30?

 

תשובה:

יש הרבה דרכים לעבוד עם קבצי אקסל בדוט נט.

אפשרות אחת היא OleDb או Odbc.
מדובר על Database Drivers שמתנהגים "כאילו" excel הוא מסד נתונים לכל דבר ואפשר לשלוח לו שאילתות SQL.
רק מה, שמדובר בקישור מאוד לא יציב עם המון בעיות. הנה כמה דוגמאות קוד:
How To Use ADO.NET to Retrieve and Modify Records in an Excel Workbook With Visual Basic .NET
Reading and Writing Excel using OLEDB

 

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

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

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

אז בואו נכתוב טבלה <table> ב-HTML, נשמור אותה לקובץ עם סיומת XLS ונראה שאקסל מרנדר אותה.
אבל רגע, אנחנו תכנתי דוט נט - אנחנו לא מדפיסים HTML בעצמנו, יש לנו Server-side controls בשביל זה!
אז ניצור פקד Table של ASP.Net ואותה נשמור לקובץ.

ניצור טבלה חדשה של ASP.Net.

            // Setup server ASP.Net control

            Table myTable = new Table();

            myTable.Rows.Add(new TableRow());

            myTable.Rows[0].Cells.Add(new TableCell());

            myTable.Rows[0].Cells.Add(new TableCell());

יצרנו כאן טבלה חדשה עם שורה אחת עם שני תאים.

עכשיו נכניס תוכן לאותם שתי תאים.

            // insert values

            myTable.Rows[0].Cells[0].Text = "20";

            myTable.Rows[0].Cells[1].Text = "30";

בשלב זה נרצה לקחת את הקוד HTML של הטבלה הזו ולשים אותה בתוך מחרוזת שנשמור עוד מעט.

            // render to string

            StringBuilder sb = new StringBuilder();

            using (StringWriter tw = new StringWriter(sb))

            using (HtmlTextWriter hw = new HtmlTextWriter(tw))

            {

               myTable.RenderControl(hw);

            }

            string fileHtmlContents = sb.ToString();

רוב העבודה מתבצעת בשורה של myTable.RenderControl שלמעשה מכניסה את ה-HTML הסופי של הפקד לתוך ה-StringBuilder שלנו ומשם למחרוזת.

נבדוק את התוכן של המחרוזת רק כדי לוודא שאני לא משקר לכם שזה מכיל HTML או משהו כזה.

image

נרצה גם לראות איך התוכן של המחרוזת נראה כ-HTML. (לחיצה על הזכוכית מגדלת ומשם על Html Visualizer)

image

ונראה שבאמת קיבלנו טבלה עם שורה אחת ושתי עמודות:

image

 

ובסופו של דבר נשמור לדיסק.

            // save to disk

            File.WriteAllText(@"c:\1.xls", fileHtmlContents);

 

נפתח את הקובץ באקסל.

image 

 

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

אני לא מרצה בכנס הקרוב

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

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

בכל מקרה, בכנס הקרוב אני לא מרצה.

Israeli 5 Minute Developer Screencast competition

שלום לכולם,

 

החלטתי להגריל שישה ספרים מהוצאת Microsoft Press למפתחים שיעשו את ההקלטות מסך (Screencast) הטובים ביותר עד סוף שנת 2007.

image

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

image 

 

סה"כ מדובר בהשקעה של 5 דקות שבמהלכן תקליטו את המסך שלכם, תסבירו על נושא טכני בתחום ה-Net. ותוכלו לזכות בספר Microsoft Press בשווי 250 ש"ח.

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

עד כדי כך שאני נותן פרסים בשווי 1,500 שקל רק לראות את זה קורה.

 

דוגמאות ל-Screencastים ישראליים:

* Logging Application Block, גיא בורשטיין
* Exception Handling Application Block, גיא בורשטיין
* Validation Application Block, גיא בורשטיין
* ADO.Net Entity Framework, גיא בורשטיין
* Policy Injection Application Block, גיא בורשטיין
* WCF Introduction Demo, גיא בורשטיין
* ASP.Net 2.0 - מצגת על מנגנון ה-WebParts, ג'סטין-יוסף אנג'ל
* ASP.Net 2.0 - מצגת Webcast בנושא Themes, ג'סטין-יוסף אנג'ל
* Silverlight 1.0 Javascript Intellisense, ג'סטין-יוסף אנג'ל
* Silverlight 1.1 Hebrew & Arabic Language Support, ג'סטין-יוסף אנג'ל
* Rhino Mocks, אורן עייני
* Select * from MonoRail.Customers , אורן עייני
* Implementing The Event Broker, אורן עייני
Hibernating Forums, אורן עייני
Hot Code Swapping, אורן עייני
Code Search Engine, אורן עייני
* Visual Studio 2008 חלק א', שחר גבירץ
* Visual Studio 2008 חלק ב', שחר גבירץ
* קובץ ה-Web.config, שחר גבירץ
* Powershell, שחר גבירץ

 

איך תגרום לתשוקה שלך להביא לך ספר Microsoft Press חינם:

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

image

2. תתכננו איך אתם מעבירים Screencast בין 5 ל-12 דקות על הנושא הזה.

More Work Remains To Be Done Before We Can Announce Our Total Failure To Make Any Progress

3. תכתבו את סדר העניינים של ההקלטה בקובץ ב-Notepad או מצגת Powerpoint.

Lack Of Planning On Your Part Does Not Constitute An Emergency On My Part

4. תקליטו את עצמכם מדברים על הנושא הזה מלווים במצגת מהחלק הקודם.
המצגת צריכה להיות באורך 5 עד 12 דקות, בעברית או באנגלית ולכלול חומרים זמינים להורדה אחר-כך.

תוכנות שאפשר להשתמש בהן להקליט:
- Camtasia Studio - תוכנה מומלצת בחום, ניתן להוריד Trial ל-30 ימים כאן.
- Windows Media Recorder - אליק לוין כתב סט מדריכים שמדגימים איך להשתמש בתוכנה.
- Wink - אורן עייני ממליץ להשתמש בתוכנה זו.

You Aren't Being Paid To Believe In The Power Of Your Dreams 

 

5. תפרסמו פוסט בבלוג שלכם עם קישור ל-Screencast, למצגת ולקוד אחרי שהעלתם אותם.
אם אין לכם בלוג או אין לכם מקום להעלות אותה - תשלחו לי דוא"ל ל-J@JustinAngel.Net ואני אדאג לעלות ולפרסם את הכל תוך 48 שעות. רק תצטרפו את הקובץ הקלטה + קבצי המצגת + קבצי הקוד שהדגמתם.

ועכשיו רק נשאר להמתין לשמוע שזכיתם בספר בשווי 250 שקל!

False Hope Is Better Than No Hope At All

 

השופטים בתחרות יהיו: גיא בורשטיין, אורן עייני ואני.

I'm giving Free Microsoft Press Books!

אני נותן שישה ספרי Microsoft Press חינם, מי רוצה?

image6

 

אם יש העדפה לספרים בעברית אז אפשר להחליף ולקבל עותק של:

image9