March 2010 - Posts
בתוך קבצי קונפיג יש לנו מקטע של appSettings שבו אנחנו מכניסים רשימה של key=value
<appSettings>
<add key="MyKey" value="MyValue"/>
<add key="TheKey" value="TheValue"/>
</appSettings>
בקוד אנחנו נגש אליהם בעזרת
string value = ConfigurationManager.AppSettings["MyKey"];
(צריך להוסיף reference ל - system.configuration.dll)
יש ל - appSettings שני מאפיינים מעניינים האחד נקרא file והשני נקרא configSource. שניהם מאפשרים להוציא את ה - appSettings לקובץ נפרד לדוגמא
<appSettings configSource="mySettings.config"/>
ובקובץ המצויין יהיה את כל ההגדרות - זה מאוד נחמד ונותן את האפשרות לסדר בצורה טובה יותר את קובץ הקונפיג.
ההבדל בין file ל - configsource הוא
1. configSource מחייב להעביר את כל ההגדרות של appSettings לקובץ החיצוני לעומת file שמאפשר להכניס חלק מהערכים בקובץ המקורי.
2. configSource הוא ממש כמו קובץ הקונפיג המקורי וכל שינוי בו יעשה restart ל - application לעומת file שמאפשר לשנות את הקובץ בלי restart.
היות שאני בימים אלו בבית ולא מרגיש טוב כפי
שכתבתי - חשבתי לנצל את ההזדמנות לקודד מספר אפליקציות שרציתי לעשות מזמן.
מותקן לי על המחשב Sql Server אבל לא הספקתי להתקין את ה - Management Studio, ולכן הורדתי את גרסת ה - Express
מכאן.
בתהליך ההתקנה קבלתי את ההודעה הבאה
The installer has encountered an unexpexted error installing this package. This may indicate a problem with this package. The error code is 29506
אחרי שיטוטים בגוגל הגעתי
לכאן, אחד מהתשובות שם (מה שהתברר כנכון) הוא להריץ Command Line עם הרשאות מנהל ולהפעיל משם את קובץ ההתקנה.
זה קצת מוזר מכיון שכשמריצים את ההתקנה בצורה רגילה, הוא מבקש הרשאות מנהל, אבל זה לא עובד אלא אם כן מכבים את ה - UAC או שמריצים אותו כאמור עם Command Line שיש לו הרשאות מנהל.
זה כנראה באג בקובץ ההתקנה של 64 bit.
עד היום (עד המעבר ל - Visual Studio 2010) כשהיינו בוחרים ב - Go To Definition על מחלקה מסויימת - היינו רואים באיזה Namespace המחלקה מוגדרת, אבל לא היה דרך הגיונית למצוא באיזה dll זה יושב (כדי לדעת למה לעשות AddReference)
ב - VS2010 כשמגיעים ל - Go To Definition בחלק העליון מופיע הקוד הבא:
#region Assembly mscorlib.dll, v4.0.30128
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll
#endregion
פשוט תענוג
לצערי התברר לי שאין הסרטה ב - Live של שאר ההרצאות אלא רק את המליאה - כך שאצטרך להמשיך לחשוב בערגה על הכנס ולקרוא את הפוסטים של גדי (בתקווה שלא יאכזב) מה היה בכנס
לצערי אני לא משתתף פיזית ב - DevAcademy אלא שוכב חולה במטה וחושב בערגה על הכנס.
אבל אז נזכרתי שלשמחתי הרבה מייקרוסופט וסלע מציגים את הכנס ב - Live כך שאני יכול איכשהו להשתתף.
ראשית כל כדאי לציין שהאיכות של ההסרטה היא מדהימה רואים ושומעים הכל בצורה מצויינת.
ההרצאה על Asure היתה טובה מאוד ונותנת הרגשה שכדאי לנסות אותה (מאוד התרשמתי מזה שהטכנולוגייה תומכת לא רק ב - net).
המרצה הצליח להציג את הנושא בצורה מרתקת ומאוד אהבתי את ההדגמה הסופית עם ההגרלה.
השתתפתי גם בחידון בסוף ההרצאה אבל לצערי לא זכיתי בלפטופ, (כנראה שגם אם הייתי זוכה לא הייתי מקבל)
בכל מקרה אני מקווה שאני ארגיש מספיק טוב כדי לצפות בהמשך ההרצאות ולעדכן אתכם
כידוע יש ב - Windows מה שנקרא "Run this program in compatibility mode" מה שמאפשר להריץ את האפליקציות ב"מוד" קודם של מערכת ההפעלה.
היום ניסתי להריץ msi כלשהו וקבלתי הודעת שגיאה שזה יכול לרוץ רק על xp או vista, חשבתי לעצמי שאוכל פשוט להריץ את ה - msi ב - Compatibility Mode, לדאבוני התברר לי שאין לקבצי msi אפשרות להרצה ב"מוד" קודם.
קצת שיטוט בגוגל והגעתי
לכאן, הוא מציע להשתמש ב -
Orca שזה הכלי של מייקרוסופט לשינוי קבצי msi אחרי שהם נסגרו (אפשר להוריד את זה
מכאן)
בתירגום פשוט אלו השלבים:
1. התקינו Orca
2. קליק ימין על ה - msi ובחירה ב - Edit in orca
3. תחפשו ברשימה בצד שמאל מה שנקרא "LaunchCondition"
4. תחפשו בצד ימין שורה שמדברת על הגרסאות
5. הסירו אותה (בעזרת קליק ימין על השורה ובחירה ב - Cut Row)
6. לחיצה על Tools בחירה ב - Options תחפשו את הטאב database ותוודאו ש - "Copy embedded streams during Save As" מסומן.
7. לחיצה על File ובחירה ב - Save As
8. תצאו מ - Orca לפני הפעלה של ה - msi
בהצלחה
נניח שיש לכם את המחלקה הבאה:
class Dolar
{
public double Value { get; set; }
public Dolar(double value)
{
Value = value;
}
}
וב - main
Dolar d1 = new Dolar(10);
Dolar d2 = new Dolar(20);
if (d1.Value > d2.Value)
{
}
לכאורה הקוד היה יותר קריא לו יכולנו לכתוב כך
כדי לעשות את זה צריך להוסיף למחלקה את הקוד הבא
public static bool operator >(Dolar d1, Dolar d2)
{
return d1.Value > d2.Value;
}
public static bool operator <(Dolar d1, Dolar d2)
{
return d1.Value < d2.Value;
}
למעשה נוכל לדרוס כמעט את כל האופרטרים שקיימים, אבל צריך לעשות את זה בזהירות כי אם נחליט שאנחנו מממשים את האופרטור < על PersonManager אף אחד לא יבין את הקוד שלנו, מה שצריך לזכור שהמטרה של OperatorOverload זה להקל על הקריאות של הקוד ולא להקשות עליו.
נקודה נוספת, שתמיד צריך לעשות את זה בצמדים כלומר אם אתם מממשים את האופרטור < אתם חייבים לממש את האופרטור > ואם תממשו את האופרטור == אתם חייבים לממש גם את != וכו'
כמובן שאפשר גם לכתוב כך
public static bool operator >(Dolar d1, double d2)
{
return d1.Value > d2;
}
public static bool operator <(Dolar d1, double d2)
{
return d1.Value < d2;
}
public static bool operator >(double d1, Dolar d2)
{
return d1 > d2.Value;
}
public static bool operator <(double d1, Dolar d2)
{
return d1 < d2.Value ;
}
ואז ב - main
if (d1 > 50)
{
}
if (50 > d1)
{
}
הקרדיט מגיע לאחי יוסי גולדברג
כתבתי פוסטים על שימוש ב -
Cookie. כעת נראה כיצד ניתן להסיר עוגיות בצד השרת.
נניח שיש לכם עוגייה שנקראת MyCookie ואתם רוצים להסיר אותה, למעשה בכל Request שיגיע מהלקוח ה - Cookie יצטרף לבקשה, מה שצריך לעשות זה לכתוב את הקוד הבא
Response.Cookies.Add(new HttpCookie("myCookie") { Expires = DateTime.Now.AddDays(-1) });
למעשה מצרפים ל - Response עוגייה עם אותו שם כשתאריך התפוגה נקבע לזמן ישן, כך כשהתשובה חוזרת ללקוח העוגייה נמחקת.
אם כבר מדברים על - Expires, אם נייצר עוגיות ולא ניתן שום ערך למאפיין הזה, הוא יחיה רק בזיכרון של הדפדפן וכשהדפדפן יסגר גם העוגייה תעלם, במידה וניתן ערך (עתידי) כלשהו לעוגייה העוגייה תשמר בזיכרון של המחשב עד לאותו תאריך.
ב - IIS ל - ApplicationPool יש מאפיין מאוד מעניין שהרבה לא מודעים אליו. Regular Time Interval תחת קטגוריית recycling.
כברירת מחדל הערך שלו זה 1740 (29 שעות) המשמעות של זה שכל 29 שעות ולא משנה מה קורה באותו רגע יש restart ל - application pool,
לפעמים יש לזה משמעות קריטית לזמן שבו יש restart (אם למשל אתם עושים streaming ופתאום האפליקצייה שלכם עושה restart זה לא נעים.
אני לא חושב שכדאי להגדיר אותו ל 0 (כלומר לא לעשות אף פעם restart) אבל חשוב להכיר את המאפיין הזה ולבטל אותו בשעת הצורך. אם זה אפשרי אפשר להשתמש במקומו במאפיין Specific Times שמקבל מערך של TimeSpan שמגדיר באיזה שעה לעשות recycling.
חפשתי איך אפשר לדעת בעוד כמה זמן ה - application pool יעשה recycling אבל לא הצלחתי למצוא פקודה כזאת - אשמח לשמוע על אחת כזאת אם זה קיים.
ב - WebService כדי לדעת מה ה - IP של ה - client שהפעיל את המתודה אנחנו כותבים:
HttpContext.Current.Request.UserHostAddress;
כדי לדעת את זה ב - WCF צריך לכתוב את הקוד הבא:
var context = OperationContext.Current;
var prop = (RemoteEndpointMessageProperty)
context.IncomingMessageProperties[RemoteEndpointMessageProperty.Name];
string ip = prop.Address;
כתבתי כמה
פוסטים על הפעלה של WebService מתוך JavScript ומקבלים תוצאות ב - JSON.
זה עובד מעולה בתוך אותו דומיין.
Microsoft JScript runtime error: Permission denied
חבר לעבודה
(ערן גרוס, CTO you-niversity ארה"ב) הציע רעיון נהדר כדי לעקוף את הבעייה.
במקום לפנות מהסקריפט ל - WebService כדי לקבל את ה - JSON, ניתן לכתוב Handler שיחזיר JSON ולייבא אותו כקובץ JavaScript.
לדוגמא נכתוב את ה - Handler הבא: (הדוגמא להפעלה עם WebService מוסברת בפוסט
הזה)
public class Student
{
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public int Age { get; set; }
}
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Data : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/x-javascript";
var students = new Student[]
{
new Student(){ Name = "Shlomo",
Age = 24,
Phone = "123456",
Address = "Elad"},
new Student(){ Name = "Yossi",
Age = 23,
Phone = "543256",
Address = "Beni brak"},
new Student(){ Name = "Tomer",
Age = 30,
Phone = "0000000",
Address = "Tel Aviv"}
};
DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(Student[]));
MemoryStream stream = new MemoryStream();
json.WriteObject(stream, students);
stream.Seek(0, SeekOrigin.Begin);
StreamReader reader = new StreamReader(stream);
context.Response.Write(string.Format("var data = {0}", reader.ReadToEnd()));
}
public bool IsReusable
{
get
{
return false;
}
}
}
מוגדרת מחלקה בשם Student שאנחנו רוצים להחזיר מערך שלה.
המתודה ProcessRequest מגדירה שמה שחוזר ללקוח הוא מסוג application/x-javascript.
לאחר מכן היא מייצרת מערך של Student.
וכעת צריך לייצר אובייקט JSON מהמערך.
צריך להוסיף את ה - referencr הבאים:
System.Runtime.Serialization
System.ServiceModel.Web
הקוד שלאחר מכן כותב לתוך ה - stream את המידע ולאחר מכן מגדיר משתנה בשם data שמכיל את כל המידע.
כעת ב - html שלנו נכתוב כך:
<script type="text/javascript" src="Data.ashx"></script>
ובכל מקום בדף יהיה לנו משתנה גלובלי בשם data שמכיל את אותם Students.
כך נראה המשתנה data ב - watch (ב - Javascrip)
אלכס (ממשיך להפתיע מידי פעם) כתב מאקרו שימושי ל - Visual Studio.
(
וגיא דואג שיהיה לי על מה לכתוב)
------------
כשאנחנו סוגרים את Visual Studio נוכל להתחרט ולעצור את תהליך הסגירה רק במידה ויש לנו קובץ פתוח שלא נשמר - והסביבה תוודא האם אנחנו רוצים לשמור את הקובץ או לבטל את היציאה.
מאוד רצוי שהסביבה תוודא שאנחנו אכן רוצים לסגור את ה - Visual Studio גם אם אין קובץ שלא נשמר (פתיחה מחדש יכולה לקחת כמה דקות מעצבנות בפרוייקטים מספיק גדולים)
תחת Tools -> Macros -> Macros IDE או All + F11
נלחץ פעמיים על MyMacros (זה TreeView - רק שלא רואים את סימן הפלוס)
נכנס ל - EnvironmentEvents
ונוסיף את קטע הקוד הבא
Private Sub SolutionEvents_BeforeClosing() Handles SolutionEvents.BeforeClosing
Try
If MsgBox("Close Solution?", MsgBoxStyle.YesNo, "Close Solution") = MsgBoxResult.Yes Then
Return
End If
DTE.ItemOperations.NewFile("General\Text File", "Undo Close")
DTE.ActiveDocument.Selection.Text = "Press 'Cancel' to abort solution close."
Catch ex As Exception
MsgBox("Error in SolutionEvents_BeforeClosing macro: " + ex.Message)
End Try
End Sub
לא אכנס להסבר הקוד - אבל מה שזה יעשה - שבכל פעם שסוגרים את VS - נקבל שאלה האם אנחנו בטוחים שאנחנו רוצים לסגור את הסביבה.
ותודה לאלכס (על הפוסט) ולגיא (שאתה חושב עלי)
הפוסט הזה הוא באדיבות מיטל (חברה טובה ומתכנתת מאוד מוכשרת)
אם יש לכם Crystal Report שמכיל פרמטרים ו - SubReports ותכתבו קוד כמו זה
report.SetDataSource(RevenueReceipt());
report.SetParameterValue("barcode", "123456");
report.Subreports["Sub.rpt"].SetDataSource(SubDetails());
report.ExportToStream(ExportFormatType.PortableDocFormat);
תקבלו הודעת שגיאה כזאת:
CrystalDecisions.CrystalReports.Engine.ParameterFieldCurrentValueException was unhandled by user code
Message="Missing parameter values."
כדי לפתור את זה - צריך להפוך את הסדר, כלומר ההגדרה של ה - DataSource עבור ה - SubReport צריכה להיות לפני הגדרת הפרמטרים ל - Report
report.SetDataSource(RevenueReceipt());
report.Subreports["Sub.rpt"].SetDataSource(SubDetails());
report.SetParameterValue("barcode", "123456");
report.ExportToStream(ExportFormatType.PortableDocFormat);
מאחד הפיצ'רים שהודגמו שם ממש התלהבתי - מדובר על האפשרות לתת עיצוב ל - disabled controls בצורה די אוטומטית.
נניח שיש לנו את קוד ה - html הבא
<asp:TextBox ID="txt" runat="server"></asp:TextBox>
<asp:Button ID="btnEnable" Text="Enable" runat="server"
onclick="btnEnable_Click" />
<asp:Button ID="btnDisable" Text="Disable" runat="server"
onclick="btnDisable_Click" />
ובצד השרת
protected void btnEnable_Click(object sender, EventArgs e)
{
txt.Text = "Enable";
txt.Enabled = true;
}
protected void btnDisable_Click(object sender, EventArgs e)
{
txt.Text = "Disable";
txt.Enabled = false;
}
די ברור מה הקוד הזה יעשה - אבל עד היום עם היינו רוצים להגדיר עיצוב מיוחד לתיבת הטקסט שהיא disabled היינו צריכים לכתוב קוד כלשהו שיחליף את ה - CssClass.
כיום מה שאנחנו צריכים לעשות - זה להוסיף CssClass מיוחד שנקרא aspNetDisabled וההגדרות שבו יחולו על הפקדים שהם במצב disable
.aspNetDisabled
{
font-size:20pt;
}