שימוש נכון ב-handler
כאשר אנחנו רוצים להעביר מידע או להפעיל פקודה מה-client ל-server, נעשה זאת בשיטת ajax. (העדיפות היישומית שלי היא jQuery)
נניח שאנחנו רוצים לייצור משתמש חדש לאתר.
יש לנו את הפקדים בדף ופונקצייה רגילה register() ב-js שמתוכה אנחנו קוראים ל-service שיטפל בבקשה של יצירת משתמש.
עכשיו צריך לייצור את ה-service – הבעיה היא
במה נבחר?
WCF vs HttpHandler vs WebService.
WCF– הדרך הכי
טובה לקריאה מ-client ל-server. החיסרון שלה בעיקר שלא
כולם יודעים איך להשתמש בזה. ולכן לא נעסוק בנושא הזה.
חיסרון נוסף זה בשימוש ב-NHibernate בגלל ה-session (שגם לזה יש פיתרון אבל כמו שציינתי לא הרבה מכירים את זה).
חיסרון נוסף זה בשימוש ב-NHibernate בגלל ה-session (שגם לזה יש פיתרון אבל כמו שציינתי לא הרבה מכירים את זה).
HttpHandler vs WebService
ב-WebService יש מתודה שמוגדרת
ע"י אטריביוט [WebMethod()]
לכן הפנייה אליה תהיה: MyWebService.asmx/Register
אבל ידוע שרמת העיבוד של HttpHandler הרבה יותר מהירה מאשר WebService. (הסיבה לכך אני אסביר בפעם אחרת)
נוחות השימוש ב-HttpHandler כרגע הרבה
יותר מסובכת!
ב-Handler אנחנו
מקבלים QueryStrings למשל כזה:
עכשיו אנחנו נצטרך לנתח את הפנייה באמצעות האובייקט QueryStrings ולעשות switch לפי הפנייה לפונקצייה המבוקשת.
נצטרך גם לכתוב פונקצייה לכל בקשה ברמת ה-handler
לנתח את הפרמטרים של ה-QueryStrings
ואולי אף להפנות משם לפונקציות שהם ברמת ה-BL.
למשל:
public void
ProcessRequest(HttpContext context)
{
string request = context.Request.QueryString["request"] as
String;
context.Response.ContentType = "text/json";
context.Response.StatusCode = 200;
try
{
switch (request)
{
case "register":
context.Response.Write(Register(context)); break;
}
}
catch (Exception
ex)
{
context.Response.StatusCode = 500;
context.Response.Write(ex.Message);
}
}
private string Register(HttpContext
context)
{
string username = context.Request.QueryString["username"] as
String;
string email = context.Request.QueryString["email"] as
String;
string reemail = context.Request.QueryString["reemail"] as
String;
string password = context.Request.QueryString["password"] as
String;
var status = new HandleUser().CreateUser(username, email, reemail,
password);
if (!status.Equals( MembershipCreateStatus.Success)
)
{
context.Response.StatusCode = (int)status;
return new
JavaScriptSerializer().Serialize(status.ToString());
}
return new JavaScriptSerializer().Serialize("checkemail.aspx?e=" + email);
}
הקוד הנ"ל הוא לא ג'נרי לא אחיד ואין הפרדה של קוד. במקרה של
שינוי יש יותר ממקום אחד לטפל בו.
לכן כתבתי פיתרון ג'נרי כזה:
הגישה: קריאה ל-handler תעשה כמו קריאה לפונקצייה.
הנה דוגמא למימוש:
public class SimpleHandler : IHttpHandler
{
public const string request = "request";
public void
ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
NameValueCollection qs = new
NameValueCollection(context.Request.QueryString);
string methodname = qs[request];
qs.Remove(request);
object[] objs = new object[qs.Count];
qs.CopyTo(objs, 0);
new Services()
.GetType()
.InvokeMember(methodname,
BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
null,
null,
objs);
}
public bool
IsReusable
{
get
{
return false;
}
}
}
מחלקה שמטפלת בפונקציות של ה-services.
public class Services
{
public static void Register(string
username, string email, string reemail, string password)
{
HttpContext.Current.Response.Write("in register! username: " + username);
}
}
הפונקצייה של js לקריאת ה-handler:
function register(em) {
var $register = $(em).closest('#register');
var request = "request=register&"
+ $register.find('> *').serialize();
// request == request=Register&username=shlomi&email=wizardnet972%40gmail.com&reemail=wizardnet972%40gmail.com&password=123
$.getJSON('/ SimpleHandler.ashx', request, function (data, textStatus, xhr) {
debugger;
//location = data;
})
.error(function (xhr) {
alert(xhr.status + ": " +
xhr.responseText);
});
return false;
}
סיכום:
1.
קוד
ברור, ג'נרי ויעיל וה-session קיים לאורך כל התוכנית.
2.
הפרדה
ברורה של הקוד. (ORM)
3.
עפ"י
המימוש הזה, אין צורך לדאוג לכך לנתב את הבקשות לפונקצייה, מה שצריך לעשות זה
להוסיף פונקצייה ב-service וזה מוכן.
4.
הקריאה
ל-handler תתבצע כמו קריאה לפונקצייה, ואם אחד הפרמטרים
לא תואם נקבל exception מתאים.
5.
אין צורך
להתעסק ב-handler עצמו, רק במחלקת ה- Servicesבלבד.
6.
רמת
הסיכון של הקוד שואפת לאפס, אין חשיפת קוד בכלל.
--
זה פוסט ראשון שלי.
קצת עליי - זה יהיה כבר בפוסט הבא.
לכל שאלה ניתן לפנות בתגובה או באמצעות המייל:
wizardnet972@gmail.com
אז מה תגובתכם על המאמר הזה?