May 2009 - Posts
כשהראתי לסטודנטים שאני מלמד את
הפוסט של
ספיריטוס שמדבר על ההבדלים בין Equal ל - ==,
שאלו אותי - מה ההבדל בין ה - Equal שיורשים מ - object לבין ה - Equal הסטטי ?
במחשבה ראשונה עניתי - שלמעשה הקריאה - Equal(obj1, obj2 מפעילה את obj1.Equal(obj2.
וכמובן שהשאלה הבאה הייתה, אז מה ההבדל ביניהם,
והתשובה הייתה נפתח את ה - reflector ונראה.
אז הנה הקוד של Equal
public static bool Equals(object objA, object objB)
{
return ((objA == objB) ||
(((objA != null) && (objB != null)) && objA.Equals(objB)));
}
למעשה קודם בודקים את האופרטור == ורק במקרה שזה החזיר false בודקים האם שניהם שונים מ - null ומפעילים את ה - equal,
שזה אומר למעשה כמה הבדלים מעשיים.
במידה ו - obj1 יהיה null, ה - Equal הרגיל ירסק את האפליקצייה בעוד שהסטטי יחיזר false.
במידה שעשינו override ל == אנחנו יכולים לקבל תוצאות שונות עבור ה - equal הרגיל (שלא מפעיל את ה - ==) לבין הסטטי.
במידה שעשינו override ל - equal אחנו יכולים לקבל תוצאה שונה עבור שני ה - equal
אני מניח שכולם מכירים את החלון המעצבן הבא, כשאנחנו מפעילים את ה - VS בפעם הראשונה:
בדרך כלל אפשר לחיות איתו, אבל במחשבים ציבוריים, (כמו במכללות) כל פעם שמגיעים לכיתה חדשה, צריך לחכות וזה מעצבן.
היום נטליה פטרוב (סטונדטית בכיתה) גילתה טריק נהדר.
במקום לחכות עד שה - VS יואיל בטובו להיפתח, אפשר לתת לחלון את הזמן שלו לקנפג את ה - VS, ובמקביל להפעיל עוד פעם את - VS, ולהתחיל לעבוד.
כאן תוכלו לקרוא על C# 4.0
זהו המאמר הראשון שלי ב -
MSDN
ותודה
לסשה על העזרה בכתיבת המאמר.
וכמובן לאיש והאגדה
גיא בורשטיין (אין כמוהו) על כל העזרה ועל כל ההשקעה שלו.
הגעתי בשעה 3:15, היה תור די גדול בעמדת ההרשמה, היינו אמורים להתחיל ב 4:30 בהרצאות, כנראה שעקב העומס, זה נדחה,
בשעה 4:45 (איחור סביר) נסגרו הדלתות, (ניסיתי לשמור לך מקום, אבי)
התחיל לדבר עו"ד יהונתן קלינגר על דמות ההאקר איך שהוא מוצג על ידי הוליווד, בסופו של ההרצאה יצאנו עם רשימת סרטים חדשים שלא ראינו שמציגות האקרים בפעולה.
לאחר מכן, דיבר יניב מירון (מארגן הכנס) על Steganography - שבסופו של דבר הצלחתי להבין שההבדל בין Steganography להצפנה, שבהצפנה ההאקרים יודעים שיש מידע אבל הוא בלתי קריא, וב - Steganography אף אחד לא יודע,
יניב גם הביא דוגמא של סיסמא שמוסתרת בתוך קובץ תמונה, על ידי שהסיסמא כתובה בצבע שונה במעט מכל התמונה, והדרך היחידה לגלות את הסיסמא, היא לפתוח את הקובץ ולשנות את כל הערכים שזהים אחד לשני (כאלו שאנו חושדים שהם מסתירים את המידע האמיתי)
כרגע יצאנו לפיצות (נבדוק האם זה כשר)
נחזור בהמשך לעידכון
אנחנו מתקרבים בצעדי ענק ל - C# 4.0, אבל אני נתקל עדיין באנשים (בעיקר סטונדנטים במהלך הלימודים) שמחפשים דוגמא לשלושת האופציות להפעלת delegate.
אז ככה:
ב - 1.1, האופציה היחידה לשליחת מתודה ל - delegate, היתה לכתוב מתודה ולתת אותה אותה כפרמטר ל - delegate,
דוגמא ראשונה:
List<int> list = new List<int>();
private int tmp;
public int Function1(int item)
{
tmp = item;
return list.Find(new Predicate<int>(FindItem));
}
private bool FindItem(int item)
{
return item == tmp;
}
אמנם ב - 1.1 היה קיים רק ArrayList, אבל הרעיון הוא שהדרך היחידה לשלוח פונקציה ל - delegate, היא על ידי יצירת delegate, ושליחת השם של הפונקציה להפעלה.
דוגמא שניה:
public void ThreadFunction1()
{
Thread thread = new Thread(new ThreadStart(Target));
thread.Start();
}
private void Target()
{
int i = 0;
while (true)
{
Thread.Sleep(1000);
Console.WriteLine(i);
i++;
}
}
כמו שאפשר לראות בדוגמא הראשונה, החיסרון הגדול של הדרך הזאת, היא שאין לפונקציה המופעלת באמצעות ה - delegate, גישה למשתנים לוקליים של הפונקציה שמתוכה היא הופעלה.
ואז ב - 2.2 הגיע לעולם המושג - Anonymous Methods, וכך נראה הקוד.
דוגמא ראשונה.
public int Function2(int item)
{
return list.Find(delegate(int i)
{
return i == item;
});
}
דוגמא שניה:
public void ThreadFunction2()
{
Thread thread = new Thread(delegate()
{
int i = 0;
while (true)
{
Thread.Sleep(1000);
Console.WriteLine(i);
i++;
}
});
thread.Start();
}
ואז ב - C# 3.0 הגיע המושג - Lamda Expression, שחוסך את המילה delegate,
וכך נראה הקוד:
דוגמא ראשונה:
public int Function3(int item)
{
return list.Find(item1 => item1 == item);
}
דוגמא שניה:
public void ThreadFunction3()
{
Thread thread = new Thread(() =>
{
int i = 0;
while (true)
{
Thread.Sleep(1000);
Console.WriteLine(i);
i++;
}
});
thread.Start();
}
נקודה ששווה לשים לב, זה שהרבה פעמים התחביר של 1.1 הוא הרבה יותר קריא (בעיקר כשלא צריך לכתוב את ה - new, ואפשר לכתוב ישירות)
public int Function1(int item)
{
tmp = item;
return list.Find(FindItem);
}
מאמר טוב שכתב
שחר לגבי חידושים ב - C# 3.0 תוכלו לקרוא
כאן.
ה -
ValidatorCallout הוא אחד מהתוספות המעניינים של ajax, הוא מאפשר להציג את הודעת השגיאה בצורה יפה ונוחה.
מה שצריך לעשות, זה לשייך את ה - targetControlID ל - Validator הספציפי.
הבעייה מתחילה כשאנחנו מצמידים ל - ValidatorCallout את ה - CustomValidator.
במקרה הזה במדה ונגדיר שהבדיקה תהיה רק בצד השרת, אנחנו נהיה בבעיה, כי במקרה כזה ה - CustomValidator לא מרונדר בכלל לדף, וה - ValidatorCallout מחפש את ה - Validator והוא לא מוצא אותו.
הפיתרון הוא פשוט, להגדיר EnableClientScript כ - true, (אין צורך לתת פונקציה - אלא אם כן אתם רוצים גם לבדוק בצד הלקוח) במקרה הזה ה - CustomValidator מרונדר לדף, וה - ValidatorCallout ימצא אותו, והכול יבוא על מקומו בשלום
יש עם זה כמה בעיות, ופתרתי אותם, אז כמובן שצריך לכתוב פוסט על זה,
אבל חשבתי שלפני שאכתוב פוסט על הבעייה הספציפית, אולי שווה לכתוב פוסט על ה CustomValidator.
השימוש בשאר ה - validators הוא די פשוט,
גוררים את ה - validator לדף,
נותנים ערך ל - ControlToValidate,
במידת הצורך גם לעוד מאפיין, (כמו ContrloToCompare ב - CompareValidator, או ValidationExpression עבור RegularExpressionValidator
מגדירים את המאפיין EnableClientScript, שמגדיר האם לבצע את הבדיקה גם בצד הלקוח (ברוב במוחץ של המקרים זה צריך להיות מסומן כ - true)
וזהו.
השימוש ב CustomValidator, הוא טיפ טיפה יותר מורכב, היות ואנחנו צריכים לכתוב את כל הבדיקות לבד.
נחפש דוגמא פשוטה, נניח שאנחנו רוצים CompareValidator על שלוש תיבות טקסט שכולל גם RequiredFieldValidator (על הבעייה ש - CompareValidator לא מכיל RequiredFieldValidator, כתבתי
כאן)
(ברור שאת הבעייה הזאת ניתן לפתור בדרכים קלות יותר, בחרתי בדוגמא הזאת כי זה קל למימוש)
כך נראה קוד ה html
<asp:TextBox ID="txt1" runat="server"></asp:TextBox>
<asp:TextBox ID="txt2" runat="server"></asp:TextBox>
<asp:TextBox ID="txt3" runat="server"></asp:TextBox>
<asp:CustomValidator
ID="cv1"
ControlToValidate="txt1"
runat="server"
ErrorMessage="*"
ClientValidationFunction="CompareAndRequierd"
ValidateEmptyText="True"
Comparer1="txt2"
Comparer2="txt3"
onservervalidate="cv1_ServerValidate">
</asp:CustomValidator>
חשוב לשים לב למאפיין ValidateEmptyText שמוגדר כ - true, אחרת, במידה ולא יהיה ערך בתיבת הטקסט, הוא לא יריץ את הבדיקות.
וכן חשוב לשים לב, שהמצאתי שני מאפיינים חדשים ל CustomValidator,
בשם Compare1 ו - Compare2, (וזאת כדי שהפונקציות הבודקות האם ה valid, יהיו פונקציות גלובליות, ולא בכל פעם שארצה כזה validator, אצטרך לכתוב את הפונקציות מחדש)
נתחיל עם צד הלקוח,
כך נראה הסקריפט שבודק את צד הלקוח:
<script type="text/javascript">
function CompareAndRequierd(sender, args) {
if (args.Value == '') {
args.IsValid = false;
return;
}
var a = document.getElementById(sender.Comparer1);
var b = document.getElementById(sender.Comparer2);
args.IsValid = args.Value == a.value && args.Value == b.value;
}
</script>
הפונקציה מקבלת שני פרמטרים, הראשון הוא sender, שהוא למעשה ה - Validator, והשני הוא args שמכיל שני מאפיינים,
הראשון Value, שזה הערך של תיבת הטקסט.
השני הוא IsValid, שכברירת מחדל שווה ל - true, ובמקרה שאנחנו רוצים להגיד שהערך אינו חוקי, נשנה את ערכו ל - false.
שימו לב ששני המאפיינים מתחילים באות גדולה.
נקודה נוספת, הסקריפט הזה ירוץ בשני המקרים הבאים,
הראשון - בזמן שיוצאים מהפקד, כלומר שתיבת הטקסט מאבדת פוקוס.
השני - לפני ריצה לשרת, בדרך כלל בלחיצת כפתור.
והנה הסבר הסקריפט.
בודקים האם יש ערך בתיבת הטקסט,
במידה וכן, נמצא את שני הפקדים האחרים, לפי השם שלהם.
נשווה את ערכי שלושת תיבות הטקסט.
וכעת נעבור לצד השרת.
protected void cv1_ServerValidate(object source, ServerValidateEventArgs args)
{
if (args.Value.Trim() == string.Empty)
{
args.IsValid = false;
return;
}
string a = ((WebControl)(source)).Attributes["Comparer1"];
string b = ((WebControl)(source)).Attributes["Comparer2"];
args.IsValid = args.Value == Request[a] && args.Value == Request[b];
}
אותו קוד בדיקה בצד השרת, בדיוק כמו בצד הלקוח.
במידה ואין ערך מחזירים false.
מוציאים מה - source את ה - attribute שמכיל את שמות ה - controls להשוואה, ומשווים את הערך של תיבת הטקסט, למה שהגיע ב - Request (השם של ה - control הוא למעשה גם ה - key בערכים שהגיעו דרך ה - request)
וכמובן לא לשכוח בקוד של הלחצן שגרם ל post back, לבדוק האם הדף הוא valid
שזה משהו שאנשים שוכחים לעשות, וצריך לעשות את זה כל פעם כשמוסיפים validators לדף.
protected void vrb_Click(object sender, EventArgs e)
{
if (IsValid)
{
}
}
ושוב אני רוצה להדגיש, שאם הייתי צריך לעשות את הבדיקה הזאת באמת, כנראה שהייתי עושה את זה בצורה שונה, והדוגמא הנ"ל היא רק כדי להדגים כמה נקודות.
איך לעבוד עם CustomValidator בצד הלקוח ובצד השרת
ושיש את האפשרות להוסיף ל controls מאפיינים משלנו, ואיך מוציאים את הערכים שלהם, כשצריך.
נניח שיש לכם את הקוד הבא:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ErrorMessage="RequiredFieldValidator"
ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="CompareValidator1" runat="server"
ErrorMessage="CompareValidator"
ControlToValidate="TextBox2" ControlToCompare="TextBox1">
שני תיבות טקסט.
RequiredFieldValidator על התיבה הראשונה
ו CompareValidator על תיבת הטקסט השנייה.
נניח שנכניס ערך כלשהו לתיבת הטקסט הראשונה, ולא נכניס שום ערך לתיבת הטקסט השנייה. כשננסה לרוץ לשרת, נצפה לכאורה לקבל הודעת שגיאה שהערכים של שני תיבות הטקסט לא מתאימים, לא ?
אז התשובה היא שלא נקבל שום הודעת שגיאה,
רק במידה ונכניס ערך שונה לתיבת הטקסט השנייה מהערך של תיבת הטקסט הראשונה, נקבל את ההודעה של ה CompareValidator.
הפיתרון הוא פשוט, להוסיף גם RequiredFieldValidator עבור תיבת הטקסט השנייה.
אבל כשאני רואה כאלו דברים, אני חייב להבין למה זה קורה, אז פתחתי את ה reflector, והנה הקוד:
protected override bool EvaluateIsValid()
{
string controlValidationValue =
base.GetControlValidationValue(base.ControlToValidate);
if (controlValidationValue.Trim().Length == 0)
{
return true;
}
לא העתקתי את המשך הקוד.
אבל ברור מדוע במידה ולא הכנסנו ערך, אנחנו לא מקבלים את השגיאה של CompareValidator.
לי זה נראה כמו באג של מי שפיתח, את ה CompareValidator .
דרך אגב, שמתם לב שהמפתחים של מייקרוסופט לא משתמשים ב string.Empty, אלא ב Length==0, כדי לבדוק האם קיים ערך ב string, (ככל הנראה ענייני ביצועים)
כשאנחנו מחברים את המחשב שלנו לדומיין, מערכת ההפעלה מזהה את המחשבים שמחוברים לדומיין, כשאנחנו מנסים להפעיל אותם,
במידה ואין הרשאות, מערכת ההפעלה תקפיץ חלון דומה לזה:
הבעייה עם החלון הזה, שבמידה ונסמן Remember,
כשניכנס פנימה, יכול מאוד להיות שנמצא תיקיות, שאין לנו הרשאות.
כשנירצה לשנות את ה user שאיתו אנחנו נכנסים, נגלה שאין קליק ימין ולבחירה כמו Change user
כדי לשנות את ההגדרה עבור כל אלו שמוגדרים ב Remember.
יש להיכנס ל Control Panel --> User Accounts --> Manager your credentials
שם נוכל לשנות/למחוק סיסמאות שהוגדרו כ Remember.
לצערי בחלק הפרויקטים אני צריך לעבוד עם oracle.
כשניסיתי להתקין, קבלתי את ההודעה הבאה :
Checking operating system version: must be 4.0, 5.0, 5.1, 5.2 or 6.0. Actual 6.1
Failed <<<<
חיפשתי ברשת ומצאתי שאפשר לשנות את ה compability כמו עם
המסנג'ר
ניסיתי לשנות את ההגדרה, והתברר לי שבמידה והקבצים יושבים ברשת, אין לי אפשרות (הרשאות ?) לשנות את ה compability,
אז העתקתי את הקבצים למחשב הלוקלי, ואמרתי לעצמי, לפני שאני אשנה את ה compability, ננסה להתקין שוב.
כמובן שזה נכשל, אבל לפני שהספקתי למצמץ, קבלתי את ההודעה הבאה:
כמובן שבחרתי ב reinstall, וההתקנה עברה בצורה חלקה.
אז תעברו (מהר) ל windows7 והחיים שלכם יהיו יותר נחמדים.
קבצי resource הם דרך נהדרת לשמור את ההודעות והטקסט של האפליקצייה לפי ה culture,
הדבר שמעצבן אותי כמפתח, שאני צריך בכל פעם לכתוב את הקוד של ההשמה מתוך קובץ ה resource על ה label המתאים.
אז לפני שאני אראה את הפיתרון שאני משתמש, נעשה מעבר מהיר על הנושא. לטובת אלו שלא יודעים מה זה resource ומה זה culture.
נניח שיש לי אפליקצייה שאני רוצה שתהיה גם באנגלית וגם בעברית, נתעלם לרגע מהעובדה שכיון הכתיבה הוא הפוך, ונתמקד בזה שהטקסט צריך להיות בשתי השפות.
איך נעשה את זה ?
קליק ימין עם העכבר על הפרויקט שלנו, נבחר ב add new item, ונבחר ב Resource
אני נוהג לייצר קובץ עבור כל דף, והשם של ה resource הוא בדרך כלל השם של הדף.
כעת נוסיף עוד קובץ resource שהשם שלו יהיה זהה לשם של הקובץ הקודם, אבל עם סיומת של ה culture, לדוגמא: Default.he-IL.resx,
אחרי שנוסיף את הקבצים, ונתחיל לערוך אותם, נוכל להוסיף ערכים, שהם למעשה key-value, כשה key, יהיה זהה בשני הקבצים, אבל ה value, יהיה שונה, לדוגמא:
(העליון הוא הקובץ עם הסיומת של he-IL)
וכעת בקוד מה שאנחנו צריכים לעשות, זה לתת לכל label, את הkey המתאים,
לדוגמא:
protected void Page_Load(object sender, EventArgs e)
{
lblHello.Text = Default.lblHello;
lblWelcome.Text = Default.lblWelcome;
}
כעת נשאר לנו רק לקבוע, מאיזה קובץ לקחת את הערכים,
אז למעשה יש כמה דרכים, אפשר מקונפיג, אפשר על ידי הגדרות הדף,
כאן אפשר לקרוא מאמר שמסביר את הנושא.
אני בדרך כלל עושה את זה מקוד, צריך לעשות override ל InitializeCulture, ושם להחליט מה ה resource המתאים,
יש לדף שני properties שמחליטים על הסביבה, הראשון, הוא ה Culture, זה אינו קשור אלינו, הוא מחליט באיזה פורמט יוצגו המספרים ותאריכים,
לדוגמא הקוד הבא,
protected void Page_Load(object sender, EventArgs e)
{
lblTime.Text = DateTime.Now.ToLongDateString();
}
protected override void InitializeCulture()
{
Culture = "he-IL";
}
יחזיר את התוצאה: שבת 09 מאי 2009
לעומת זאת הקוד הבא:
protected void Page_Load(object sender, EventArgs e)
{
lblTime.Text = DateTime.Now.ToLongDateString();
}
protected override void InitializeCulture()
{
Culture = "en-US";
}
יחזיר את התוצאה: Saturday, May 09, 2009
אבל כמו שאמרתי, זה לא המאפיין שכרגע אנחנו מדברים עליו, אנחנו מדברים על המאפיין UICulture,
הוא מחליט מאיזה קובץ resource לקחת את הערכים, ולכן הקוד הבא:
protected void Page_Load(object sender, EventArgs e)
{
lblHello.Text = Default.lblHello;
lblWelcome.Text = Default.lblWelcome;
}
protected override void InitializeCulture()
{
UICulture = "he-IL";
}
יחזיר את הערכים מתוך קובץ ה resource עם סיומת ה he-IL,
לעומת זאת הקוד הבא:
protected void Page_Load(object sender, EventArgs e)
{
lblHello.Text = Default.lblHello;
lblWelcome.Text = Default.lblWelcome;
}
protected override void InitializeCulture()
{
UICulture = "en-US";
}
יחזיר את הערכים, מתוך הקובץ הרגיל (ללא סיומת של תרבות כלשהו).
בעייה אחת, יש לזה, שבמידה ואנחנו צריכים גישה לערכים מתוך ה javascript, אין לנו, הפיתרון לזה, נמצא
כאן.
והבעייה האחרונה (שלכבודה נכתב כל הפוסט הזה),
אני לא רוצה כמפתח לדאוג להשמה של כל הערכים על ה labels השונים, אז כדי לפתור את זה כתבתי את הפיתרון הבא:
בקבצי ה resource, השמות שאני נותן ל keys הם שם האובייקט_שם המאפיין לדוגמא:
שני הראשונים, הם שמות של label ומאפיין הטקסט שלהם, האחרון הינו RequiredFieldValidator ומאפיין ErrorMessage.
כעת בקוד אני מפעיל את המתודה הבאה:
private void SetDataFromResource()
{
Type type = typeof(Default);
PropertyInfo[] properties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Static);
var stringProperties = from property in properties
where property.PropertyType == typeof(string)
select new Pair(property.Name, property.GetValue(null, null));
foreach (var item in stringProperties)
{
string[] arr = item.First.ToString().Split('_');
if (arr.Length == 2)
{
Control ctr = FindControl(arr[0]);
if (ctr != null)
{
PropertyInfo pi = ctr.GetType().GetProperty(arr[1]);
if (pi != null)
{
pi.SetValue(ctr, item.Second.ToString(), null);
}
}
}
}
}
אני מוציא את כל הערכים מתוך קובץ ה resource.
מחפש control עם השם של האובייקט, במידה ואני מוצא, אני משים את הערך למאפיין.
הפיתרון הזה הוא לא כל כך טוב מבחינת ביצועים, אבל במידה והנקודה הזאת לא מפריעה, אז זה פותר לי את הבעייה שאני צריך לדאוג להשים את הערכים למקומות המתאימים
הפוסטים שלי לגבי WIN7, יתמקדו בדברים הפשוטים,
אז ככה, הדבר הראשון שהפריע לי, זה כשמתקינים את המסנג'ר, וממזערים אותו, הוא מתעקש להישאר על ה taskbar, ולא מוכן ללכת לצד ימין, כמו שהיה בעבר,
הפיתרון (ותודה
לברוך) הוא להגדיר שהמסנג'ר יעבוד כמו בויסטה, הוראות מפורטות
כאן.
הדבר השני, זה שה Quick Launch נעלם, הוראות מפורטות להחזרה
כאן
(אני חייב לציין שאני מגיע ישירות מ XP, ולא היה לי שום ניסיון עם ויסטה, כך שאני צריך להיזהר לא לכתוב על פיצ'רים שהיו כבר קיימים בויסטה.)
בכל מקרה, ההתקנה הייתה ממש נעימה בלי שום בעיות, 15 דקות בערך והמחשב היה מותקן,
לוקח לי הרבה זמן להתרגל לניווט בתוך windows,
אחד הדברים שהתלהבתי, היה כשלא הצלחתי להתחבר לרשת, windows הציע לי באדיבות לבדוק מה הבעייה,
אמרתי לו, אשמח אם תפתור לי את הבעייה, הוא חשב דקה וחצי, ואז הוא אומר לי שה DCPH (או משהו כזה) לא מוגדר, והאם אני מעוניין שהוא יגדיר אותו לבד, אמרתי לו שכן, וכעבור דקה וחצי, הייתי מסוגל לגלוש.
עד עכשיו הכול (חוץ מזה שאני צריך לחשוב איך מגיעים לכל דבר) נהדר עם המערכת, ואני בהחלט ממליץ להתנסות במערכת,
בנתיים מצאתי רק דבר קטן, שקצת הציק לי, כשאני מפעיל את ה Windows update, הוא מציג לי את גודל ההורדות, וכמה אחוזים ירדו, ואני צריך לחשב לבד כמה ירד, וכמה זמן נשאר,
ואני חושב שאם אחרי יום עבודה אינסטסיבי על המערכת, נתקלתי רק בדבר קטן כזה, שה מעיד שהפעם מייקרוסופט באמת עשו עבודה טובה.
בפוסט
הקודם הדגמתי איך להפעיל מתודות סטטיות באמצעות ScriptManager
אבל מה יקרה במצב שהדף שלנו הוא דף הלוגין,ובקונפיג מוגדר בצורה הבאה:
<authorization>
<deny users="?"/>
</authorization>
<authentication mode="Forms">
<forms loginUrl="Default.aspx"></forms>
</authentication>
שזה אומר, שאסור להכנס לשום דף חוץ מה Default (שזה דף הלוגין)
במקרה הזה לא נצליח להפעיל את ה PageMethods,
הרבה אנשים אומרים להגדיר על המתודה [WebMethod(EnableSession=true)], אבל זה לא בדיוק עובד,
לכאורה זה נראה לי כמו באג של הצוות שפיתח את ajax, כי במידה ואני נמצא בדף שמוגדר כדף הלוגין ומותר לגלוש אליו, מדוע אסור להפעיל את ה PageMethods ?
מה שאפשר לעשות, זה להוסיף את הקוד הבא לקובץ הקונפיג מעל system.web
<location path="Default.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
זה יגרום שלא תהיה בדיקה האם יש הרשאות לדף Default,
אמנם זה טיפה מטופש כי Default מוגדר כדף לוגין, ולכאורה זה היה צריך לקרות בצורה אוטומטית,
אבל זה הפתרון היחידי שמצאתי.
More Posts
Next page »