Category: การพัฒนา Web Application

  • มาทำความรู้จักกับ Validator ใน ASP.NET กันเถอะ

                ในการพัฒนาโปรแกรมโดยทั่วไป สิ่งหนึ่งที่นักพัฒนาควรคำนึงถึงและให้ความสำคัญในการรับค่าข้อมูลจากผู้ใช้ คือ การตรวจสอบความถูกต้องของข้อมูลที่รับเข้า เพื่อให้มั่นใจว่าข้อมูลที่ได้มาจะเป็นประโยชน์ สามารถนำไปใช้ในการประมวลผลต่อไปได้ และลดปัญหาการเก็บข้อมูลขยะไว้ในฐานข้อมูลซึ่งอาจทำให้ฐานข้อมูลมีขนาดใหญ่เกินความจำเป็น อีกทั้งยังถือเป็นการป้องกันความผิดพลาดที่อาจจะเกิดขึ้นจากการเก็บข้อมูลที่ไม่ถูกต้อง ในกรณีเลวร้ายอาจมีผลกระทบทำให้ฐานข้อมูลเกิดความเสียหายได้ ดังนั้น การตรวจสอบความถูกต้องของข้อมูลก่อนบันทึกถือเป็นสิ่งหนึ่งที่นับว่ามีความสำคัญสำหรับนักพัฒนาที่จะต้องคำนึงถึงในการเก็บข้อมูลจากผู้ใช้
                วิธีที่ใช้ในการตรวจสอบสามารถทำได้หลายวิธี ซึ่งเดิมผู้พัฒนาจะต้องเขียน Client-Script (อาจจะเป็น JavaScript VBScript หรือ JQuery) เพื่อใช้ในการตรวจสอบเองทั้งหมด โดยวิธีการนี้ผู้พัฒนาจะต้องมีความรู้เกี่ยวกับ Client Script เหล่านั้นพอสมควร และอาจต้องใช้เวลานานในกรณีที่มีการตรวจสอบที่ซับซ้อน แต่นับว่าเป็นโชคดีของนักพัฒนาที่ใช้เครื่องมือ ASP.NET ในการพัฒนาโปรแกรม เนื่องจาก .NET framework ได้จัดเตรียมเครื่องมือในการตรวจสอบเหล่านี้ไว้ให้เรียบร้อยแล้วตั้งแต่เวอร์ชั่น Visual Studio .NET 2003 เพื่ออำนวยความสะดวกให้กับผู้พัฒนาสามารถหยิบมาใช้ได้โดยง่าย ทำให้การตรวจสอบไม่ใช่เรื่องยากและซับซ้อนอีกต่อไป และยังถือเป็นการประหยัดเวลา ไม่จำเป็นต้องเขียนสคริปต์ตรวจสอบเองทั้งหมด เพียงกำหนด properties ต่างๆที่จำเป็นให้ validator เหล่านั้นและเลือกใช้ให้เหมาะสมกับความต้องการก็จะสามารถตรวจสอบความถูกต้องของข้อมูลได้โดยง่ายดาย ผู้เขียนจึงเห็นว่าการทำความเข้าใจกับความสามารถของ validator เหล่านี้ถือเป็นสิ่งสำคัญเพื่อช่วยในการตัดสินใจเลือก validator มาใช้ให้เหมาะสมกับงานและความต้องการในการตรวจสอบนั้นๆ
                หากแบ่ง Validator control ที่มีใน ASP.NET ตามลักษณะการทำงาน สามารถแบ่งออกได้เป็น 2 ลักษณะ ดังนี้

    การตรวจสอบข้อมูลในฝั่ง Client โดยการตรวจสอบข้อมูลในลักษณะนี้ จะเกิดขึ้นทันทีเมื่อผู้ใช้มีการป้อนข้อมูลเข้ามาและการตอบโต้นี้จะยังไม่มีการส่งค่าไปยังฝั่ง server ซึ่งข้อดีของการตรวจสอบในลักษณะนี้ คือ สามารถโต้ตอบกับผู้ใช้ในเวลาอันรวดเร็วและแสดงให้ผู้ใช้ทราบได้ทันทีว่าเกิดข้อผิดพลาดในการป้อนข้อมูล โดยไม่ต้องรอให้มีการเรียกใช้ไปยังฝั่งเซิร์ฟเวอร์ก่อนจึงจะตอบสนองกลับมายังผู้ใช้ และยังถือเป็นการลดจำนวนครั้งในเรียกใช้ไปยังฝั่งเซิร์ฟเวอร์โดยไม่จำเป็น ซึ่งหลักการทำงานของ Validator ของ ASP.NET ในลักษณะนี้ คือ Validator จะทำหน้าที่แปลง Validation เป็น JavaScript และถูกทำงานที่ฝั่ง Client ซึ่งจะขึ้นอยู่กับการทำงานของ Validation Control แต่ละประเภทที่ใช้นั่นเอง
    การตรวจสอบข้อมูลในฝั่งเซิร์ฟเวอร์ โดยการตรวจสอบในลักษณะนี้ จะเกิดขึ้นที่ฝั่งเซิร์ฟเวอร์ ซึ่งมีข้อดี คือ สามารถเพิ่มความปลอดภัยและความแม่นยำในการตรวจสอบอีกระดับก่อนจะบันทึกข้อมูลเหล่านั้นลงฐานข้อมูลในกรณีที่อาจมีข้อมูลผิดพลาดที่ตกสำรวจมาจากการตรวจสอบในฝั่ง Client โดยการตรวจสอบในลักษณะนี้ ผู้พัฒนาจะเป็นผู้เขียนโค้ดในการตรวจสอบตามเงื่อนไขที่กำหนดขึ้นเอง ซึ่ง ASP.NET ก็ได้มีการเตรียม validation control เพื่อรองรับการตรวจสอบในลักษณะนี้ไว้แล้วเช่นกัน

    โดย Validation control ที่มีเตรียมไว้ใน ASP.NET ประกอบด้วย Validator ชนิดต่างๆ ดังนี้
    • RequiredFieldValidator
    • RegularExpressionValidator
    • RangeValidator
    • CompareValidator
    • CustomValidator
    • Validation Summary

                เพื่อให้ง่ายต่อการทำความเข้าใจ ผู้เขียนจะขอพูดถึงการกำหนดค่า Properties ให้กับ validator หลักๆที่สำคัญที่ทุกตัวต้องมีไว้เป็นเบื้องต้น และจะเพิ่ม properties เพิ่มเติมที่แตกต่างจาก properties หลักของ validator แต่ละตัวดังนี้

    ID : เป็นการกำหนดชื่อ ID ให้กับตัว validator ซึ่งผู้เขียนแนะนำให้ตั้งชื่อให้สื่อความหมาย เพื่อง่ายต่อการต่อยอดในการพัฒนาร่วมกับผู้อื่น
    ControlToValidate : เป็นการกำหนดว่าจะให้ validator ดังกล่าวทำการควบคุมและตรวจสอบ control หรือ element ตัวใดในหน้าจอ
    Display : เป็นการกำหนดลักษณะในการแสดงผลของ validator ซึ่งมีด้วยกัน 3 แบบคือ

    o Static : แบบจองพื้นที่ในการแสดงผล validator กรณีมีข้อผิดพลาด แม้ไม่พบข้อผิดพลาด validator ก็จะยังคงจองพื้นที่ส่วนนั้นไว้เช่นกัน
    o Dynamic : จะแสดงผล validator เมื่อพบข้อผิดพลาด และเมื่อมีการแก้ไขข้อผิดพลาดดังกล่าวแล้ว Error message ของ validator ตัวดังกล่าวจะหายไปและลดพื้นที่ส่วนการแสดงผลให้เหมือนก่อนจะพบข้อผิดพลาด
    o None : ไม่แสดงผลบนหน้าจอ

    Error Message : เป็นการกำหนดข้อความที่ต้องการให้แสดง เมื่อผู้ใช้กรอกข้อมูลผิดพลาด ซึ่งถือเป็นการชี้แนะให้ผู้ใช้ทราบว่าความผิดพลาดดังกล่าวเกิดขึ้นจากสาเหตุใด และควรแก้ไขอย่างไร
    SetFocusOnError : เป็นการกำหนด Focus ให้กับ control ที่พบความผิดพลาด แต่หากในหน้าจอดังกล่าวพบข้อผิดพลาดหลายจุดและ validator ทุกตัวมีการกำหนดค่า SetFocusOnError เป็น true จะทำให้ Focus เลื่อนไปยังจุดที่มีข้อผิดพลาดจุดแรกที่พบทันที
    Text : เป็นการกำหนดในส่วนที่จะแสดงผล เมื่อ validator พบข้อผิดพลาดนั่นเอง ซึ่งโดยทั่วไปแล้วมักกำหนดให้แสดงเป็นเครื่องหมายดอกจันท์ หรือ * และวางไว้หลัง control ตัวที่ validator ดังกล่าวกำลังควบคุม เพื่อแจ้งให้ผู้ใช้ทราบว่าข้อมูลที่กรอกส่วนใดกำลังมีปัญหาหรือพบข้อผิดพลาดจากการตรวจสอบอยู่นั่นเอง
    ToolTip : เป็นการกำหนดข้อความที่ต้องการให้แสดงเมื่อผู้ใช้นำเมาส์ไปชี้ที่ validator ที่กำลังแสดงข้อผิดพลาดอยู่
    Validation group : เป็นการจัดกลุ่มให้กับ validator ที่ใช้ในการตรวจสอบ ซึ่งโดยปกติหากไม่กำหนดค่าในส่วนนี้จะถือว่า control ทั้งหมดในหน้าจอถูกจัดกลุ่มการควบคุมไว้เป็นกลุ่มเดียวกันทั้งหน้าจอ แต่หากมีบางกรณีที่ต้องการแยกกลุ่มในการตรวจสอบ ต้องมีการระบุ ValidationGroup ของปุ่มและ validator ที่ต้องการตรวจสอบเหล่านั้นให้เป็นกลุ่มเดียวกัน ซึ่งจะทำให้ validator ตัวอื่นที่ไม่ใช่กลุ่มดังกล่าวไม่ถูกนำมาตรวจสอบ เพราะถือว่าเป็นการตรวจสอบคนละส่วนกัน

                หลังจากที่ทราบ properties หลักที่จำเป็นต้องใช้ในการกำหนดค่าให้กับ validator ที่จะใช้งานแล้ว ผู้เขียนขออธิบายในรายละเอียดเพิ่มเติมทั้งในส่วนของหน้าที่การทำงานและการกำหนดค่า properties ที่จำเป็นอื่นๆของแต่ละ validator control ดังนี้

    RequiredFieldValidator
                การทำงานโดยทั่วไปของ validator นี้ จะใช้ในการตรวจสอบค่าว่างในการกรอกข้อมูล โดยหากกำหนดว่าต้องการควบคุมตัวใด การกรอกข้อมูลของ control ดังกล่าวจะถือเป็นข้อมูลบังคับกรอก หากไม่กรอกระบบจะแสดงข้อความแจ้งเตือนให้ทราบและไม่บันทึกข้อมูลให้ โดยการกำหนดค่า properties ต่างๆเพิ่มเติมจากที่กล่าวไว้แล้วข้างต้น คือ

    • InitialValue : ใช้เปรียบเทียบค่าจาก InitialValue ที่กำหนดใน validator กับค่าที่ผู้ใช้กรอกมาใน control ที่ validator ตัวนี้ควบคุมอยู่ ซึ่งโดยทั่วไปการใช้งาน RequiredFieldValidator อาจไม่จำเป็นต้องกำหนดค่าให้กับ  properties นี้ แต่ผู้เขียนจะขอยกตัวอย่างเพื่อให้ผู้พัฒนาเห็นภาพการทำงานของลักษณะการกำหนดค่า InitialValue  เพื่อนำไปประยุกต์ใช้งานได้ ดังนี้

    ตัวอย่างที่ 1 การเรียกใช้งาน RequiredFieldValidator  แบบทั่วไป(ไม่ได้กำหนดค่า InitialValue )

    <asp:TextBox ID="TxtEmail" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="ReqEmail" runat="server"
    ErrorMessage="Please enter your email-address" 
    ControlToValidate="TxtEmail" SetFocusOnError="True">*
    </asp:RequiredFieldValidator>

    ตัวอย่างที่ 2  เช่น กรณีที่มีการกำหนดค่า InitialValue และมีการเลือกประเภทจาก dropdownlist ที่มีชื่อว่า DdlType และบังคับเลือก

    <asp:DropDownList ID="DdlType" runat="server"> 
    <asp:ListItem Value="--Select--">--Select--</asp:ListItem>
    <asp:ListItem Value="Item1" />
    <asp:ListItem Value="Item2" />
    <asp:ListItem Value="Item3" />
    </asp:DropDownList>
    <asp:RequiredFieldValidator ID="ReqType" runat="server"
    ErrorMessage="Please select type" ControlToValidate="DdlType" 
    SetFocusOnError="True" InitialValue="--Select--" >*
    </asp:RequiredFieldValidator>

    จากตัวอย่างที่ 2 จะเห็นว่า ค่า InitialValue คือ “–Select–” นั่นหมายถึงว่า หากผู้ใช้เลือกรายการ “–Select–” จาก dropdownlist แล้วกดปุ่มบันทึก validator ดังกล่าวจะแสดงข้อผิดพลาดทันที

    RegularExpressionValidator

                เป็น validator ที่ใช้ในการตรวจสอบรูปแบบการกรอกของข้อมูล เช่น อีเมล์ หมายเลขโทรศัพท์ URL ของเว็บไซต์ หรือรหัสไปรษณีย์ เป็นต้น โดย properties  ที่สำคัญเพิ่มเติมจากที่กล่าวไว้แล้วในข้างต้นของ validator นี้คือ

    • ValidationExpression ซึ่งทาง .NET ได้มีการกำหนดรูปแบบ regular expression สำเร็จรูปในการตรวจสอบไว้ให้แล้วในเบื้องต้น แต่ผู้พัฒนาสามารถประยุกต์ใช้ และปรับแก้ให้รูปแบบของ regular expression ที่ใช้ในการตรวจสอบเป็นไปในแบบที่ต้องการได้

    ตัวอย่าง การใช้งาน ValidationExpression ในการตรวจสอบรูปแบบ URL ของเว็บไซต์

    <asp:TextBox ID="txtURL" runat="server"></asp:TextBox>
    <asp:RegularExpressionValidator ID="RegExURL" runat="server"
    ControlToValidate="txtURL" ErrorMessage="Internet URL 's format is incorrect" SetFocusOnError="True" ValidationExpression="http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&amp;=]*)?">*</asp:RegularExpressionValidator>

    จากตัวอย่าง พบว่า regular expression ที่ใช้ในการตรวจสอบรูปแบบของข้อมูล คือ  http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&amp;=]*)? ซึ่งเป็นแบบสำเร็จรูปที่ ASP.NET ได้เตรียมไว้ให้แล้ว

    RangeValidator

                เป็น validator ที่ใช้ในการตรวจสอบข้อมูลว่าอยู่ในช่วงของข้อมูลที่กำหนดหรือไม่ ซึ่งสามารถกำหนดชนิดของช่วงข้อมูลได้  โดย validator ตัวนี้จะไม่พบข้อผิดพลาดหากผู้ใช้ไม่กรอกข้อมูล หากต้องการตรวจสอบข้อมูลห้ามเป็นค่าว่างด้วยจะต้องทำงานร่วมกับ RequiredFieldValidator  สำหรับการใช้งาน validator ชนิดนี้มี properties ที่สำคัญในการกำหนดการใช้งานเพิ่มเติม ดังนี้

    • MaximumValue : เป็นการกำหนดค่าสูงสุดที่สามารถกรอกได้
    • MinimumValue : เป็นการกำหนดค่าข้อมูลต่ำสุดที่สามารถกรอกได้
    • Type :เป็นการกำหนดชนิดของข้อมูลที่จะทำการตรวจสอบช่วงของข้อมูลว่าให้มองเป็นชนิดใด โดยชนิดของข้อมูลประกอบด้วย
      • String : การตรวจสอบช่วงข้อมูลชนิดที่เป็นชนิด String นี้จะคำนวณค่าโดยเทียบกับ Ascii Code (http://www.lookuptables.com/)
      • Integer
      • Double
      • Date

    ตัวอย่างที่ 1 : การตรวจสอบช่วงของข้อมูลที่เป็นชนิด string

    <asp:DropDownList ID="DdlChoice" runat="server">
    
    <asp:ListItem Value="--Select--">--Select--</asp:ListItem>
    <asp:ListItem Value="A" >A</asp:ListItem>
    <asp:ListItem Value="B" >B</asp:ListItem>
    <asp:ListItem Value="C" >C</asp:ListItem>
    <asp:ListItem Value="D">D</asp:ListItem>
    <asp:ListItem Value="E">E</asp:ListItem>
    </asp:DropDownList>
    <asp:RangeValidator ID="RangeChoice" runat="server"
    ControlToValidate="DdlChoice" 
    ErrorMessage="Please select between A-D"
    MaximumValue="D" MinimumValue="A">*</asp:RangeValidator>

    จากตัวอย่างจะพบข้อผิดพลาดหากผู้ใช้เลือกรายการ “E” เนื่องจากเมื่อนำค่าดังกล่าวไปเปรียบเทียบกับค่าแบบ Ascii code แล้วจะมีค่าเกินช่วงที่กำหนดใน validator คือ A-D นั่นเอง

    ตัวอย่างที่ 2 : การตรวจสอบช่วงของข้อมูลที่เป็นชนิดตัวเลข

    Enter number (between 1 - 10) :
    <asp:TextBox ID="txtAmount" runat="server"></asp:TextBox>
    <asp:RangeValidator ID="RangeNumber" runat="server"
    ControlToValidate="txtAmount" 
    ErrorMessage="The data must be from 1 to 10"
    MaximumValue="10" MinimumValue="1" Type="Integer">*</asp:RangeValidator>

    CompareValidator

                เป็น validator ที่ใช้ในการเปรียบเทียบค่าหรือตรวจสอบชนิดของข้อมูลที่กรอก โดยตัวอย่างที่ใช้กันบ่อยมักเป็นการเปรียบเทียบค่า 2 ค่า เช่น กรณีการระบุรหัสผ่าน และยืนยันรหัสผ่าน หรือกรณีต้องการตรวจสอบชนิดของจำนวนเงินว่าต้องเป็นตัวเลขเท่านั้น เป็นต้น โดย properties เพิ่มเติมที่ใช้ในการกำหนด มีดังนี้

    • ValueToCompare : เป็น properties ที่ใช้ในกรณีที่ต้องการเปรียบเทียบค่าที่รับจากผู้ใช้กับค่าคงที่ที่ระบุ
    • ControlToCompare : เป็น properties ที่ใช้กำหนดคอนโทรลตัวที่ต้องการเปรียบเทียบค่า(ในกรณีที่มีการเปรียบเทียบค่าจาก 2 คอนโทรล)
    • Operator :เป็นpropertiesที่ใช้ในการกำหนดการปฏิบัติการในการเปรียบเทียบค่า มีดังนี้
      • Equal : ค่าของข้อมูลที่รับมาต้องมีค่าเท่ากันกับค่าที่ต้องการเปรียบเทียบ
      • NotEqual : ค่าของข้อมูลที่รับมาต้องไม่เท่ากับค่าที่ต้องการเปรียบเทียบ
      • GreaterThan : ค่าของข้อมูลที่รับมาต้องมีค่ามากกว่าค่าที่ต้องการเปรียบเทียบ
      • GreaterThanEqual : ค่าของข้อมูลที่รับมาต้องมีค่ามากกว่าหรือเท่ากับค่าที่ต้องการเปรียบเทียบ
      • LessThan : ค่าของข้อมูลที่รับมาต้องมีค่าน้อยกว่าค่าที่ต้องการเปรียบเทียบ
      • LessThanEqual : ค่าของข้อมูลที่รับมาต้องมีค่าน้อยกว่าหรือเท่ากับค่าที่ต้องการเปรียบเทียบ
      • DataTypeCheck : เป็นการระบุการตรวจสอบชนิดของข้อมูล และทำงานร่วมกับ properties ที่ชื่อว่า Type โดยการกำหนด properties นี้ จะส่งผลให้ค่าที่ถูกกำหนดไว้ให้กับ properties ที่มีชื่อว่า ValueToCompare และ ControlToCompare ไม่ทำงาน
    • Type : ชนิดของข้อมูลที่ต้องการตรวจสอบ
    หมายเหตุ : ค่าที่ต้องการเปรียบเทียบอาจเป็นค่าที่มาจากคอนโทรลอีกตัวที่ต้องการเปรียบเทียบ(ControlToCompare) หรือมาจากค่าที่กำหนดไว้ใน ValueToCompare นั่นเอง ซึ่งค่า properties ทั้งสองนี้ไม่ควรกำหนดร่วมกัน ควรเลือกใช้เพียงตัวใดตัวหนึ่งเท่านั้น แต่หากมีการกำหนดทั้ง 2 ค่าพร้อมกัน การทำงานของ ControlToCompare จะมีลำดับในการทำงานก่อน


    ตัวอย่างที่
    1
    การเปรียบเทียบค่าข้อมูล 2 ค่าจากคอนโทรล เช่น กรณีการพิมพ์รหัสผ่านและยืนยันรหัสผ่าน เป็นต้น

    Password :<asp:TextBox ID="txtPassword" runat="server">
    </asp:TextBox><br />
    Retype-password :<asp:TextBox ID="txtConfirmPassword" 
    runat="server"></asp:TextBox> 
    <asp:CompareValidator ID="CmpPassword" runat="server" 
    ErrorMessage="Password must be the same" 
    ControlToCompare="txtPassword" ControlToValidate="txtConfirmPassword">*</asp:CompareValidator>
    
    

    ตัวอย่างที่ 2 การเปรียบเทียบค่าของข้อมูลกับค่าคงที่ที่กำหนด กรณีที่ต้องกรอกข้อมูลที่มีค่ามากกว่าหรือเท่ากับ 18

    Age :<asp:TextBox ID="txtAge" runat="server"></asp:TextBox>
    <asp:CompareValidator ID="CmpAge" runat="server" 
    ControlToValidate="txtAge" 
    ErrorMessage="Age must greater than or equal 18 years old"
    Operator="GreaterThanEqual" ValueToCompare="18">*
    </asp:CompareValidator>
    
    

    ตัวอย่างที่ 3 การตรวจสอบชนิดของข้อมูล กรณีกรอกข้อมูลราคาต้องเป็นตัวเลขเท่านั้น

    Price : <asp:TextBox ID="txtPrice" runat="server"></asp:TextBox>
    
    <asp:CompareValidator ID="CmpType" runat="server" 
    ControlToValidate="txtPrice" ErrorMessage="Price must be number" 
    Operator="DataTypeCheck" Type="Double">*</asp:CompareValidator>

    CustomValidator

                หากการตรวจสอบด้วย validator ที่กล่าวมาก่อนหน้านี้ ยังไม่ครอบคลุมการตรวจสอบที่ต้องการ นักพัฒนาสามารถกำหนดเงื่อนไขในการตรวจสอบ และการทำงานนอกเหนือจากที่ validator ที่ ASP.NET เตรียมไว้ให้ขึ้นได้เอง โดยใช้ validator ประเภท CustomValidator ซึ่ง validator ประเภทนี้ จะมีช่องทางในการตรวจสอบสำหรับผู้พัฒนาเตรียมไว้ให้ทั้ง 2 ฝั่ง คือทั้งฝั่ง client และฝั่ง server โดยมี properties ที่จำเป็นเพิ่มเติมจาก properties หลัก ดังนี้

    • ClientValidationFunction : เป็นการกำหนดค่าของฟังก์ชั่นในฝั่ง client ที่ใช้ในการตรวจสอบข้อมูล
    • OnServerValidate : เป็นการกำหนดฟังก์ชั่น event หรือเมธอดที่ใช้ในการตรวจสอบข้อมูลในฝั่งเซิร์ฟเวอร์

    ตัวอย่างที่ 1 การใช้งาน custom validator ในการตรวจสอบค่าข้อมูลจากฝั่ง client

    <script type="text/javascript">
    function CheckData(oSrc, args) {
    if(args.Value.length >= 5 && args.Value.search('-') == -1)
    args.IsValid = true;
    else
    args.IsValid = false;
    oSrc.innerText = "(Your custom message here) ";
    }
    </script>
    
    <asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>
    <asp:CustomValidator ID="CustomUsername" runat="server" 
    ClientValidationFunction="CheckData" ControlToValidate="txtUserName" 
    ErrorMessage="Username must be greater than or equal 5 letters and cannot contain contain '-'">*</asp:CustomValidator>
    
    หมายเหตุ : หากต้องการเปลี่ยนแปลงข้อความผิดพลาดที่ต้องการแสดงสามารถทำได้โดยกำหนด      oSrc.innerText ในฟังก์ชั่น JavaScript นั้น

    ตัวอย่างที่ 2 การใช้งาน custom validator ในการตรวจสอบค่าข้อมูลจากทั้งฝั่ง client และฝั่งเซิร์ฟเวอร์

    ฝั่ง Client

    <script type="text/javascript">
    function CheckData(oSrc, args) {
    if(args.Value.length >= 5 && args.Value.search('-') == -1)
    args.IsValid = true;
    else
    args.IsValid = false;
    
    </script>
    <asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>
    <asp:CustomValidator ID="CustomUsername" runat="server"
    ClientValidationFunction="CheckData" 
    ControlToValidate="txtUserName"
    ErrorMessage="Username must greater than or equal 5 letters and cannot contain '-' " onservervalidate="CustomUsername_ServerValidate">*
    </asp:CustomValidator>
    
    

    ฝั่งเซิร์ฟเวอร์

    protected void CustomUsername_ServerValidate(object source, ServerValidateEventArgs args)
    {
    string username = args.Value;
    string[] Users = {"Amanda","Robert","John","Jennie"};
    if (Users.Contains(username))
    {
    args.IsValid = false;
    
    CustomUsername.ErrorMessage = "Username is already exists in database.";
    }
    else
    args.IsValid = true;
    }
    

                จากตัวอย่างจะมีการตรวจสอบค่าข้อมูลรหัสผู้ใช้จากฝั่ง client ก่อน ว่าต้องมีความยาวตั้งแต่ 5 ตัวอักขระขึ้นไปและต้องไม่ประกอบด้วย “-” หากมีเงื่อนไขครบตามกำหนดจะทำการตรวจสอบอีกครั้งในฝั่งเซิร์ฟเวอร์ว่าจะต้องไม่ซ้ำกับค่าที่มีอยู่แล้วจากข้อมูลรหัสผู้ใช้สมมติที่มีอยู่ และหากพบข้อผิดพลาดจะมีการแสดงข้อความแจ้งบอก

    Validation Summary

                เป็น validator ที่ใช้ในการสรุปข้อผิดพลาดทั้งหมดที่เกิดขึ้นในหน้าจอดังกล่าว ซึ่งอาจมีการระบุ ValidationGroup เพื่อแยกกลุ่มการตรวจสอบตามที่ได้กล่าวไว้แล้วข้างต้นได้ โดยการใช้งาน validator ตัวนี้จะประกอบด้วย properties ที่สำคัญ ดังนี้

    • DisplayMode :เป็นรูปแบบในการแสดงผลสรุปรวมข้อผิดพลาด ซึ่งประกอบด้วย
      • List : เป็นการแสดงผลแบบเว้นบรรทัด
      • BulletList : เป็นการแสดงผลแบบ bullet ซึ่งโดยปกติจะมีค่าตั้งต้นเป็นการแสดงผลในรูปแบบนี้
      • SingleParagraph : เป็นการแสดงผลข้อผิดพลาดแบบเว้นวรรคต่อกันในบรรทัดเดียวกันไปเรื่อยๆ

    ตัวอย่างผลลัพธ์การแสดงผลของ DisplayMode ในแต่ละแบบ

    DisplayMode

    • HeaderText : เป็นการระบุข้อความที่ต้องการให้แสดงในส่วนบนของข้อสรุปผิดพลาดทั้งหมดที่เกิดขึ้น
    • ShowMessageBox : เป็นการกำหนดว่าต้องการให้แสดงผลสรุปในรูป MessageBox หรือไม่ ซึ่ง properties ดังกล่าวจะไปทำการสร้างฟังก์ชั่นที่เรียกใช้งาน alert() ของ JavaScript เพื่อการแสดงผลสรุปข้อผิดพลาดนี้
    • ShowSummary : เป็นการแสดงผลรายการข้อผิดพลาดในรูปแบบ HTML ในตำแหน่งที่ validator ตัวนี้ถูกวางอยู่

    ตัวอย่างที่ 1 การใช้ ValidationSummary ในการสรุปข้อผิดพลาดในหน้าจอโดยแสดงผลในรูปแบบ MessageBox

    Username : <asp:TextBox ID="txtUserName" runat="server">
    </asp:TextBox>
    <asp:CustomValidator ID="CustomUsername" runat="server" 
    ClientValidationFunction="CheckData" ControlToValidate="txtUserName" 
    ErrorMessage="Username must greater than or equal 5 letters and cannot contain '-' "  onservervalidate="CustomUsername_ServerValidate">*
    </asp:CustomValidator><br />
    Password :
    <asp:TextBox ID="txtPass" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="ReqPass" runat="server" 
    ControlToValidate="txtPass" ErrorMessage="Password">*
    </asp:RequiredFieldValidator>
    <asp:ValidationSummary ID="ValidationSummary" runat="server"
    HeaderText="Errors:" ShowMessageBox="True" />
    
    

                จากบทความข้างต้น หากผู้พัฒนาเลือกใช้ validator ให้ตรงและเหมาะสมกับงาน น่าจะเป็นประโยชน์และช่วยอำนวยความสะดวกในการตรวจสอบข้อมูลให้ง่ายและรวดเร็วขึ้น และผู้เขียนหวังเป็นอย่างยิ่งว่าข้อมูลการใช้งาน validator จากบทความนี้จะมีส่วนช่วยในการตัดสินใจของผู้พัฒนาในการเลือกหยิบ validator มาใช้งานไม่มากก็น้อย หากมีข้อผิดพลาดประการใด ผู้เขียนขออภัยไว้ ณ ที่นี้ด้วยค่ะ

    แหล่งข้อมูลอ้างอิง :
    http://www.codeproject.com/Articles/3882/ASP-NET-Validators-Unclouded
    http://www.codeproject.com/Articles/334310/Understanding-ASP-NET-Validation-Techniques
    http://www.codeproject.com/Articles/7943/Validator-Controls-in-ASP-NET

  • ทำอย่างไรให้สามารถกำหนดจุดพิกัดบนแผนที่ Google map แบบจุดเดียวและหลายจุดจากฐานข้อมูลได้ด้วย ASP.NET C#

          การพัฒนาเว็บไซต์ในปัจจุบัน พบว่ามีบางเว็บไซต์มีความต้องการในการแสดงผลตำแหน่ง ที่ตั้งบนแผนที่ Google map เพื่ออำนวยความสะดวกให้กับผู้เยี่ยมชมเว็บไซต์ในการค้นหาตำแหน่งที่ตั้งของสถานที่นั้นๆมากกว่าการบอกเพียงที่อยู่อย่างเช่นแต่ก่อน อาธิเช่น เว็บไซต์ที่เป็นศูนย์รวมในการจองที่พัก ที่มีความจำเป็นต้องแสดงที่ตั้งของโรงแรมที่มีในบริเวณหรือละแวกนั้นๆที่เข้ามาร่วมให้ข้อมูลกับเว็บไซต์ในการจองที่พัก หรือแม้กระทั่งโรงพยาบาล ห้างสรรพสินค้า โรงเรียน มหาวิทยาลัย ที่เว็บไซต์ต้องการแสดงที่ตั้งเพื่อให้ผู้เยี่ยมชมเว็บไซต์สามารถทราบได้ว่าสถานที่เหล่านั้นมีที่ตั้งอยู่ในบริเวณใดบ้าง เพื่อเป็นประโยชน์ให้ผู้ที่เข้ามาเยี่ยมชมเว็บไซต์สามารถเรียกดูได้จากแผนที่เพื่อศึกษาเส้นทาง หรือหาตำแหน่งที่จะสามารถไปยังจุดนั้นๆได้โดยง่ายและใช้ระยะทางใกล้ที่สุดนั่นเอง
          ในบทความนี้ ผู้เขียนจึงขอพูดถึงวิธีการแสดงผลตำแหน่งที่ตั้งบน Google map ซึ่งมีทั้งแบบกำหนดตายตัว โดยมีการระบุตำแหน่งที่ตั้งทั้งละติจูดและลองจิจูด และแบบที่มีการดึงค่าของละติจูดและลองจิจูดมาจากฐานข้อมูลของเว็บไซต์ที่พัฒนาโดยใช้เครื่องมือ ASP.NET ด้วย C# และแบบที่มีการกำหนดจุดแสดงตำแหน่งเพียงจุดเดียวและหลายจุดพร้อมกัน เพื่อประโยชน์กับนักพัฒนาท่านอื่นๆที่มีความสนใจสามารถนำไปประยุกต์ใช้กับเว็บไซต์ของตนได้

          โดยผู้เขียนขอเสนอวิธีการเบื้องต้นในการแสดงผลแบบกำหนดค่าตายตัวให้ผู้อ่านลองศึกษาการทำงานเพื่อทำความเข้าใจในเบื้องต้นก่อน ดังนี้

    การแสดงผลแบบจุดเดียว

    1. อ้างอิงพาธที่ตั้งของ Google API ซึ่งเป็นส่วนหนึ่งของการแสดงผลบนแผนที่ Google map และไฟล์จาวาสคริปต์ที่ใช้ในการแสดงผล(ถ้ามี)
    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
     
    <script src="js/mapwithmarker.js" type="text/javascript"></script>
    1. กำหนดสไตล์ชีทที่ใช้ในการแสดงผล เมื่อมีการคลิกตำแหน่งที่ได้ทำการกำหนดพิกัดไว้
    <style type="text/css">  
    .labels { color: black; background-color: #FF8075; font-family: Arial; font-size: 11px; font-weight: bold; text-align: center; width: 12px; }  </style>
    1. กำหนดพิกัดที่ต้องการให้แผนที่ค้นหาจุดกึ่งกลางของการแสดงผล ซึ่งโดยปกติจะถือเอาจุดแรกที่ต้องการแสดงเป็นตำแหน่งกึ่งกลางของการแสดงผลตำแหน่งบนแผนที่นั้นๆ เพื่อให้ตำแหน่งดังกล่าวอยู่กึ่งกลางของแผนที่ที่ต้องการแสดงนั่นเอง
    var mapOptions = {  
    center: new google.maps.LatLng(ค่าละติจูด, ค่าลองจิจูด),  
    zoom: 12, 
    ///ขนาดที่ต้องการให้ซูมเป็นค่าตั้งต้น  
    mapTypeId: google.maps.MapTypeId.ROADMAP  };
    1. กำหนดส่วนที่ต้องการให้แสดงแผนที่ ว่าต้องการให้แสดงในส่วนใดของเว็บไซต์
    var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
     ///ในที่นี้พื้นที่ที่ต้องการให้แสดงผลในเว็บไซต์ คือ dvMap โดยนำค่าที่กำหนดกึ่งกลางไว้ในขั้นตอนที่ 3 (mapOptions) มาเป็นค่าพารามิเตอร์ในการแสดงผลด้วย
    
    1. การกำหนดจุดพิกัดที่ต้องการแสดงผล ซึ่งค่าที่ต้องการคือ ชื่อสถานที่ ค่าละติจูด ลองจิจูด และคำอธิบายในการแสดงผลตำแหน่งสถานที่ที่เราทำการกำหนดไว้ ดังนี้
      • กำหนดค่าพิกัดลองจิจูดและละติจูดของจุดที่เราต้องการกำหนดบนแผนที่
      var infoWindow = new google.maps.InfoWindow();
       var myLatlng = new google.maps.LatLng(ค่าละติจูด, ค่าลองจิจูด);
      
      
      • กำหนดค่าพิกัดตำแหน่งของจุดและพารามิเตอร์ต่างๆที่จำเป็นต้องใช้ในการกำหนดจุดที่เราต้องการกำหนดบนแผนที่
      var marker = new MarkerWithLabel({
       position: myLatlng, //เป็นการกำหนดค่าพิกัดตำแหน่งของจุดที่เราต้องการกำหนดบนแผนที่
       map: map, //เป็นการกำหนดพื้นที่ที่ต้องการแสดงแผนที่ ในที่นี้คือ dvMap
       title: title, //เป็นการกำหนดชื่อสถานที่
       labelContent:1,  //เป็นการกำหนดหมายเลขลำดับของตำแหน่งแสดงผล
       labelAnchor: new google.maps.Point(7, 30),
       labelClass: "labels", //เป็นการกำหนดรูปแบบในการแสดงผลด้วยสไตล์ชีท
       labelInBackground: false
       });
      
      
      • กำหนดการแสดงผลเมื่อผู้เยี่ยมชมมีการคลิกบนจุดดังกล่าว
      (function(marker) {
       google.maps.event.addListener(marker, "click", function(e) {
       infoWindow.setContent(description);
       //เป็นการกำหนดข้อความที่ต้องการแสดง เมื่อผู้เยี่ยมชมเว็บไซต์คลิกบนจุดดังกล่าว
       infoWindow.open(map, marker);
       });
       })(marker);
      
      
    1. สร้างพื้นที่ที่กำหนดการแสดงผลในส่วน body
    <div id="dvMap" style="width: 800px; height: 700px;">
     </div>
    1. แสดง code ทั้งหมดที่ใช้
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     <html xmlns="http://www.w3.org/1999/xhtml">
     <head runat="server">
     <title>Google map Test for one point</title>
     <style type="text/css">
     .labels { color: black; background-color: #FF8075; font-family: Arial; font-size: 11px; font-weight: bold; text-align: center; width: 12px; }
     </style>
     <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
     <script src="js/mapwithmarker.js" type="text/javascript"></script>
     <script type="text/javascript">
     window.onload = function() {
     var mapOptions = {
     center: new google.maps.LatLng(7.006923, 100.500238),
     zoom: 12,
     mapTypeId: google.maps.MapTypeId.ROADMAP
     };
     var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
     var infoWindow = new google.maps.InfoWindow();
     var myLatlng = new google.maps.LatLng(7.006923, 100.500238);
     var marker = new MarkerWithLabel({
     position: myLatlng,
     map: map,
     title: 'มหาวิทยาลัยสงขลานครินทร์',
     labelContent: 1,
     labelAnchor: new google.maps.Point(7, 30),
     labelClass: "labels", // the CSS class for the label
     labelInBackground: false
     });
     (function(marker ) {
     google.maps.event.addListener(marker, "click", function(e) {
     infoWindow.setContent('มหาวิทยาลัยสงขลานครินทร์ วิทยาเขตหาดใหญ่');
     infoWindow.open(map, marker);
     });
     })(marker );
     }
     </script>
     </head>
     <body>
     <form id="form1" runat="server">
     <div id="dvMap" style="width: 800px; height: 700px;">
     </div>
     </form>
     </body>
     </html>

    ตัวอย่างภาพผลลัพธ์ที่ได้ :
    Map1point

    แบบหลายจุดและดึงค่าละติจูด ลองจิจูดจากฐานข้อมูลมาแสดงผล

    โดยลักษณะการเขียนจะคล้ายๆกับแบบกำหนดจุดเพียงจุดเดียวอย่างที่กล่าวไว้แล้วในตอนต้น แต่จะแตกต่างกันในส่วนของการดึงข้อมูล ซึ่งจะเน้นเฉพาะส่วนที่แตกต่าง และแสดง code สรุปรวมให้ดูอีกครั้ง

    ไฟล์ default.aspx ในฝั่ง Client

    1. กำหนดค่าตัวแปรที่ใช้ในแสดงผลจาก Repeater ซึ่งเป็นเครื่องมือที่มีอยู่แล้วใน .NET โดยตัวแปรที่จะใช้ที่นี้ให้มีชื่อว่า markers และค่าที่ต้องการนำมาใช้จะเป็นฟิลด์ของ Name, Latitude, Longitude และ Description ซึ่งดึงมาจากฐานข้อมูล(โดยชื่อฟิลด์สามารถเปลี่ยนแปลงได้ตามข้อมูลที่มีอยู่จริงในฐานข้อมูลของแต่ละท่าน)
      <script type="text/javascript">
       var markers = [
       <asp:Repeater ID="rptMarkers" runat="server">
       <ItemTemplate>
       {
       "title": '<%# Eval("Name") %>',
       "lat": '<%# Eval("Latitude") %>',
       "lng": '<%# Eval("Longitude") %>',
       "description": '<%# Eval("Description") %>'
       }
       </ItemTemplate>
       <SeparatorTemplate>
       ,
       </SeparatorTemplate>
       </asp:Repeater>
       ];
       </script>
    2. กำหนดพิกัดที่ต้องการให้แผนที่ค้นหาจุดกึ่งกลางของการแสดงผล ซึ่งโดยปกติจะถือเอาจุดแรกที่ต้องการแสดงเป็นตำแหน่งกึ่งกลางของการแสดงผลตำแหน่งบนแผนที่นั้นๆ เพื่อให้ตำแหน่งดังกล่าวอยู่กึ่งกลางของแผนที่ที่ต้องการแสดงนั่นเอง
      var mapOptions = {
       center: new google.maps.LatLng(markers[0].lat, markers[0].lng),
       zoom: 8,
       mapTypeId: google.maps.MapTypeId.ROADMAP};
    3. กำหนดค่าต่างๆ และวนค่าตัวแปร markers ที่ดึงมาจากฐานข้อมูลและตัว Repeater ที่กล่าวไว้ในข้างต้น และทำการกำหนดค่าต่างๆให้กับแต่ละจุดที่ต้องการ โดยรายละเอียดในการกำหนดค่าจะคล้ายกับวิธีกำหนดแบบจุดเดียว(แบบแรก) แต่จะมีการวนซ้ำให้ครบจำนวนตัวแปรที่ดึงมาจากฐานข้อมูล
      var infoWindow = new google.maps.InfoWindow();
       var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
       for (i = 0; i < markers.length; i++) {
       //เป็นการวนค่าตัวแปร markers ที่ดึงมาจากฐานข้อมูลและตัว Repeater ที่กล่าวไว้ในข้างต้น
      
        var data = markers[i]
       //นำค่าจากตัวแปร markers  ที่ดึงมาทีละรายการตามลำดับมาใส่ไว้ในตัวแปร data เพื่อนำไปใช้ในการกำหนดค่าต่อไป
      var myLatlng = new google.maps.LatLng(data.lat, data.lng);
       //กำหนดค่าละติจูดและลองจิจูด
      var marker = new MarkerWithLabel({
       position: myLatlng, //เป็นการกำหนดตำแหน่งที่ต้องการแสดงผล
      map: map,
       title: data.title, //เป็นการกำหนดชื่อที่ต้องการแสดงผลเมื่อนำเมาส์ไปชี้ยังจุดดังกล่าว
      labelContent: i+1//เป็นการกำหนดหมายเลขลำดับให้กับจุดดังกล่าว
       labelAnchor: new google.maps.Point(7, 30),
       labelClass: "labels", // the CSS class for the label
       labelInBackground: false}
       );(function (marker, data) {google.maps.event.addListener(marker, "click", function (e) {
       infoWindow.setContent(data.description);
       //เป็นการกำหนดข้อความที่ต้องการแสดง เมื่อผู้เยี่ยมชมเว็บไซต์คลิกบนจุดดังกล่าว
      infoWindow.open(map, marker);
       });
       })(marker, data);
       }
    4. Code ทั้งหมดในฝั่งไฟล์ Default.aspx
      <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
      
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
       <html xmlns="http://www.w3.org/1999/xhtml">
       <head runat="server">
       <title></title>
       </head>
       <body>
       <form id="form1" runat="server">
       <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script><script src="js/mapwithmarker.js" type="text/javascript"></script>
      <script type="text/javascript">
       var markers = [
       <asp:Repeater ID="rptMarkers" runat="server">
       <ItemTemplate>
       {
       "title": '<%# Eval("Name") %>',
       "lat": '<%# Eval("Latitude") %>',
       "lng": '<%# Eval("Longitude") %>',
       "description": '<%# Eval("Description") %>'
       }
       </ItemTemplate>
       <SeparatorTemplate>
       ,
       </SeparatorTemplate>
       </asp:Repeater>
       ];
       </script>
       <script type="text/javascript">
       window.onload = function() {
       var mapOptions = {
       center: new google.maps.LatLng(markers[0].lat, markers[0].lng),
       zoom: 8,
       mapTypeId: google.maps.MapTypeId.ROADMAP
       };
       var infoWindow = new google.maps.InfoWindow();
       var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
       var j = 1;
       for (i = 0 ; i <= markers.length-1; i++) {
       var data = markers[i]
       var myLatlng = new google.maps.LatLng(data.lat, data.lng);
       // var marker = new google.maps.Marker({
       var marker = new MarkerWithLabel({
       position: myLatlng,
       map: map,
       title: data.title,
       labelContent: i+1,
       labelAnchor: new google.maps.Point(7, 30),
       labelClass: "labels", // the CSS class for the label
       labelInBackground: false
       });
       (function(marker, data) {
       google.maps.event.addListener(marker, "click", function(e) {
       infoWindow.setContent(data.description);
       infoWindow.open(map, marker);
       });
       })(marker, data);
       }
       }
       </script>
       <div id="dvMap" style="width: 500px; height: 500px">
       </div>
       </form>
       </body>
       </html>

     

    ไฟล์ default.cs ในฝั่ง server

    using System;
     using System.Collections.Generic;
     using System.Web;
     using System.Web.UI;
     using System.Web.UI.WebControls;
     using System.Data;public partial class _Default : System.Web.UI.Page
     {
     protected void Page_Load(object sender, EventArgs e)
     {
     if (!this.IsPostBack)
     {
     rptMarkers.DataSource = GetData();
    //กำหนดแหล่งข้อมูลให้กับตัว Repeater ที่เราต้องการใข้ในการแสดงผล
     rptMarkers.DataBind();
     }
     }
      private DataTable GetData()
    //เมธอดที่ใช้ในการดึงค่าข้อมูลจากฐานข้อมูล ซึ่งในที่นี้มีการส่งค่ากลับเป็น datatable และมีการสมมุติค่าข้อมูลใน datatable เพื่อให้เห็นภาพการดึงจากฐานข้อมูลเท่านั้น แต่สามารถนำไปประยุกต์ใช้กับการติดต่อฐานข้อมูลจริงได้  {
     DataTable table = new DataTable();
     table.Columns.Add("Name", typeof(string));
     table.Columns.Add("Latitude", typeof(decimal));
     table.Columns.Add("Longitude", typeof(decimal));
     table.Columns.Add("Description", typeof(string));
     table.Rows.Add("มหาวิทยาลัยสงขลานครินทร์", 7.006923, 100.500238, "Hatyai");
     table.Rows.Add("มหาวิทยาลัยราชภัฏ สงขลา", 7.172661, 100.613726, "Songkla");
     return table;
     }
     }
    1. ดึงข้อมูลจากแหล่งข้อมูลที่ต้องการ ซึ่งประกอบด้วยข้อมูลตามที่ต้องการให้แสดงผล เช่น ค่าละติจูด ลองจิจูด และชื่อสถานที่ โดยในกรณีนี้ผู้เขียนขอสมมติค่าและสร้าง datatable ขึ้นมา เพื่อใช้ในการทดสอบ โดยแสดงในเมธอด GetData() หากเป็นข้อมูลที่ใช้จริงผู้พัฒนาสามารถนำไปประยุกต์กับการดึงข้อมูลของท่านได้
    2. กำหนดค่าแหล่งข้อมูลให้กับ repeater เพื่อสร้างตัวแปร marker ตามที่กล่าวไว้ในข้างต้น
    3. ผลลัพธ์ที่ได้ :

    Mapmultipoint

           ผู้เขียนหวังเป็นอย่างยิ่งว่า บทความนี้จะเป็นประโยชน์กับนักพัฒนาบางท่านที่กำลังสนใจ และต้องการนำวิธีดังกล่าวไปใช้กับเว็บไซต์ที่ตนกำลังพัฒนาอยู่ หากมีข้อผิดพลาดประการใดผู้เขียนขออภัยไว้ ณ ที่นี้ด้วย และหากผู้รู้ท่านใดมีคำแนะนำหรือข้อเสนอแนะเพิ่มเติมเกี่ยวกับเรื่องนี้ สามารถแลกเปลี่ยนความรู้กันได้เพื่อประโยชน์ในการต่อยอดความรู้ร่วมกันค่ะ

    แหล่งข้อมูลอ้างอิง :
    http://www.dotnetbull.com/2013/06/multiple-marker-with-labels-in-google.html
    http://www.codeproject.com/Articles/36151/Show-Your-Data-on-Google-Map-using-C-and-JavaScrip

  • ทำความรู้จักกับ Bootstrap

    สำหรับในบทความนี้ เป็นภาคต่อจาก “เตรียมความพร้อมก่อนการพัฒนา Web Application ” โดยจะมาทำความรู้จักกับ Bootstrap กันให้มากขึ้น ซึ่ง Bootstrap จัดเป็น Front-end Framework  ที่กำลังได้รับความนิยมเป็นอย่างมากในปัจจุบัน อาจจะเป็นเพราะว่า Bootstrap มีแนวทางในการพัฒนาในแบบ Responsive Web Design ก็เป็นได้ (บทความ แนวทางการพัฒนาเว็บแบบ Responsive Web Design)

    แนวคิดของ Bootstrap จะให้ความสำคัญกับการออกแบบการแสดงผลในอุปกรณ์ขนาดเล็กก่อน (Mobile First Approach) กล่าวคือ การสร้างเว็บไซต์ 1 หน้าสำหรับ Content ชุดเดียวกัน เราต้องออกแบบการแสดงผลให้ครอบคลุมหน้าจออย่างน้อย 3 ขนาดทั้ง Mobile device, Table และ Notebook  จริงๆ แล้วการจะออกแบบโดยเริ่มต้นที่หน้าจอขนาดใหญ่ หรือเล็กก่อนก็สามารถทำได้ทั้งนั้น แต่การเริ่มต้นจากหน้าจอขนาดเล็กจะทำให้เราได้โฟกัสใน Content ที่สำคัญๆ ก่อน เพื่อให้ User ได้รับข้อมูลหลักที่เว็บไซต์ต้องการนำเสนอ และค่อยๆ ออกแบบโดยเพิ่มรายละเอียดที่สำคัญรองลงมาในหน้าจอขนาดใหญ่ขึ้นตามลำดับ

    ใน Bootstrap เวอชั่น 3 นั้นได้เพิ่มคุณสมบัติการเป็น Responsive มาในตัวแล้ว การนำมาใช้งานจึงไม่ต้อง Include ไฟล์คุณสมบัตินี้เพิ่มเหมือนในเวอร์ชั่นก่อนหน้า

    การดาวน์โหลด Bootstrap

    สามารถดาวโหลดได้ที่ www.getbootstrap.com

    โครงสร้างไดเร็กทอรี่

    หลังจากดาวน์โหลดไฟล์มาแล้ว ให้ทำการแตกไฟล์ .zip จะพบว่ามีโครงสร้างไฟล์ดังนี้

    file_structure

    css
    เป็นโฟลเดอร์สำหรับเก็บไฟล์ CSS ที่ใช้กำหนด Layout และ Theme ของหน้าเว็บ สังเกตว่าในโฟลเดอร์นี้จะมีไฟล์ .min ซึ่งเป็นไฟล์ CSS ที่ผ่านการคอมไพล์แล้วทำให้มีขนาดเล็กลง

    js
    เป็นโฟลเดอร์สำหรับเก็บไฟล์ JavaScript เพิ่มลูกเล่นให้กับเว็บ

    fonts
    เป็นโฟลเดอร์สำหรับเก็บฟอนต์ต่างๆ ที่ใช้ในการแสดงผลข้อความบนหน้าเว็บ

    สิ่งที่ Bootstrap เตรียมไว้ให้

    Grid system
    ระบบ Grid จำนวน 12 คอลัมน์ สามารถเลือกใช้ได้ทั้งแบบ fixed และแบบ fluid

    Base CSS
    style sheets สำหรับ html elements พื้นฐาน เช่น typography, tables, forms และ images

    Components
    style sheets สำหรับสิ่งที่เราต้องใช้บ่อยๆ ไม่ว่าจะเป็น navigation, breadcrumbs รวมไปถึง pagination

    JavaScript
    jQuery plugins ต่างๆ ไม่ว่าจะเป็น modal, carousel หรือ tooltip

    เทมเพลตพื้นฐาน

    Bootstrap ใช้โครงสร้างเอกสารเป็น HTML5 ซึ่งมีเทมเพลตพื้นฐานดังรูป

    basic template

    ตัวอย่างการนำไปใช้งานที่เห็นได้ชัด และหลายๆ ท่านในชุมชน PSU SysAdmin เองคงจะคุ้นเคยกันดี เช่น

    – Joomla เวอร์ชั่น 3 ที่นำ Bootstrap ไปใช้ เพื่อให้เว็บไซต์มีคุณสมบัติของ Responsive Design ตอบสนองการแสดงผลบนอุปกรณ์ที่มีขนาดต่างๆ กันได้เป็นอย่างดี

    – WordPress ก็สามารถสร้าง Theme ด้วย Bootstrap ได้เหมือนกัน (http://blog.teamtreehouse.com/responsive-wordpress-bootstrap-theme-tutorial)

    – นอกจากนี้ท่านยังสามารถดูตัวอย่างเว็บไซต์อื่นๆ ที่ทางผู้พัฒนา Bootstrap ได้รวบรวมไว้ได้ที่ http://expo.getbootstrap.com/

     

     

     

  • การทำ Wireframe

    ในการพัฒนาเว็บไซต์ จะมีผู้ที่เกี่ยวข้องโดยตรงหลักๆ ได้แก่
    1. ทีมพัฒนาเว็บไซต์ หรือโปรแกรมเมอร์ อาจจะมีคนเดียว หรือทำงานกันเป็นทีมก็ได้ และ
    2. ผู้ใช้ หรือลูกค้า จะเป็นผู้กำหนดความต้องการของเว็บไซต์

    หลังจากที่ทีมพัฒนาเก็บรวบรวมความต้องการของลูกค้า และได้ทำการวิเคราะห์ความต้องการแล้ว ขั้นตอนถัดไป ก็จะเป็นการวางแผน ออกแบบ Layout คร่าวๆ ก่อน เพื่อให้ทีมพัฒนามีความเข้าใจที่ตรงกัน อีกทั้งยังสามารถนำเสนอต่อลูกค้า เพื่อให้ลูกค้าเห็นภาพรวมของเว็บไซต์ก่อนการลงมือออกแบบเว็บไซต์ และเขียนโค้ดจริง  เราเรียกกระบวนการออกแบบ Layout และนำเนื้อหาคร่าวๆ ในเว็บไซต์มาจัดเรียงบน Layout นี้ว่า “การทำ Wireframe”

    การทำ Wireframe นั้นไม่ได้มีรูปแบบตายตัว นักพัฒนาแต่ละคนอาจมีวิธีการที่แตกต่างกันไป แต่มีวัตถุประสงค์ในการทำที่เหมือนกัน คือ เพื่อให้เห็นภาพรวมของเว็บไซต์ ทำให้ทีมเข้าใจตรงกัน และพัฒนาไปในทางเดียวกัน

    ตัวอย่างเครื่องมือที่ใช้ทำ Wireframe ที่ทำได้ง่ายที่สุด คือการใช้ดินสอ วาด Layout ลงบนกระดาษ และจัดเรียงเนื้อหาคร่าวๆ ดังรูป

    wireframe

    หรือจะใช้โปรแกรมคอมพิวเตอร์ช่วยในการทำก็ได้แล้วแต่ความถนัดของแต่ละคน ซึ่งโปรแกรมคอมพิวเตอร์ที่ช่วยในการทำ Wireframe จะมีให้เลือกใช้มากมาย ทั้งในแบบใช้งานออนไลน์ และแบบที่ต้องติดตั้งลงเครื่อง มีทั้งที่ให้ใช้งานฟรี และเสียตังค์ซื้อก็มี ตัวอย่างที่น่าสนใจได้แก่

    1. Prototype – โปรแกรมทำ Wireframe ตัวนี้มีทั้งบน Windows / Mac OS โดยแบ่งเป็นเวอร์ชั่นฟรี กับเวอร์ชั่นเสียเงิน
    2. Pencil Project – โปรแกรมทำ Wireframe ใช้ฟรี ๆ มีทั้งบน Windows / Linux / Mac OS
    3. Cacoo – Web App สำหรับทำ Diagram, Wireframe ออนไลน์ โดย Account ฟรีจะสร้าง Wireframe ได้จำกัดหน้า
    4. JumpChart – Web App สำหรับทำ Wireframe Online ที่หน้าตาเรียบง่าย โดย Account ฟรีจะสร้าง Wireframe ได้จำกัดหน้า
    5. FrameBox – Web App สำหรับทำ Wireframe ฟีเจอร์น้อย แต่ใช้ฟรี ทำเสร็จส่งลิงค์ให้ลูกค้าได้ทันที
    6. iPlotz – Web App สำหรับสร้าง Wireframe ออนไลน์ที่ดูมีสีสันกว่าตัวอื่น ใช้ฟรี Account จะจำกัดหน้า

    วิธีการใช้งานโปรแกรมเหล่านี้ก็ไม่ยากมาก สามารถศึกษาได้ด้วยตนเอง และเลือกใช้งานโปรแกรมได้ตามความถนัดของแต่ละคน ตัวอย่างต่อไปนี้จะเป็นวีดีโอแนะนำการใช้งาน Pencil Project ซึ่งเท่าที่เคยได้ลองเล่นดูพบว่าเป็นโปรแกรมที่น่าสนใจ มีเครื่องมือให้ใช้ค่อนข้างครบถ้วน และที่สำคัญคือใช้งานได้ฟรีไม่มีค่าใช้จ่าย

     

  • เตรียมความพร้อมก่อนการพัฒนา Web Application

    ในปัจจุบันนี้ต้องยอมรับว่าระบบอินเตอร์เน็ตเข้ามามีบทบาทสำคัญต่อการดำเนินกิจกรรมต่างๆ มากมาย ทั้งในด้านสังคม เศรษฐกิจ การเมือง การศึกษา หรือแม้กระทั่งวงการทหาร ดังนั้นแนวโน้มของโปรแกรมคอมพิวเตอร์จึงเน้นไปทางด้านโปรแกรมที่สามารถทำงานผ่านระบบอินเตอร์เน็ตได้ ประกอบกับอุปกรณ์ในการเข้าถึงอินเตอร์เน็ตมีความหลากหลายมากยิ่งขึ้นจึงมีผลต่อการพิจารณาเทคนิค วิธีการต่างๆ ที่จะนำมาใช้ในการพัฒนาระบบของผู้พัฒนาว่าควรจะเลือกใช้เทคโนโลยีใดบ้าง เพื่อให้โปรแกรมที่พัฒนาขึ้นมีความทันสมัย รองรับการใช้งานบนอุปกรณ์ต่างๆ ได้เป็นอย่างดี

    เนื่องจากอุปกรณ์ต่างๆ ไม่ว่าจะเป็น Computer, Tablet หรือ Mobile จะมีโปรแกรมพื้นฐานที่เรียกว่า Web Browser สำหรับเข้าใช้งานเว็บไซต์ต่างๆ อยู่แล้ว ดังนั้นการพัฒนาโปรแกรมในรูปแบบ Web หรือที่เรียกว่า Web Application จึงเป็นทางเลือกที่ได้รับความนิยมเป็นอย่างมาก สามารถตอบสนองความต้องการของผู้ใช้งานได้เป็นอย่างดี

    ก่อนการพัฒนาโปรแกรมทุกครั้ง ผู้พัฒนาระบบจะต้องทำการรวบรวมความต้องการของโปรแกรม (เป็นขั้นตอนแรกของการพัฒนาโปรแกรมตามกระบวนการ SDLC) เพื่อนำมาวิเคราะห์ และออกแบบระบบในขั้นตอนต่อไป ผลจากการวิเคราะห์ความต้องการในบางครั้งพบว่าเราไม่จำเป็นต้องพัฒนาโปรแกรมขึ้นมาใหม่ เนื่องจากโปรแกรมสำเร็จรูปบางตัวสามารถตอบโจทย์ความต้องการเหล่านั้นได้แล้ว เช่น Joomla, Moodle, WordPress เป็นต้น แต่ถ้าหากไม่ตอบโจทย์ความต้องการ ก็จะเป็นหน้าที่ของผู้พัฒนาที่จะต้องพัฒนาระบบขึ้นมาเอง ซึ่งในการที่จะพัฒนาระบบได้นั้น ผู้พัฒนาจะต้องมีความรู้พื้นฐานที่เกี่ยวข้อง เพื่อที่จะได้นำมาประกอบการตัดสินใจเลือกเทคนิคเหล่านั้นได้อย่างเหมาะสม ในบทความนี้เราจะมาทำความเข้าใจพื้นฐานที่ควรรู้สำหรับนักพัฒนาเว็บไซต์มือใหม่ได้แก่ความหมายของ Front-end,  Back-end และ Front-end Framework

    Front-end สำหรับเว็บไซต์ คือส่วนที่แสดงผล หรือหน้าเว็บไซต์ที่เราคุ้นเคยกัน เปรียบได้กับหน้าบ้าน ซึ่งเป็นส่วนที่ User โดยทั่วไปสามารถเห็น และเข้ามาใช้งานได้ เช่น หน้าเว็บที่ท่านกำลังอ่านอยู่ ณ ขณะนี้ เป็นต้น ซึ่งหน้าเว็บเหล่านี้จะต้องมีการออกแบบให้สวยงาม เพื่อสร้างความน่าสนใจของเนื้อหาเว็บไซต์ให้มากยิ่งขึ้น รวมทั้งการออกแบบในส่วนของการจัดวางเมนู การจัดตำแหน่งของเนื้อหาเว็บ การกำหนดรูปแบบ และขนาด Text เป็นต้น

    Back-end ในที่นี้หมายถึงส่วนหน้าจอการจัดการข้อมูล ไม่ว่าจะเป็นการเพิ่ม แก้ไข ลบเนื้อหาเว็บไซต์ (Content) สำหรับผู้ดูแลเว็บไซต์ (Admin) ตัวอย่างเช่น เนื้อหาที่ท่านกำลังอ่าน ก็มาจากการเพิ่มข้อมูล หรือเขียน Blog ผ่านหน้าจอการจัดการ ข้อมูลนั่นเอง

    สังเกตได้ว่าในการพัฒนาเว็บไซต์ทั้งส่วน Front-end หรือ Back-end ไม่ว่าจะเป็นเว็บใดก็ตามจะมีการนำเสนอเนื้อหาโดยใช้ภาษา HTML จากนั้นจึงจัดรูปแบบให้สวยงามด้วย CSS และเพิ่มลูกเล่นให้กับเว็บไซต์ให้น่าสนใจด้วย JavaScript ซึ่งเดิมทีการสร้างเว็บไซต์แต่ละเว็บนั้นเราจะเริ่มจากเขียน HTML, CSS และ JavaScript เองตั้งแต่ต้นจนจบ หรืออาจจะใช้เครื่องมือช่วยเช่น Dreamweaver แต่ในปัจจุบันนี้เราไม่จำเป็นต้องเริ่มจากศูนย์อีกแล้ว เนื่องจากได้มีการเขียนโค้ด HTML, CSS และ JavaScript แบบสำเร็จรูปรวมกันไว้เป็นชุดให้นักพัฒนาเว็บไซต์ได้ดาวน์โหลดไปใช้งานต่อได้เลย ซึ่งชุดโค้ดเหล่านี้จะทำหน้าที่ในการจัดวาง Layout ตัวอักษร ปุ่ม เมนู ฯลฯ นักพัฒนาก็แค่คัดลอกโค้ดส่วนที่ต้องการไปใช้ได้เลย เราเรียกชุดของโค้ดดังกล่าวนี้ว่า Front-end Framework

    ตัวอย่างของ Front-end Framework ที่นิยมใช้งานกัน ได้แก่ Bootstrap, ZURB foundation เป็นต้น  โดยในบทความถัดไปจะเป็นการแนะนำการพัฒนาเว็บไซต์ด้วย Bootstrap

  • ตั้งค่า php ให้แสดงข้อความ error

    อาการปัญหา: นำโค้ดอัพโหลดขึ้นเครื่องเว็บเซิร์ฟเวอร์จริง ลองทดสอบการใช้งาน ปรากฎว่าเจอแต่หน้าว่างๆ ขาวๆ

    ตอบ: เซิร์ฟเวอร์ปิดการทำงานการแสดงผลข้อความ error ต่างๆ ของ php เพื่อความปลอดภัย ต้องทำการเปิดก่อนที่ php.ini มีขั้นตอนดังนี้

    (more…)

  • c# string concatenations

    การต่อ String ใน C# ทำได้  4 แบบดังนี้

    1. ใช้เครื่องหมาย plus (+) แบบยอดนิยมใช้งานกันบ่อยๆ.
      string txt = “aaa”+”bbb”+”ccc”;
    2. ใช้ string.Concat() สะดวกับการต่อ list หรือ array มาก.
      string [] s = { “ManU”, “Liverpool”, “Asenal” };
      Console.WriteLine(string.Concat(s));
    3. ใช้ string.Format() เหมาะสำหรับต่อ string และจัดการรูปแบบการแสดงผลด้วยไปในคราวเดียวกันเลย.
      string value1 = “Hello World!”;
      int value2 = 2557;
      DateTime value3 = DateTime.Now();
      string result = string.Format(“{0}: {1:0.0} – {2:dd-mm-yyyy}”, value1, value2, value3);
    4. ใช้ stringBuilder เหมาะสำหรับการต่อ sting ที่มีปริมาณมากๆจะทำงานได้เร็วประมาณ 1000 ขึ้นไป.
      StringBuilder returnNumber = new StringBuilder(1500);
      for(int i = 0; i<1500; i++)
      {
      returnNumber.Append(i.ToString());
      }

    ถ้ามีเวลาจะมาขยายเรื่องนี้ในหัวข้อการทดสอบ Performance จะมาลองดูว่าแบบไหนเร็วกว่ากันไปซักเท่าไร ตอนนี้เอาเท่านี้ไปก่อนแล้วกันครับ

  • วิธีตรวจสอบเว็บไซต์ที่โดน Hack #15

    เทคนิคนี้ ใช้ผ่าน Internet Information Services (IIS) Manager โดยการแก้ไข Request Filtering ในระดับ Web Server เลย โดยดำเนินการตามวิธีการต่อไปนี้

    1. เรียก Command ด้วย การกดปุ่ม Windows + R แล้ว พิมพ์ inetmgr แล้วกดปุ่ม Enter
    2. คลิกเว็บเซิร์ฟเวอร์ของเครื่องที่ต้องการใน Connection Tab (ตัวอย่างในภาพ คลิกที่ WUNCAWEBSEC)
    3. ต่อไป ภายใต้หัวข้อ IIS ให้ Double-Click ที่ Request Filtering
    4. คลิกที่ Rules tab
    5. เพิ่มกฏสำหรับ JCE Bot
      ซึ่ง ไม่ต้องการให้ PHP ทำงานภายใต้ URL ซึ่งมีข้อความว่า “images/stories”
      โดย ไปที่ Action ด้านขวามือ แล้ว คลิกที่ Add Filtering Rules …
      แล้วใส่ข้อมูลตามภาพ แล้วคลิกปุ่ม OK

    1. เพิ่มกฏสำหรับ Upload โฟลเดอร์
      ซึ่ง ไม่ต้องการให้ PHP ทำงานภายใต้ URL ซึ่งมีข้อความว่า “upload”
      โดย ไปที่ Action ด้านขวามือ แล้ว คลิกที่ Add Filtering Rules …
      แล้วใส่ข้อมูลตามภาพ แล้วคลิกปุ่ม OK
    2. ผลที่ได้ใน Rules tab

    ทดสอบผลการทำงาน

    สมมุติเดิมโดนวางไฟล์ Backdoor ไว้ที่

    http://localhost/corin/images/stories/backdoor.php

    แต่เมื่อตั้ง Rules ดังกล่าวแล้ว จะทำให้ Hacker ไม่สามารถเรียกใช้งาน PHP ที่วางไว้ใน images/stories ได้ โดยจะได้ Error เช่นนี้

    วิธีนี้มีข้อดีคือ สามารถป้องกันการใช้งาน PHP ใน images/stories (และใน upload โฟลเดอร์) แต่ยังสามารถเรียกไฟล์ภาพและไฟล์อื่นๆได้ตามปรกติ เช่น

    http://localhost/corin/images/stories/clownspin.gif

    ลองใช้งานดูครับ 😉

  • การสร้างระบบ Load Balance Web Server ด้วยวิธีการ URL Redirect

    เราสามารถสร้างระบบ Load Balance Web Server ด้วยวิธีการ URL Redirect
    โดยสามารถสร้างด้วยภาษาใดก็ได้ แต่จะขอยกตัวอย่างด้วยภาษา PHP ได้ง่าย ๆ ดังนี้

    ตัวอย่างไฟล์ server-status ที่ได้ทำการ monitor web server มาเรียบร้อยแล้ว

    webserver1.testlab UP
    webserver2.testlab DOWN
    

    – เราสามารถใช้คำสั่งดึงไฟล์เพื่อคัดเฉพาะ Web Server ที่สามารถใช้งานได้จริง ๆ ดังนี้

    exec("cat /tmp/server-status | grep UP",$redirect);

    – จากนั้นจะทำการ นำรายการ server ทั้งหมดซึ่งอยู่ในตัวแปร $redirect มาทำการสุ่ม ดังนี้

    $random = rand(0,(count($redirect)-1);

    – ก็จะทำเอาเลข server ที่ random ได้ไปเข้ากระบวนการ Redirect ดังนี้

    $server = explode(" ",$redirect[$random]);
    header('HTTP/1.1 301 Moved Permanently');
    header('Cache-Control: no-store, no-cache, must-revalidate');
    header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
    header('Location: https://'.$server[0].'/');
    unset($server);
    

    ในกรณีที่ต้องการสร้างหน้ารอให้ทำการตรวจสอบว่าในกรณีที่ไม่มีเครื่องให้บริการให้แสดงข้อความ ตัวอย่างดังนี้

    if(count($redirect)==0){
       echo "Server Unavailable or Maintenance Period";
    }

    ดังที่กล่าวมาทั้งหมดข้างต้นสามารถรวมเป็น script ไฟล์ PHP ได้ดังนี้

    <?php
    exec("cat /tmp/server-status | grep UP",$redirect);
    if(count($redirect)==0){
       echo "Server Unavailable or Maintenance Period";
    }else{
       $random = rand(0,(count($redirect)-1));
       $server = explode(" ",$redirect[$random]);
       header('HTTP/1.1 301 Moved Permanently');
       header('Cache-Control: no-store, no-cache, must-revalidate');
       header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
       header('Location: http://'.$server[0].'/');
       unset($server);
    }
    unset($redirect);
    ?>

    *สามารถอ่านวิธีสร้างไฟล์สำหรับ monitor web serverได้จาก บทความนี้ http://sysadmin.psu.ac.th/2014/06/19/monitor-web-server-wget-shell-script-daemon/