Category: การพัฒนา ASP.NET Web Application

  • มาทำความรู้จักและเรียนรู้การใช้งาน Progress bar ในเบื้องต้นกันเถอะ

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

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

    ไฟล์ Progress.css

      .progress-title {
        font-size: 18px;
        font-weight: 700;
        color: #000;
        margin: 0 0 10px;
      }
    
    .progress-outer {
        background: #fff;
        padding: 5px 60px 5px 5px;
        border: 5px solid #bebfbf;
        border-radius: 45px;
        margin-bottom: 20px;
        position: relative;
    }
    
    .progress {
        background: #bebfbf;
        border-radius: 20px;
        margin: 0;
    }
    
        .progress .progress-bar {
            border-radius: 20px;
            box-shadow: none;
            animation: animate-positive 2s;
        }
    
        .progress .progress-value {
            font-size: 20px;
            font-weight: 700;
            color: #6b7880;
            position: absolute;
            top: 3px;
            right: 10px;
        }
    
        .progress-bar.active{
        animation: reverse progress-bar-stripes 0.40s linear infinite, animate-positive 2s;
        }
       @-webkit-keyframes animate-positive{
        0% { width: 0%; }
        }
       @keyframes animate-positive {
        0% { width: 0%; }
        }
    
       .progress-bar-striped {
        background-image: linear-gradient(
    45deg
    ,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);
        background-size: 1rem 1rem;
      }
      .progress-bar {
        display: -ms-flexbox;
        display: flex;
        -ms-flex-direction: column;
        flex-direction: column;
        -ms-flex-pack: center;
        justify-content: center;
        overflow: hidden;
        color: #fff;
        text-align: center;
        white-space: nowrap;
         transition: width .6s ease;
       }
       .progress {
        display: -ms-flexbox;
        display: flex;
        height: 1rem;
        overflow: hidden;
        font-size: .75rem;
        background-color: #e9ecef;
        border-radius: .25rem;
        box-shadow: inset 0 0.1rem 0.1rem rgb(0 0 0 / 10%);
        }
     

    เพิ่มเติม : การอ้างอิงไฟล์สไตล์ชีทจากภายนอก โดยที่อยู่ของไฟล์ก็ขึ้นกับการระบุของแต่ละท่าน

    <link href="dist/css/Progress.css" rel="stylesheet">

    2. การกำหนดพื้นที่ในการแสดงผล Progress bar ในส่วนของแท็ก body ในไฟล์ html

    <div class="container">
        <div class="row">
            <div class="col-md-6">
    
             <!-- progress bar-->
                <h3 class="progress-title">Basic Progress</h3>  <!-- progress bar Title-->
                <div class="progress-outer">
                    <div class="progress">
                        <!-- กำหนดสไตล์ชีทเพื่อแสดงแถบสี และขนาดของ progress bar -->
                        <div class="progress-bar progress-bar-striped progress-bar-info" style="width:85%;"></div>
                       <div class="progress-value"><span>85</span>%</div> <!-- แสดงข้อความจำนวน % บน progress bar -->
                    </div>
                </div>
            <!-- End progress bar-->
          
            </div>
        </div>
    </div>

    คำอธิบาย : จากตัวอย่าง จะเห็นว่าเราสามารถปรับแต่งและใส่ข้อมูลให้กับ Progress bar 3 ส่วนคือ

    • ข้อความบนแถบ Progress bar ได้ในส่วนของ Progress-title คือ <h3 class=”progress-title”>Basic Progress</h3>
    • กำหนดความกว้างของ Progress bar ได้ผ่านทาง style-inline คือ style=”width:85%;
    • แสดงข้อความจำนวนของข้อมูลบนแถบ Progress bar คือ <div class=”progress-value“><span>85</span>%</div> นั่นเอง

    3. การเรียกใช้งาน jQuery เพื่อการแสดงผล Progress bar ของเราให้มีการเพิ่มขึ้นของจำนวนเลขที่แสดงตั้งแต่ 0 จนถึงจำนวนเลขนั้น เช่น หากเลขที่ต้องการแสดงคือ 60% ตัวเลขแสดงจำนวนดังกล่าวจะค่อยๆเปลี่ยนแปลงเพิ่มขึ้นโดยเริ่มจาก 0 จนถึง 60 นั่นเอง

    <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
     <script>
    $(document).ready(function(){
        $('.progress-value > span').each(function(){
            $(this).prop('Counter',0).animate({
                Counter: $(this).text()
            },{
                duration: 1500,
                easing: 'swing',
                step: function (now){
                    $(this).text(Math.ceil(now));
                }
            });
        });
    });
     </script>

    ผลลัพธ์

    เพิ่มเติม
              จากตัวอย่างข้างต้น จะเป็นการแสดงผล Progress bar แบบพื้นฐานอย่างง่าย เพียงเท่านี้ท่านก็จะสร้าง Progress bar ได้ด้วยตนเองแล้ว แต่หากท่านใดที่อยากเพิ่มสีสันและความสวยงามให้กับ Progress bar ของท่าน ก็สามารถทำได้ดังตัวอย่างนี้ค่ะ
    1. ปรับแก้เพิ่มเติมในส่วนของการกำหนดพื้นที่ในการแสดงผล

    <div class="container">
        <div class="row">
            <div class="col-md-6">
    
             <!-- progress bar-->
                <h3 class="progress-title">Progress1</h3>  <!-- progress bar Title-->
                <div class="progress-outer">
                    <div class="progress">
                        <!-- กำหนดสไตล์ชีทเพื่อแสดงแถบสี และขนาดของ progress bar -->
                        <div class="progress-bar progress-bar-striped progress-bar-danger" style="width:25%;"></div>
                       <div class="progress-value"><span>25</span>%</div> <!-- แสดงข้อความจำนวน % บน progress bar -->
                    </div>
                </div>
    
            <!-- End progress bar-->
                <h3 class="progress-title">Progress2</h3>
                <div class="progress-outer">
                    <div class="progress">
                        <div class="progress-bar progress-bar-striped progress-bar-warning" style="width:50%;"></div>
                        <div class="progress-value"><span>50</span>%</div>
                    </div>
                </div>
                <h3 class="progress-title">Progress3</h3>
                <div class="progress-outer">
                    <div class="progress">
                        <div class="progress-bar progress-bar-striped progress-bar-info" style="width:75%;"></div>
                        <div class="progress-value"><span>75</span>%</div>
                    </div>
                </div>
                <h3 class="progress-title">Progress4</h3>
                 <div class="progress-outer">
                    <div class="progress">
                        <div class="progress-bar progress-bar-striped progress-bar-success" style="width:90%;"></div>
                        <div class="progress-value"><span>90</span>%</div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    2. เพิ่มสไตล์ชีทที่ใช้สำหรับเพิ่มสีสันให้กับ Progress bar ของเรา

    .progress-bar-danger {
        background-color: #d9534f;
    }
    .progress-bar-warning {
        background-color: #f0ad4e;
    }
    .progress-bar-success {
        background-color: #5cb85c;
    }
    .progress-bar-info {
        background-color: #5bc0de;
    }

    ผลลัพธ์

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

    การกำหนดพื้นที่ในการแสดงผล Progress bar ในส่วนของแท็ก body ในไฟล์ html

    <div class="container">
        <div class="row">
            <div class="col-md-6">
    
                  <h3 class="progress-title">Multiple-color Progress</h3>
                    <div class="progress-outer">
                <!-- การกำหนดแถบสีใน 1 แถบ progress bar-->
                        <div class="progress">
    
                            <!-- แถบสีแดงใน progress bar ขนาด 25%-->
                            <div class="progress-bar progress-bar-danger progress-bar-striped" style="width: 25%">25%
                            </div>
                              <!-- แถบสีส้มใน progress bar ขนาด 25%-->
                            <div class="progress-bar progress-bar-warning progress-bar-striped" style="width: 25%">50%
                            </div>
                             <!-- แถบสีฟ้าใน progress bar ขนาด 25%-->
                            <div class="progress-bar progress-bar-info progress-bar-striped " style="width: 25%">75%
                            </div>
                             <!-- แถบสีเขียวใน progress bar ขนาด 25%-->
                            <div class="progress-bar progress-bar-success progress-bar-striped active" style="width: 10%">10%
                            </div>
                            <div class="progress-value">
                                <span>85</span>%</div>
                        </div>
                    </div>
          
            </div>
        </div>
    </div>

              จากโค้ดตัวอย่างข้างต้น จะสังเกตเห็นว่าการกำหนดค่าต่างๆจะมีลักษณะกับหลักการที่กล่าวไว้แล้วข้างต้น แต่จะแตกต่างกันตรงที่การแสดงผลหลายแถบสีในแถบเดียวกันจะมีการกำหนด progress bar ภายใต้แท็ก <div class=”progress”> เดียวกัน และหากต้องการกำหนดให้มีกี่แถบสีก็สามารถเพิ่มสี และกำหนดขนาดของแต่ละแถบสีได้ตามต้องการ

    ผลลัพธ์

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

    แหล่งข้อมูลอ้างอิง :

    https://bestjquery.com/tutorial/progress-bar/demo78/

    https://www.jquery-az.com/boots/demo.php?ex=51.0_5

  • การทำ Partial Rendering สำหรับ User Controls

    สำหรับท่านใดที่ยังใช้งาน ASP.NET Web From ในการพัฒนาเว็บไซต์อยู่ คงคุ้นเคยกับการใช้งาน User Controls เป็นอย่างดีเนื่องจากเป็นการสร้าง UI เพื่อใช้งานซ้ำในหลายๆ Page ซึ่งเป็นที่นิยม สำหรับบทความนี้จะแนะนำวิธีการ แยกเรนเดอร์ User Controls ที่มีปัญหาโหลดช้าอันเนื่องมาจากสาเหตุใดก็ตาม และเป็นข้อมูลเพิ่มเติมที่ผู้ใช้ไม่จำเป็นต้องเห็นเป็นอย่างแรก โดยมีขั้นตอนดังนี้

    1.เพิ่ม HTML Container element เช่น Div, Panel ในหน้าจอ ที่ต้องการใช้งาน เช่น

    2.เพิ่ม Ajax Controls toolkit : Dynamic Populate ใช้เพื่อ Render HTML หลังจากที่ Page Load เสร็จเรียบร้อย

    • TargetControlsID คือ ID ของ HTML Container element ที่เราต้องการแสดงผล HTML ของ User Controls ที่เราสร้างมาจาก Web Service
    • ServicePath คือ Path ของ Web Service ที่เรียกใช้งาน
    • ServiceMethod คือ Web Method ที่ใช้ Render User Controls
    • UpdatingCssClass คือ CSS Class ที่ต้องการให้แสดงระหว่างรอ Load HTML

    3.Java Script เรียกใช้งาน  Ajax Controls toolkit : Dynamic Populate และเพิ่มเติมฟังก์ชันที่ต้องการขณะแสดงผล User Controls

    4.สร้าง Web Method สำหรับสร้าง HTML ของ User Controls

    • รูปแบบของ Web Service Method ซึ่งจะต้องมี Return Type เป็น string และรับ Parameter ชื่อ contextKey ซึ่งมี Type เป็น string เช่นกัน
    • เรียก Method ชื่อ RenderUserControl โดยระบุ Path ของ User Control ที่ต้องการ และ List ของ Property ทั้งหมดของ User Control

    5.Method ที่ใช้ในการสร้างเนื้อหา HTML จาก User Controls

    เพียงเท่านี้ เราก็สามารถเรียกใช้งาน User Control นี้ในหน้าจอต่างๆ ได้โดยไม่ต้องกังวลเรื่องเพิ่มเวลาโหลดให้กับหน้าจอแสดงผลนั้นๆแล้วครับ อย่างไรก็ดีบทความนี้ผมได้เขียนไว้นานมากแล้ว แต่ยังไม่ได้นำมาเผยแพร่ ในปัจจุบันอาจมีวิธีการอื่นๆ และ ASP.NET ที่เป็น Web Form อาจจะได้รับความนิยมน้อยลงไปแล้ว แต่สำหรับท่านที่ต้องดูแล และปรับปรุงระบบเก่าๆ ไม่สามารถเขียนขึ้นมาใหม่ทั้งหมดได้ ก็ยังสามารถนำเทคนิคนี้ไปปรับใช้กับระบบของตนเองได้ครับ

  • การติดตั้งเว็บไซต์ ที่พัฒนาด้วย ASP.NET บน IIS

    สำหรับนักพัฒนาเว็บแอปพลิเคชัน ที่จะต้องทำหน้าที่ครบวงจร (Full Stack Programer) สิ่งที่ต้องทำหลังจากพัฒนาเว็บขึ้นมาเสร็จแล้ว คือการติดตั้งบนเซิร์ฟเวอร์ (Deploy) ในบทความนี้จะเล่าขั้นตอนหลักๆ ในการติดตั้งเว็บไซต์ ที่พัฒนาด้วย ASP.NET (ไม่ว่าจะพัฒนาด้วย .Net Framework เวอร์ชันไหนก็ขั้นตอนเดียวกัน เปลี่ยนแปลงแค่ .Net Runtime ที่ใช้งาน) บนวินโดวส์เซิร์ฟเวอร์ โดยใช้ IIS (Internet Information Services) ซึ่งหน้าตาอาจเปลี่ยนแปลงไปตามเวอร์ชันของ IIS แต่ขั้นตอนการตั้งค่ายังคงคล้ายคลึงกัน

    Publish เว็บไซต์ (กรณีใช้ Visual Studio)

    1.คลิกขวาที่ชื่อโปรเจ็ค เลือก Publish

    2.จะได้หน้าจอเลือกประเภทในบทความนี้เลือกเป็น Folder เพื่อใช้วิธีการ Deploy แบบนำไฟล์ไปวางที่ Server เอง ดังรูป

    3. เลือกที่ตั้งไฟล์ กด Finish

    4. ตั้งค่าการ Publish จากในรูปคือให้ลบไฟล์ที่มีอยู่ก่อน และใช้รูปแบบ Release ในการ Compile

    5. ตัวอย่างไฟล์ที่ทำการ Publish เสร็จแล้ว

    6. ทำการ Copy ไฟล์ทั้งหมดไปวางใน wwwroot บน Server

    ติดตั้ง Component ต่างๆ

    1.ในบทความนี้ใช้ Windows Server 2016 Datacenter เป็นตัวอย่าง ซึ่งการติดตั้ง Component ต่างๆ สามารถทำได้ผ่าน Server Manager > Manage > Add Roles and Features ได้เกือบทั้งหมด ยกเว้น Runtime อื่นๆที่เว็บไซต์มีการนำมาใช้งานเพิ่มเติม

    2. ติดตั้ง IIS , ASP.NET และ Component ที่เกี่ยวข้อง โดยไปที่ Server Role > Web Server (IIS) และทำการเลือก Component ต่างๆดังรูป จากนั้นกด Next

    3. ติดตั้ง .Net Framework เวอร์ชันที่เว็บไซต์ใช้งาน ในตัวอย่างใช้ .Net Framework 4.6 โดยสามารถเลือกจาก เมนู Features ดังรูป

    4. เท่านี้ก็จะมี Component ที่จำเป็นในการติดตั้งเว็บไซต์ที่พัฒนาด้วย ASP.NET แล้ว

    สร้าง และตั้งค่า Application Pool

    1.เปิดโปรแกรม IIS โดยไปที่ Start > Windows Administrative Tools > Internet information Services (IIS) จะได้หน้าจอดังรูป

    2. เลือกเมนู Application Pool จากนั้นคลิก Add Application Pool จะได้หน้าจอการตั้งค่าดังรูป โดยที่ .Net CLR Version จะแยกเป็น 2.0.xxx และ 4.0.xxx โดยหากต้องการใช้งาน .Net Runtime 3.5 – 4.x สามารถเลือกเป็น 4.0.x ได้ทั้งหมด

    3. เมื่อสร้างสำเร็จ จะมีรายการ Application Pool ที่เราสร้างดังรูป

    สร้าง และตั้งค่าเว็บไซต์ ทดสอบเรียกใช้งาน

    1.ในการสร้างไซต์นั้น หากบน Server นั้นยังไม่มีเว็บไซต์ใดๆ สามารถใช้ Default Web Site ได้เลย แต่ถ้ามีเว็บไซต์อื่นๆอยู่ก่อนแล้ว จะต้องพิจารณาว่าจะให้บริการในแบบใด เป็น Application ที่อยู่ภายใต้เว็บไซต์เดิม หรือแยกออกมาเป็นอีก URL ในส่วนนี้ บทความจะไม่ลงรายละเอียด โดยจะแสดงวิธีการเพิ่ม ไซต์ใหม่ภายใต้ URL เดิมที่มีอยู่แล้วโดยเลือกเมนู Add Website จะได้หน้าจอการตั้งค่าดังรูป

    2. จากนั้นทำการตั้งค่า Default Document โดยคลิกเลือกที่ชื่อเว็บไซต์ เลือกไฟล์ที่ต้องการกำหนดเป็นหน้าแรกของเว็บไซต์

    3. ตั้งค่าต่างๆของเว็บไซต์ ซึ่งขึ้นอยู่กับแต่ละเว็บไซต์ว่ามีการใช้งาน Feature ใดบ้าง ดังรูป (อีกช่องทางนึงคือการแก้ไขไฟล์ web.config โดยตรง)

    4. ทำการทดสอบเรียกใช้งาน โดยคลิกที่เมนู Browse เพื่อเรียกดูแบบ Localhost หรือหากมี URL อยู่แล้วสามารถเรียกดูผ่าน URL/ApplicationName ดังรูป

    ในขั้นตอนติดตั้งชิ้นงานจริง แน่นอนว่าอาจมีขั้นตอนเพิ่มเติมตามแต่ละเว็บไซต์ และอาจพบปัญหาต่างๆ แตกต่างกันไปตามเวอร์ชันของวินโดวส์, IIS, .Net Runtime แต่อย่างไรก็ดีหวังว่าบทความนี้จะเป็นไกด์ไลน์ ให้เห็นภาพขั้นตอนคร่าวๆในการติดตั้งเว็บไซต์หนึ่งๆ สำหรับผู้เริ่มต้นครับ

  • ข้อมูลใน DropdownList แรกจนถึง DropdownList สุดท้ายกับค่าที่เหลืออยู่ของเขา ด้วย LINQ

    ในช่วงที่ผ่านมา ได้มีการพัฒนาระบบโดยมีการนำ LinQ มาใช้นิด ๆ หน่อย ๆ (มือใหม่หัดใช้ >< ) ซึ่งมีอยู่ฟังก์ชันนึงที่เกี่ยวกับ การ Bind ค่า DropdownList กรณีที่มี DropdownList หลาย ๆ ตัวและไม่อยากให้ค่าที่เคยเลือกจาก DropdownList ก่อนหน้าไปแสดงใน DropdownList ถัดไปอีก น่าสนใจทดลองใช้แล้วทำงานได้ดี ผู้เขียนจึงนำมาเขียนเพื่อไว้เตือนความจำ จะได้กลับมาอ่าน แนวคิดและวิธีการดังนี้ค่ะ

    ในขั้นตอนแรก สร้าง Data ที่ชื่อว่า MyList เก็บข้อมูล id และชื่อ เพื่อเตรียมเป็น DataSource สำหรับ Bind ให้กับ DropdownList1 ดังนี้

    class MyList
    {
        private string id = string.empty;
        private string name = string.empty;
    
        public MyList(string _id, string _name)
        {
            id = _id;
            name = _name;
        }
    
        public string ID
        {
            get{return id;}
            set {id = value;}
        }
    
        public string Name
        {
            get{return name;}
            set {name = value;}
        }
    }

    ต่อมากำหนดค่าให้กับ MyList เพื่อผูกให้กับ DropdownList1

    List<MyList> mylist = new List<MyList>{
                        new MyList(1,'name1'),
                        new MyList(2,'name2'),
                        new MyList(3,'name3'),
                        new MyList(5,'name5'),
                        new MyList(10,'name10')
                        };

    ผลลัพธ์ของ DropdownList1 ได้ดังนี้

    ID          Name
    1 name1
    2 name2
    3 name3
    5 name5
    10 name10

    ต่อมา กำหนดว่า DropdownList1 เลือกค่าเป็น ID = ‘2’

    string mySelectedValue = '2';

    จากนั้น ที่ Event SelectedIndexChange ของ DropdownList1 ให้ใส่ Code ดังนี้

    var myDataSource = from d in MyList
    where !mySelectedValue.Contains(d.ID)
    select d;

    จากนั้นผูก myDataSource ให้กับ DropdownList2 ค่าล่าสุดใน DropdownList2 จะแสดงดังด้านล่าง โดยที่ ID = ‘2’ จะหายไป เนื่องจากถูกเลือกไปแล้ว ดังนี้

    ID          Name
    1           name1
    3           name3
    5           name5
    10          name10

    กรณีที่มี DropdownList3 ก็ให้ทำเหมือนขั้นตอนก่อนหน้า ตัวอย่างกำหนดค่าการเลือกของ DropdownList1 = ‘2’ และ DropdownList2 = ‘5’ ดังนี้

    string mySelectedValue = '2,5';

    จากนั้น ที่ Event SelectedIndexChange ของ DropdownList2 ให้ใส่ Code แบบเดิม

    var myDataSource = from d in MyList
    where !mySelectedValue.Contains(d.ID)
    select d;

    จากนั้นผูก myDataSource ให้กับ DropdownList3 ค่าล่าสุดใน DropdownList3 จะแสดงดังด้านล่าง โดยที่ ID = ‘2’ และ ‘5’ จะหายไป เนื่องจากถูกเลือกไปแล้ว ดังนี้

    ID           Name
    1            name1
    3            name3
    10           name10

    จะเห็นได้ว่าเราใช้ Query เดียวกันในหลาย ๆ DropdownList ดังนั้นสามารถทำ Query นี้ให้เป็นฟังก์ชันเพื่อเรียกใช้งานได้

    หวังว่าจะเป็นประโยชน์ไม่มากก็น้อยสำหรับผู้อ่านนะคะ \(@^0^@)/

  • อยากดึงข้อมูลมาแสดงใน TreeView จะทำอย่างไรดี?

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

    ขั้นตอนในการดึงข้อมูลจากฐานข้อมูลมาแสดงใน TreeView

    1. สร้าง TreeView ที่ต้องการใช้ในการแสดงผลข้อมูล
      ตัวอย่าง code ในฝั่ง Client
      <body>
      <form id="form1" runat="server">
      <asp:TreeView ID="TvOrganization" runat="server" >
      </asp:TreeView>
      </form>
      </body>
    2. ติดต่อฐานข้อมูลเพื่อใช้ในการแสดงผล ซึ่งในตัวอย่างนี้จะขอสมมุติข้อมูลจาก datatable ที่สร้างขึ้นแทน
      ตัวอย่าง code ในฝั่ง Server (C#)
      • ฟังก์ชั่นตอน Page_Load
      protected void Page_Load(object sender, EventArgs e)
          {
              if (!this.IsPostBack)
              {   ///////ดึงข้อมูลวิทยาเขต โดยในการใช้งานจริงจะเป็นการติดต่อกับฐานข้อมูลเพื่อดึงค่าวิทยาเขตมาแสดง
                  DataTable dt = this.GetCampusData();
              
      ///////เรียกใช้งานฟังก์ชั่น PopulateTreeView() เพื่อนำค่าข้อมูลวิทยาเขตมาแสดงผลใน TreeView 
      โดยในกรณีนี้จะเริ่มสร้างจาก root node โดยส่งค่าพารามิเตอร์ของ parentId เป็น 0
                  this.PopulateTreeView(dt, 0, null);
              }
          }
      • ฟังก์ชั่นดึงข้อมูลวิทยาเขตและคณะ/หน่วยงาน
      private DataTable GetCampusData() {
       ///////เตรียมข้อมูลวิทยาเขต เนื่องจากในกรณีนี้เป็นการสมมุติโครงสร้างและข้อมูลวิทยาเขตโดยสร้างเป็น DataTable 
      เสมือนเป็นตารางวิทยาเขตในฐานข้อมูล
      DataTable dtCampus = new DataTable();
      dtCampus.Columns.AddRange(new DataColumn[2] {
      new DataColumn("CampID", typeof(int)), 
      new DataColumn("CampNameThai",typeof(string)) }); 
      dtCampus.Rows.Add("01", "วิทยาเขตหาดใหญ่"); 
      dtCampus.Rows.Add("02", "วิทยาเขตปัตตานี");
      dtCampus.Rows.Add("03", "วิทยาเขตภูเก็ต"); 
      dtCampus.Rows.Add("04", "วิทยาเขตสุราษฎร์ธานี");
      dtCampus.Rows.Add("05", "วิทยาเขตตรัง"); return dtCampus; } private DataTable GetFacultyData() { ///////เตรียมข้อมูลคณะ/หน่วยงาน ในกรณีนี้เป็นการสมมุติโครงสร้างข้อมูลคณะ/หน่วยงานและสร้างเป็น DataTable โดยมีการระบุรหัสของวิทยาเขตไว้ด้วย ซึ่งในการทำงานจริงจะเป็นการดึงข้อมูลจากตารางที่เก็บข้อมูลคณะ/หน่วยงานแทน DataTable dtFaculty = new DataTable(); dtFaculty.Columns.AddRange(new DataColumn[3] { new DataColumn("FacID", typeof(int)), new DataColumn("FacNameThai",typeof(string)) , new DataColumn("CampID",typeof(string)) }); dtFaculty.Rows.Add("01", "สำนักงานอธิการบดี","01"); dtFaculty.Rows.Add("02", "ศูนย์คอมพิวเตอร์", "01"); dtFaculty.Rows.Add("03", "วิศวกรรมศาสตร์", "01"); dtFaculty.Rows.Add("54", "คณะรัฐศาสตร์", "02"); dtFaculty.Rows.Add("07", "ศึกษาศาสตร์", "02"); dtFaculty.Rows.Add("36", "วิทยาการสื่อสาร", "02"); dtFaculty.Rows.Add("81", "ศูนย์การเรียนรู้", "03"); dtFaculty.Rows.Add("56", "คณะศิลปศาสตร์และวิทยาศาสตร์", "04"); dtFaculty.Rows.Add("44", "คณะเทคโนโลยีและการจัดการ", "04"); dtFaculty.Rows.Add("46", "คณะพาณิชยศาสตร์และการจัดการ", "05"); dtFaculty.Rows.Add("66", "คณะสถาปัตยกรรมศาสตร์", "05"); return dtFaculty; }
      • ฟังก์ชั่นที่ใช้ในการวนแสดงข้อมูลที่ได้จากวิทยาเขตและคณะ/หน่วยงานมาแสดงใน TreeView
      private void PopulateTreeView(DataTable dtParent, int parentId, TreeNode treeNode)
      {
      ///////ดึงค่าข้อมูลคณะ/หน่วยงาน
      DataTable dtChild = this.GetFacultyData();
      DataRow[] drChild;
      
      ///////วนค่าข้อมูลวิทยาเขตจาก dtParent ที่เป็นพารามิเตอร์ที่ส่งมา
      foreach (DataRow row in dtParent.Rows)
      {
      
      if (parentId == 0) ///////กรณีที่เป็น root node ค่าของ parentId จะเท่ากับ 0 ซึ่งในที่นี้หมายถึง node วิทยาเขต นั่นเอง
      {
         TreeNode child = new TreeNode
        {  ///////กำหนดคุณสมบัติให้กับ root node ในส่วนของ Text,Value,ToolTip,SelectAction ตอน runtime 
      ขึ้นอยู่กับเงื่อนไขและจุดประสงค์ที่เราต้องการให้แสดงผล โดยในที่นี้จะนำค่าข้อมูลจากวิทยาเขตมาวนแสดง
      
      ///////สามารถกำหนด Style ตอนระบุ Text ได้ด้วย โดยในกรณีนี้ใส่ style ในแท็ก <span></span> นั่นเอง
          Text = "<span style='color:blue;font-weight:bold'>" + row["CampNameThai"].ToString() + "</span>" ,  
      
      ///////กำหนดค่าของ node เป็นรหัสวิทยาเขต
          Value = row["CampID"].ToString(),
      
      //////ระบุให้ ToolTip เป็นชื่อวิทยาเขต[รหัสวิทยาเขต]
          ToolTip = row["CampNameThai"].ToString() + "[" + row["CampID"].ToString() +"]", 
      
      ///////ระบุคุณสมบัติไม่ให้เลือกได้
          SelectAction = TreeNodeSelectAction.None, 
         };
      ///////เมื่อระบุคุณสมบัติและกำหนดค่าเรียบร้อยแล้วจะเพิ่ม node ดังกล่าวลงใน TreeView ที่ชื่อว่า TvOrganization
        TvOrganization.Nodes.Add(child); 
      
      ///////ดึงข้อมูลคณะ/หน่วยงานตามวิทยาเขตที่กำลังวนค่าซึ่งก็คือ row["CampID"].ToString()
        drChild = dtChild.Select("CampID=" + row["CampID"].ToString());
      
      ///////เรียกใช้ฟังก์ชั่น PopulateTreeView() โดยส่งค่าข้อมูลคณะ/หน่วยงานของวิทยาเขตที่กำลังวน(ตัวแปร drChild.CopyToDataTable())
      เพื่อวนสร้าง node ย่อยเพิ่มลงไปใน node วิทยาเขตที่กำลังจัดการ(ตัวแปร child)
      PopulateTreeView(drChild.CopyToDataTable(), int.Parse(child.Value), child); }
      else ///////กรณีที่เป็นการจัดการ node ย่อย ซึ่งในที่นี้หมายถึง node คณะ/หน่วยงาน { TreeNode child = new TreeNode { ///////กำหนดคุณสมบัติให้กับ node ย่อย
      ในส่วนของ Text,Value,ToolTip,SelectAction,ImageUrl,NavigateUrl,Target ตอน runtime ขึ้นอยู่กับเงื่อนไขและจุดประสงค์ที่เราต้องการให้แสดงผล โดยในที่นี้จะนำค่าข้อมูลจากคณะ/หน่วยงานมาวนแสดง
      ///////แสดงค่าข้อมูลคณะ/หน่วยงานที่กำลังวน Text = row["FacNameThai"].ToString() , ///////แสดงค่าข้อมูลรหัสคณะ/หน่วยงานที่กำลังวน Value = row["FacID"].ToString(), //////ระบุให้ ToolTip เป็นชื่อคณะ/หน่วยงาน[รหัสคณะ/หน่วยงาน] ToolTip = row["FacNameThai"].ToString() + "[" + row["FacID"].ToString() + "]", ///////ระบุคุณสมบัติไม่ให้สามารถคลิกเลือก node ได้ SelectAction = TreeNodeSelectAction.Select, ///////ระบุ url ของเพจที่ต้องการให้ลิงค์ไปโดยส่งค่าพารามิเตอร์ของรหัสคณะ/หน่วยงานไปด้วยกรณีที่ต้องการนำค่าข้อมูลไปใช้ต่อในเพจดังกล่าว NavigateUrl = "BasicTreeviewAll.aspx?FacId=" + row["FacID"].ToString(), ///////กำหนดให้เปิดเพจใหม่ Target="_blank", ///////กำหนดให้แสดงรูปภาพดาวหน้าข้อความใน node ดังกล่าว ImageUrl = "~/images/star.png", }; ///////เมื่อระบุคุณสมบัติและกำหนดค่าเรียบร้อยแล้วจะเพิ่ม node ดังกล่าวลงใน ตัวแปร treeNode(ซึ่งก็คือ node แม่ที่ถูกส่งมานั่นเอง) ซึ่งเป็นพารามิเตอร์ที่ส่งมาตอนเรียกใช้ฟังก์ชั่น PopulateTreeView() แต่ถ้าเป็นกรณี เรียกใช้ฟังก์ชั่นเพื่อสร้าง root node ค่า treeNode ที่ส่งมานี้จะเป็น null treeNode.ChildNodes.Add(child); } } }

      หมายเหตุ :
      1) การกำหนดคุณสมบัติให้กับ node ตอน RunTime เราสามารถเลือกระบุคุณสมบัติได้เช่นเดียวกับตอนกำหนดฝั่ง Client ที่เคยกล่าวไว้ในบทความก่อน โดย properties ที่สามารถระบุได้ขึ้นอยู่กับความต้องการของผู้ใช้ มีดังนี้

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

      ตัวอย่างแสดงผลลัพธ์ของการดึงข้อมูลมาแสดงใน TreeView จากโค้ดข้างต้น


              นอกจากนี้ ท่านยังสามารถเพิ่มความสามารถให้กับ TreeView ของท่านได้อีกหน่อยในกรณีที่ TreeView ที่ต้องการจัดการมี check box และต้องการให้สามารถเลือก node แม่และสามารถเลือก node ลูกทั้งหมดด้วยได้ (ลักษณะคล้ายกับแบบ Select All นั่นเอง) โดยใช้  jQuery เข้ามาช่วย โดยเพิ่ม code ที่เป็น jQuery  ดังนี้ ค่ะ

    1. อ้างอิงไฟล์ที่ใช้ในการทำงานร่วมกับ jQuery
      <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    2. ส่วนของ jQuery ที่ใช้ในการเลือกแบบ Select All ให้กับ node แม่และลูก
      <script type="text/javascript">
          $(function () {
              $("[id*=TvOrganization] 
      ////ทุกครั้งที่คอนโทรลที่มีชนิดเป็น checkbox ถูกคลิก
      input[type=checkbox]").bind("click", function () {
      ////จะหา tag table ที่ใกล้ที่สุด เพื่อแยกระหว่าง node แม่(วิทยาเขต)และลูก(คณะ/หน่วยงาน)
                  var table = $(this).closest("table");
                  if (table.next().length > 0 && table.next()[0].tagName == "DIV") {
                    ////เป็นการตรวจสอบว่าเป็น node ที่เป็นแม่หรือไม่
      โดยตรวจสอบว่าต้องเจอแท็ก table ถัดไป และแท็ก table ดังกล่าวต้องมีแท็ก DIV อยู่ด้วย
      var childDiv = table.next();

      ////นำค่าการเช็คของ check box ดังกล่าว มาใส่ไว้ในตัวแปร isChecked var isChecked = $(this).is(":checked");

      ////นำค่าจากตัวแปร isChecked ไปเซ็ทการเช็คหรือไม่เช็คใน check box ใน node ลูกทั้งหมด $("input[type=checkbox]", childDiv).each(function () { if (isChecked) { $(this).attr("checked", "checked"); } else { $(this).removeAttr("checked"); } }); } else { ////กรณีที่เป็น node ย่อยหรือ node ลูก var parentDIV = $(this).closest("DIV");

       ////ถ้าค่าของจำนวน node ย่อย เท่ากับจำนวนของการเช็คใน node ย่อยจะไปเช็ค check box ตัวแม่ด้วย
      แต่ถ้าไม่เท่ากันจะไปติ๊กเลือกออกจาก check box ตัวแม่ให้อัตโนมัติ
      if ($("input[type=checkbox]", parentDIV).length ==
      $("input[type=checkbox]:checked", parentDIV).length)
      { $("input[type=checkbox]", parentDIV.prev()).attr("checked", "checked"); } else { $("input[type=checkbox]", parentDIV.prev()).removeAttr("checked"); } } }); }) </script>

      คำอธิบายเพิ่มเติม :
             จากโค้ดของ jQuery เบื้องต้น ที่มีการแยกระหว่างส่วนของ node แม่และลูก เนื่องจากเมื่อดูจากโครงสร้าง Tag HTML ของ TreeView ที่ถูกสร้างขึ้นเมื่อทำการรันโปรแกรมเพื่อแสดงผล จะสังเกตว่าจะมีการสร้างเป็น Tag HTML ในลักษณะดังนี้

      ////ส่วนของการแสดงผล node แม่(วิทยาเขต) โดยในที่นี้คือ วิทยาเขตตรัง
      <table cellpadding="0" cellspacing="0" style="border-width:0;">
      <tbody>
      <tr>
      <td><a id="TvOrganizationn13"
      href="javascript:TreeView_ToggleNode(TvOrganization_Data,13,document.getElementById('TvOrganizationn13'),' '
      ,document.getElementById('TvOrganizationn13Nodes'))">
      <img src="xxxx" alt="Collapse <span style='color:blue;font-weight:bold'>วิทยาเขตตรัง</span>"
      style="border-width:0;">
      </a></td>
      <td style="white-space:nowrap;"><input type="checkbox" name="TvOrganizationn13CheckBox"
      id="TvOrganizationn13CheckBox"
      title="วิทยาเขตตรัง[5]"><span class="TvOrganization_0" title="วิทยาเขตตรัง[5]" id="TvOrganizationt13">
      <span style="color:blue;font-weight:bold">วิทยาเขตตรัง</span></span></td>
      </tr>
      </tbody>
      </table>

      ////ส่วนของการแสดงผล node ลูก(คณะ/หน่วยงาน) จะมีแท็ก DIV คั่นอยู่ ก่อนจะเจอแท็ก <table></table>ของ node ลูก

      <div id="TvOrganizationn13Nodes" style="display:block;">
      ////ในที่นี้จะมี 2 คณะ/หน่วยงานในวิทยาเขตตรัง คือ คณะพาณิชยศาสตร์และการจัดการ และคณะสถาปัตยกรรมศาสตร์
      ////คณะพาณิชยศาสตร์และการจัดการ
      <table cellpadding="0" cellspacing="0" style="border-width:0;">
      <tbody>
      <tr>
      <td><div style="width:20px;height:1px"></div></td>
      <td><img src="xxx" alt=""></td>
      <td><a href="BasicTreeviewAll.aspx?FacId=46" target="_blank"
      onclick="javascript:TreeView_SelectNode(TvOrganization_Data, this,'TvOrganizationt14');"
      title="คณะพาณิชยศาสตร์และการจัดการ[46]" id="TvOrganizationt14i" tabindex="-1">
      <img src="images/star.png" alt="" style="border-width:0;"></a></td>
      <td style="white-space:nowrap;"><input type="checkbox" name="TvOrganizationn14CheckBox"
      id="TvOrganizationn14CheckBox" title="คณะพาณิชยศาสตร์และการจัดการ[46]">
      <a class="TvOrganization_0" href="BasicTreeviewAll.aspx?FacId=46" target="_blank"
      onclick="javascript:TreeView_SelectNode(TvOrganization_Data, this,'TvOrganizationt14');"
      title="คณะพาณิชยศาสตร์และการจัดการ[46]" id="TvOrganizationt14">คณะพาณิชยศาสตร์และการจัดการ</a></td>
      </tr>
      </tbody>
      </table>
      ////คณะคณะสถาปัตยกรรมศาสตร์
      <table cellpadding="0" cellspacing="0" style="border-width:0;">
      <tbody>
      <tr>
      <td><div style="width:20px;height:1px"></div></td>
      <td><img src="xxxx" alt=""></td>
      <td><a href="BasicTreeviewAll.aspx?FacId=66" target="_blank"
      onclick="javascript:TreeView_SelectNode(TvOrganization_Data, this,'TvOrganizationt15');"
      title="คณะสถาปัตยกรรมศาสตร์[66]" id="TvOrganizationt15i" tabindex="-1">
      <img src="images/star.png" alt="" style="border-width:0;"></a></td>
      <td style="white-space:nowrap;"><input type="checkbox" name="TvOrganizationn15CheckBox"
      id="TvOrganizationn15CheckBox" title="คณะสถาปัตยกรรมศาสตร์[66]">
      <a class="TvOrganization_0" href="BasicTreeviewAll.aspx?FacId=66" target="_blank"
      onclick="javascript:TreeView_SelectNode(TvOrganization_Data, this,'TvOrganizationt15');"
      title="คณะสถาปัตยกรรมศาสตร์[66]" id="TvOrganizationt15">คณะสถาปัตยกรรมศาสตร์</a></td>
      </tr>
      </tbody>
      </table>
      </div>

                จากแถบสีที่เน้นไว้ใน tag HTML ข้างต้น จะเห็นว่า  node แม่(วิทยาเขต)จะถูกสร้างเป็นแท็ก <table> </table> คลุมและถูกคั่นกับ node ลูก ด้วยแท็ก <div> </div> ก่อน node ลูกจะสร้างแท็ก <table> </table> คลุม node ของตัวเอง ทำให้ตอนจัดการกับ node แต่ละแบบใน jQuery จึงแยกส่วน node แม่และลูกด้วยแท็กดังกล่าวนั่นเองค่ะ

    3. ส่วนของ body ในการแสดงผล
      <body>
          <form id="form1" runat="server">
              <asp:TreeView ID="TvOrganization" runat="server" ShowCheckBoxes="All" >
              </asp:TreeView>
          </form>
      </body>

      หมายเหตุ : กรณีที่ต้องการใช้งานเกี่ยวกับ check box อย่าลืมกำหนดคุณสมบัติให้กับ TreeView เพื่อให้สามารถแสดง check box ไว้ด้วยนะคะ ซึ่งก็คือ การกำหนดค่าให้กับ ShowCheckBoxes นั่นเองค่ะ

    4. ตัวอย่างผลลัพธ์
      แบบที่ 1 เลือกที่  node วิทยาเขต จะเลือกที่ node คณะ/หน่วยงานในวิทยาเขตนั้นให้ทั้งหมด

      แบบที่ 2
      หากเลือกออกจากคณะ/หน่วยงานใดหน่วยงานหนึ่ง จะทำการเลือกออกที่  node วิทยาเขตให้อัตโนมัติ

               เพียงเท่านี้ท่านก็จะสามารถดึงข้อมูลจากฐานข้อมูลมาแสดงใน TreeView ของท่านได้แล้ว และนี่ก็อาจจะเป็นเพียงหนึ่งในวิธีการดึงข้อมูลมาแสดงใน TreeView ในเบื้องต้นที่ผู้เขียนศึกษาและนำมาประยุกต์ให้ดูเป็นตัวอย่างเท่านั้น หวังว่าผู้อ่านจะสามารถนำไปเป็นแนวทางในการนำไปประยุกต์ใช้กับงานของท่านได้ นอกจากนี้ท่านยังสามารถผนวกส่วนของการกำหนดคุณสมบัติที่ฝั่ง client กับการกำหนดคุณสมบัติตอนฝั่งเซิร์ฟเวอร์(C#) ร่วมกันได้ เพื่อเพิ่มประสิทธิภาพและลูกเล่นให้กับ TreeView ของท่านมากยิ่งขึ้นค่ะ หากมีส่วนใดผิดพลาดทางผู้เขียนขออภัยไว้ ณ ที่นี้ด้วยนะคะ ขอบคุณค่ะ

    แหล่งข้อมูลอ้างอิง :

  • มาทำความรู้จักกับพื้นฐานการใช้งาน “TreeView” สำหรับมือใหม่กันดีกว่า

              เชื่อว่านักพัฒนาโปรแกรม Web application ด้วย .Net หลายๆท่านอาจจะเคยได้ยินชื่อของเจ้า “TreeView” กันมาบ้างแล้ว หรือบางท่านก็อาจจะเกือบลืมเจ้าเครื่องมือตัวนี้ไปแล้วก็ตามเพราะมันอาจจะไม่ใช่เครื่องมือที่ถูกหยิบมาใช้บ่อยนัก ในบทความนี้ผู้เขียนจึงขอหยิบยกเจ้า “TreeView” มาปัดฝุ่น แนะนำลูกเล่นการใช้งาน การกำหนดคุณสมบัติต่างๆ และวิธีการใช้งานกันอย่างคร่าวๆก่อน เพื่อเป็นการปูพื้นฐานให้กับมือใหม่หัดใช้ TreeView และรื้อความทรงจำให้กับผู้ที่เคยใช้ TreeView มาก่อนหน้านี้ เผื่อความสามารถที่ซ่อนอยู่จะไปเตะตาตรงใจท่านใดที่กำลังมองหาการทำงานแบบนี้อยู่พอดี จนอยากนำเครื่องมือตัวนี้ไปประยุกต์ใช้เป็นอีกหนึ่งทางเลือกในการแสดงผลข้อมูลในงานพัฒนาของท่านกันอีกครั้งได้ค่ะ
              แต่ก่อนจะพูดถึงลูกเล่นการทำงานของ TreeView คงต้องเกริ่นนำกันก่อนว่าเจ้าเครื่องมือตัวนี้ถูกจัดอยู่ในจำพวก Navigation Control ซึ่งบางคนอาจเกิดคำถามว่า ข้อมูลแบบใดบ้างจึงจะเหมาะนำมาใช้งานแสดงผลกับเจ้า TreeView นี้ ซึ่งโดยความเห็นส่วนตัวแล้วนั้น ผู้เขียนคิดว่าข้อมูลที่เหมาะจะมาแสดงผลด้วย TreeView ควรจะเป็นข้อมูลที่มีลักษณะเป็นแบบ Hierarchy หรือเป็นลักษณะโครงสร้าง มีลักษณะข้อมูลเป็นลำดับชั้นย่อยๆ เช่น โครงสร้างหน่วยงาน โครงสร้างองค์กร หรือข้อมูลที่เป็นประเภทหลักและประเภทย่อย เป็นต้น และเพื่อไม่ให้เป็นการเสียเวลา เรามาเรียนรู้วิธีจัดการกับ TreeView ของเรากันเลยดีกว่าค่ะ

    ขั้นตอนสร้าง TreeView อย่างง่ายจาก Tool box ของ Visual studio .Net สามารถทำได้ดังนี้

    1. สร้าง TreeView โดยเลือกจากแท็บเครื่องมือ ในกลุ่ม Navigation มาวางในหน้าจอ design ของเรา ดังรูป


    2. การเพิ่มและจัดการ node ให้กับ TreeView ได้โดยการคลิกเลือก “Edit Nodes…” ดังภาพ


    3. การจัดการเพิ่ม-ลดข้อมูล node ในระดับต่างๆ จะแสดงภาพดังหน้าจอต่อไปนี้ เพื่อใช้ในการจัดการเพิ่ม-ลดข้อมูล node ในระดับต่างๆ ดังนี้



      โดยขั้นตอนการเพิ่ม – ลด node อย่างคร่าวๆ มีดังนี้
      • การเพิ่ม node ที่เป็น root (ลำดับแรกสุด) โดยการกดปุ่ม
      • การเพิ่ม node ระดับย่อย(child node) โดยการกดปุ่ม
      • การลบ node ที่ไม่ต้องการ สามารถทำได้โดยการกดปุ่ม
      • ปรับเปลี่ยนระดับความลึกของ node โดยคลิกเลือก node ที่ต้องการจัดการและกดปุ่ม เพื่อเลื่อนระดับความลึกมากน้อยได้ตามต้องการ ซึ่งจะเห็นได้ว่ามีการทำงานคล้ายกับการเยื้องย่อหน้าใน MS Word ที่เราคุ้นเคยกันดี
      • การเลื่อนลำดับบน-ล่างให้กับ node สามารถทำได้โดยกดปุ่ม

        ตัวอย่าง หน้าจอการจัดการ node ใน TreeView



                      จากภาพตัวอย่าง มีการเพิ่มและจัดการ node ข้อมูลโครงสร้างองค์กรตั้งแต่ระดับมหาวิทยาลัย วิทยาเขต และคณะ โดยการกำหนดค่าตายตัวจากหน้าจอ design ด้วยการระบุเอง ไม่ได้ดึงจากฐานข้อมูล ซึ่งท่านสามารถทดลองเพิ่มและจัดการได้ด้วยตัวเองเพื่อให้เข้าใจการทำงานมากขึ้น โดยลองทำตามขั้นตอนการจัดการ node ข้างต้น
                      นอกจากการเพิ่ม-ลด node แล้ว ท่านยังสามารถกำหนดคุณสมบัติให้กับ node ได้ด้วย โดยคลิกข้อมูล node ที่ต้องการจัดการจากฝั่งซ้ายมือ และกำหนดคุณสมบัติของ node ดังกล่าวในฝั่งขวามือ ซึ่งรายละเอียดการกำหนดคุณสมบัติต่างๆ ในแต่ละ node จะขอพูดในหัวข้อถัดไป (ข้อ 4.)ค่ะ

    4. กำหนดคุณสมบัติให้กับแต่ละ node เราสามารถกำหนดคุณสมบัติ (Properties) เฉพาะให้กับแต่ละ node ได้ โดยจะขอพูดถึงคร่าวๆ ที่คิดว่าน่าจะใช้อยู่บ่อยๆและน่าสนใจ ดังนี้
      • ShowCheckBox : เป็นการระบุว่าจะให้ node ดังกล่าวแสดงช่องให้เลือกหรือไม่
      • Checked : เป็นการระบุว่า ต้องการให้มีการทำเครื่องหมายถูกไว้ในกล่อง check box หรือไม่ ซึ่งต้องมีการกำหนดควบคู่กับ ShowCheckBox = “true” นั่นเอง
      • Text : ระบุว่าต้องการให้ node ดังกล่าวแสดงข้อความอะไร
      • Value : ระบุค่าที่จะกำหนดให้กับ node ดังกล่าว และสามารถเลือกดึงค่าไปใช้งานได้(ในกรณีที่จะนำไปพัฒนาโปรแกรมต่อ)
      • NavigateUrl : กำหนดว่าเมื่อกด node ดังกล่าวจะให้ไปยังหน้าจอใด โดยระบุชื่อเพจหน้าจอนั้น
      • Target : เป็นการระบุการเปิดเพจในกรณีที่มีการกำหนด NavigateUrl ไว้ว่าจะให้เปิดเพจใหม่ หรืออยู่ในหน้าเดิมนั่นเอง
      • ImageUrl : เป็นการระบุว่าต้องการให้แสดงเป็นรูปภาพอะไรหน้าข้อความใน node นั้นๆ
      • Selected : เป็นการระบุว่าจะให้ node ดังกล่าวสามารถคลิกลิงค์ได้หรือไม่
      • SelectAction : กำหนด action ที่จะให้ทำตอนกดเลือกลิงค์ใน node นั้น
        1) Expand : เมื่อหากต้องการให้คลิกแล้วขยาย node ย่อย ซึ่งเมื่อคลิกแล้วจะย่อ-ขยาย node ย่อยได้
        2) SelectExpand : จะเป็นการระบุให้มีการขยาย node เช่นกัน แต่จะต่างกันตรงที่เมื่อขยาย node ย่อยแล้วจะไม่ย่อ-ขยายให้อีกแบบ Expand นั่นหมายถึงว่าจะสามารถคลิกลิงค์ของ node เพื่อขยายได้เท่านั้น แต่จะไม่สามารถย่อกลับมาได้นั่นเอง
        3) None : เมื่อไม่ต้องการให้คลิกได้
      • ToolTip : เป็นการระบุข้อความที่ต้องการให้แสดงเมื่อชี้ไปที่ node นั้นๆ
      • Expanded : เป็นการกำหนดว่า ตอนเริ่มต้นจะให้ node ย่อยของ node ดังกล่าวขยายไว้หรือไม่

        ตัวอย่าง ผลลัพธ์จากการกำหนดลองกำหนดค่าต่างๆให้กับบาง node


                      จากภาพ จะเห็นว่าแต่ละ node มีการแสดงผลแตกต่างกันตามที่เราระบุ เช่น บาง node มีการกำหนดให้แสดงภาพหน้าข้อความ บาง node ไม่สามารถคลิกลิงค์ได้ เช่น มหาวิทยาลัยสงขลานครินทร์ และบาง node มี check box อยู่หน้าข้อความให้เลือก และบาง node มีการยุบ node ย่อยไม่แสดงในตอนเริ่มต้น เป็นต้น
    5. กำหนดคุณสมบัติให้กับทุก node จาก properties ของคอนโทรล TreeView ซึ่งจะแตกต่างจากการกำหนดในแต่ละ node ในข้อ 4. เนื่องจากวิธีการกำหนดคุณสมบัติแบบนี้ จะเหมาะกับกรณีที่ไม่ต้องการระบุคุณสมบัติแยกในแต่ละ node แต่ต้องการให้เป็นไปในแบบเดียวกันทั้ง TreeView ทำให้ลดระยะเวลาที่จะต้องกำหนดรูปแบบให้กับทุก node ที่ต้องการให้แสดงผลเหมือนกัน โดยจะขอยกตัวอย่างให้กับคุณสมบัติบางตัวที่อาจจะจำเป็นต้องใช้ ดังนี้
      • ShowCheckBox : เป็นการกำหนดคุณสมบัติคล้ายกับที่กำหนดให้กับแต่ละ node แต่หากมากำหนดที่ตรงนี้ จะทำให้ทุก node แสดงหรือซ่อนกล่อง check box ได้จากจุดเดียว โดยมีให้เลือก 4 ตัวเลือก ดังนี้

        1) All : กำหนดให้ทุก node แสดง check box

        ตัวอย่าง ผลลัพธ์จากการกำหนด ShowCheckBox =”All”


        จากภาพจะเห็นว่า มี check box อยู่ในแต่ละ node ทั้งหมด โดยการกำหนดที่คุณสมบัติ ShowCheckBox =”All” นี้ที่จุดเดียว โดยไม่ต้องไปกำหนดที่แต่ละ node

        2) Leaf : กำหนดให้แสดง check box เฉพาะ node ลูกที่ไม่มี node ย่อย

        ตัวอย่าง ผลลัพธ์จากการกำหนด ShowCheckBox =”Leaf”


        จากภาพจะเห็นว่า จะแสดงผล check box เฉพาะ node ที่เป็นลูก และไม่มี node ย่อยอีก ซึ่งเรียก node แบบนี้ว่า “Leaf” นั่นเอง

        3) None : ไม่แสดง Checkbox ใน node ใดๆ เลย

        ตัวอย่าง ผลลัพธ์จากการกำหนด ShowCheckBox =”None”


        จากภาพจะเห็นว่า ไม่แสดงผล check box ใน node ใดๆเลย

        4) Parent : เป็นการแสดง check box เฉพาะตำแหน่ง node ที่มีลูก หรือ child node ที่ไม่ใช่ root node นั่นเอง

        ตัวอย่าง ผลลัพธ์จากการกำหนด ShowCheckBox =”Parent”


        จากภาพจะเห็นว่า จะแสดง check box เฉพาะ node ที่มีลูกในระดับย่อย และต้องไม่ใช่ root node นั่นเอง

        5) Root : จะแสดง check box เฉพาะตำแหน่ง root หรือ node ระดับแรกสุดเท่านั้น

        ตัวอย่าง ผลลัพธ์จากการกำหนด ShowCheckBox =”Root”

        จากภาพจะเห็นว่า จะแสดงผล check box ใน node ที่อยู่ในระดับ root หรือระดับแรกสุดนั่นเอง

      • ShowExpandCollapse : เป็นการระบุว่าต้องการให้แสดงตัวย่อ-ขยาย ที่เป็นเครื่องหมาย + และ – เพื่อย่อขยาย TreeView หรือไม่ หากกำหนดเป็น false จะไม่สามารถย่อ-ขยาย TreeView ดังกล่าวได้ โดยค่าตั้งต้นจะเป็น true ซึ่งหมายถึงสามารถย่อ-ขยายได้นั่นเอง

        ตัวอย่าง การกำหนดคุณสมบัติ ShowExpandCollapse =”false”

        จากภาพจะเห็นว่า ไม่สามารถย่อ-ขยายข้อมูลของ TreeView แต่ละ node ได้เลย

      • BorderStyle : เป็นการกำหนดรูปแบบของเส้นขอบของ TreeView ที่เราต้องการได้ เช่น solid dashed dotted เป็นต้น

        ตัวอย่าง การกำหนดคุณสมบัติของเส้นขอบ BorderStyle เป็น Double


      • CollapseImageUrl : เป็นการระบุ url ภาพที่ต้องการนำมาใช้แสดงแทนเครื่องหมาย – เพื่อให้กดแล้วย่อ node ย่อย
      • ExpandImageUrl : เป็นการระบุ url ภาพที่ต้องการนำมาใช้แสดงแทนเครื่องหมาย + เพื่อให้กดแล้วขยาย node ย่อย
      • NoExpandImageUrl : เป็นการระบุ url ภาพที่ต้องการนำมาใช้แสดงในกรณีที่ node ดังกล่าวไม่มี node ย่อย

        ตัวอย่าง ผลลัพธ์ของการระบุค่าของ CollapseImageUrl ให้เป็นรูปเครื่องหมายลบ กำหนดค่า ExpandImageUrl ให้เป็น url ของรูปที่เป็นเครื่องหมายบวก และกำหนด NoExpandImageUrl เป็นรูปไอคอนสีฟ้า ดังรูป

        หมายเหตุ : รูปภาพที่กำหนดในการย่อ-ขยายจะแสดงผลเมื่อ ShowLines เป็น false เท่านั้น

      • ImageSet : เป็นการกำหนดภาพที่ต้องการให้แสดงหน้า node ลักษณะคล้ายกับ bullet ดังตัวอย่างในภาพ



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



        เมื่อเราคลิกเลือก “Auto Format…” จะปรากฎภาพหน้าจอดังนี้



        ซึ่งจะเห็นได้ว่า มีลักษณะการจัดการเดียวกับตอนเรากำหนดคุณสมบัติจาก ImageSet นั่นเอง

      • การกำหนด style ให้กับ node แต่ละแบบ ไม่ว่าจะเป็น LeafNodeStyle NodeStyle ParentNodeStyle หรือ RootNodeStyle ท่านก็สามารถกำหนดรูปแบบและตกแต่งความสวยงามให้กับ node แต่ละแบบได้ เช่น การใส่พื้นหลัง สีตัวอักษร หรือ แม้กระทั่งการระบุ style sheet ที่จัดทำไว้ก็สามารถทำได้เช่นกัน

      • LevelStyles : เป็นการกำหนด Style ให้กับแต่ละ level โดยจะเรียงตามลำดับ style ของแต่ละ node เริ่มจาก root ตามลำดับ ดังภาพ



        ตัวอย่าง ผลลัพธ์ของการกำหนด LevelStyles 3 ระดับข้างต้น โดยกำหนดให้ Level แรก มีสีตัวอักษรเป็นสีม่วง และ Level ที่ 2 มีสีตัวอักษรเป็นสีชมพู และ Level ที่ 3 มีตัวอักษรสีเขียว ดังภาพ



      • ExpandDepth : เป็นการกำหนดว่าจะให้การแสดงผล TreeView ขยายเริ่มต้นที่กี่ระดับ โดยค่าตั้งต้นจะเป็นแบบ FullyExpand ซึ่งหมายถึงขยายทั้งหมดตอนเริ่มต้น

        ตัวอย่าง ผลลัพธ์การระบุ ExpandDepth = “1”

      • DataSourceID : เป็นการระบุแหล่งข้อมูลให้กับการแสดงผล TreeView ให้มาจากการดึงข้อมูล ไม่ใช่การระบุค่า node ตายตัวจากหน้าเพจ
      • NodeIndent : ระยะการเยื้องหน้าของ node แต่ละระดับ โดยมีค่าตั้งต้นเท่ากับ 20 ซึ่งท่านสามารถลดหรือเพิ่มได้ตามความเหมาะสม
      • ShowLines : เป็นการระบุว่าต้องการให้แสดงเส้นโยงเชื่อมของ node แต่ละระดับหรือไม่
      • SelectedNodeStyle : เป็นการกำหนด style ให้กับ node ที่โดนเลือกคลิก เช่น การระบุพื้นหลัง หรือการกำหนดสีตัวอักษร เป็นต้น
        ตัวอย่าง ผลลัพธ์การระบุ SelectedNodeStyle ให้พื้นหลังเป็นสีม่วงและตัวอักษรสีขาว โดยเมื่อคลิกที่ node ใดก็ตามก็จะแสดงผลดังที่ได้ระบุไว้ที่ node นั้น

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

  • ปัญหา “A potentially dangerous Request.Form value was detected from the client (ctl00$ContentPlaceHolder1$txtAbstractEng="…ontrol ” แก้ไขได้อย่างไร

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

    ปัญหา :

    ในการบันทึกข้อมูลลงบางเว็บไซต์เราจะอาจจะพบปัญหาว่าหลังจากเราป้อนข้อมูลเสร็จแล้ว แต่ทำไมไม่สามารถบันทึกข้อมูลได้ เกิด error เช่น

    เมื่อบันทึกจะมีข้อความขึ้นดังภาพข้างล่าง ป้อนใหม่บันทึกใหม่ก็ยังไม่ได้ โอ๊ยเครียด จะทำยังไงดี

    สาเหตุ :

    อาจจะเนื่องมาจากมีการ copy ข้อมูลมาจากแหล่งอื่นที่มีตัวอักษรพิเศษบางตัว  เช่น ? ติดมาด้วย ทำให้เราจะไม่สามารถบันทึกข้อมูลลงฐานได้ เราจะทำอย่างไร

    การแก้ไข : สามารถแก้ไขได้หลายวิธี คือ

    1. ในกรณีที่เป็นผู้ใช้งาน เราสามารถแก้ไขง่ายๆ ได้โดยการ นำ ? ออกจากข้อความ ดังรูปข้างล่าง แล้วบันทึกใหม่

    2. ในกรณีที่เป็นผู้พัฒนาระบบ เราจะเพิ่มข้อความ ValidateRequest=”false” ลงใน source ของหน้าจอที่ error ดังรูปข้างล่าง

    เพียงเท่านี้ปัญหาดังกล่าวก็จะหมดไปแล้วค่ะ ไม่ยากเลยใช่มั้ยคะ

    แล้วพบกันใหม่ค่ะ

  • การเข้ารหัส Password หรือข้อมูลส่วนบุคคลในฐานข้อมูล ด้วย Hash Function กับ Salt Value

    การ Hash
    การ Hash หรือ Hashing ชื่ออย่างเป็นทางการคือ Cryptographic Hash คือการสร้างข้อมูลที่เป็นตัวแทนของข้อมูลที่ต้องการ ซึ่งอาจจะเป็นรหัสผ่าน หรือข้อมูลส่วนบุคคลอื่นๆ และนำไปจัดเก็บในฐานข้อมูลหรือใน Text file หรือในที่อื่นๆ ซึ่งข้อดีของการทำ Hash คือจะไม่สามารถถอดรหัส หรือกระทำการใดๆ เพื่อที่จะ Reverse ให้ออกมาเป็นข้อความต้นฉบับ ซึ่งในปัจจุบันมีวิธีการ Hash มากมาย เช่น MD5, SHA1, SHA256, SHA512, RipeMD, WHIRLPOOL, SHA3 เป็นต้น

    การเขียนโปรแกรม
    ในแง่การเขียนโปรแกรมของแต่ละภาษา จะมี Library หรือเครื่องมือที่เอาไว้ใช้ทำ Hash อยู่แล้ว สามารถเปิดจากคู่มือ ได้เลยครับ

    MD5 Hashing & Cracking
    เป็นการทำ Hash ที่พื้นฐานที่สุด และเมื่อหลายปีที่ผ่านมามีข่าวออกมาว่ามีผู้ Crack ได้สำเร็จ ซึ่งรายละเอียดคร่าวๆ ของเรื่องนี้คือ การทำ Hash ทุกชนิดจะมีการเกิดการซ้ำกันของค่า Hash เนื่องจากการมีคุณสมบัติแทนข้อมูลที่ต้องการ ซึ่งค่า Hash ที่สร้างขึ้นจะมีความยาวที่เท่ากันเสมอ ซึ่งสำหรับ MD5 ก็จะมีความยาว 16 bytes (128 bits) ซึ่งค่า hash ที่เป็นไปได้ทั้งหมดก็จะมีค่า 256^16 (หรือ 2^128) ค่าเท่านั้น ในขณะนี้ที่ข้อมูลที่เราต้องการแทนตัวนั้นอาจเป็นข้อมูลอะไรก็ได้ที่มากกว่าค่า 256^16 (หรือ 2^128) แน่นอน จึงเป็นไปได้ที่จะพบข้อมูลมากกว่า 1 ชุดจะมีค่า Hash ที่ตรงกัน
    ความจริงแล้ว MD5 จะไม่สามารถถอดรหัสได้ เนื่องจาก Hash ทุกชนิดจะผ่านกระบวนการเข้ารหัสแบบทางเดียว ดังนั้นทางที่จะสามารถจะรู้ได้ว่าค่าตั้งต้นของ Hash นี้คืออะไร คือการพยายามสุ่มรหัสที่เป็นไปได้ จากนั้นเอาไปแปลงค่าเป็น MD5 และนำค่าที่ได้ไปเปรียบเทียบ (เรียกว่าเป็นการ Brute force นั่นเอง) ซึ่งถ้าเป็นข้อมูลที่มีความยาวหรือมีความซับซ้อนมาก ก็จะต้องใช้เวลาที่นานขึ้น

    Rainbow Table
    เป็นการเก็บข้อมูล Hash โดยมีข้อมูลต้นฉบับจากการ Brute Force เพื่อความรวดเร็วในการตรวจสอบ ซึ่งในปัจจุบัน GPU ระดับปานกลางหลายๆ รุ่นจะสามารถคำนวน Hash ได้ในระดับ 10 ล้าน Hash ต่อวินาที ซึ่งในปัจจุบันมีผู้ยอมเสียเวลาเพียงครั้งเดียวเพื่อสร้าง Hash ที่มีควายาวมากๆ และมีความซับซ้อน เพื่อในครั้งต่อๆ ไปจะสามารถนำมาาใช้งานได้ทันที และมีให้ดาวน์โหลดได้ฟรีอีกด้วย

    ปัญหาของ Rainbow Table ในปัจจุบันคือ ยังไม่มีการสร้าง rainbow table ขึ้นมาสำหรับ hash ทุกชนิดหรือทุกความยาวของข้อมูลที่ต้องการ ถึงแม้จะมี CPU หรือ GPU ความสามารถสูงๆ แต่การทำ Hash ก็ยังคงใช้พลังในการประมวลผลมากเช่น SHA-2 ขนาด 256 bits ขึ้นไป เป็นต้น

    Image result for hashing with salt

    Salting
    เป็นเทคนิคนึงสำหรับเพิ่มความปลอดภัยสำหรับข้อมูลตั้งต้นของเรา ซึ่งทำให้ใช้เวลาในการถอดรหัสมากขึ้น ดังตัวอย่างเช่น ข้อความที่ต้องการเข้ารหัสตั้งต้นคือ “ThisIsMyPassword” และเมื่อรวมเข้ากับ Salt (ซึ่งอาจมาจากข้อความที่สุ่มขึ้นมา) คือ “3gswgW09seh” จะได้เป็น “ThisIsMyPassword3gswgW09seh” จากนั้นนำข้อความนี้ไป Hasing ซึ่งถ้าคำนวนความน่าจะเป็นของข้อความ กรณีที่เป็นตัวอักษรตัวเล็ก ตัวใหญ่ และตัวเลข มีความเป็นไปได้ 62 แบบ จะเท่ากับว่าถ้ารหัสผ่านที่เราเก็บมีความยาว 16 ตัวอักษร ก็ต้อง Hash ถึง 16^62 แบบ แต่ถ้าเป็นข้อความที่รวมกับSalt แล้วข้างต้น เป็นความยาว 27 ตัวอักษร ผู้ไม่ประสงค์ดีต้อง Hash ถึง 27^62 ถึงจะได้ข้อความที่ถูกต้อง ซึ่งต้องใช้เวลามหาศาลมากกว่าเดิม แต่ข้อเสียของวิธี Salting จะต้องมีการเก็บ Salt Value ในลักษณะของ Plain Text หรือเก็บไว้ในโปรแกรมที่พัฒนา เพื่อการถอดรหัสที่ถูกต้อง และถ้าหาก Salt Value มีการเสียหายหรือเปลี่ยนค่าไปหลังจากการเข้ารหัสเสร็จแล้ว จะไม่สามารถเทียบ Hash เพื่ออ่านข้อความต้นฉบับได้เลย

    Image result for hashing with salt

    Conclusion
    1. การเก็บข้อมูลที่สำคัญ เช่น รหัสผ่าน หรือแม้กระทั่งเลขประจำตัวประชาชน ในฐานข้อมูล ควรเก็บในรูปแบบ Hash เท่านั้น
    2. รหัสผ่านยิ่งยาว ยิ่งใช้เวลาในการถอดรหัสมากขึ้น และยิ่งมีการใช้ Salt Value จะใช้เวลามากยิ่งขึ้น โดยเฉพาะการใช้ Salt Value เพิ่มเข้าไปเพื่อให้มีความยาวมากขึ้น
    3. MD5 ก็ยังเพียงพอต่อการเก็บรหัสผ่านและข้อมูลอื่นๆ แต่ก็ยังสู้ SHA-2 ไม่ได้
    4. ทางที่ดีที่สุดคือ อย่าให้รหัสผ่านหรือข้อมูลที่เก็บอยู่ ถูกเข้าถึงจากภายนอก แม้แต่จะเป็นแค่ Hash ก็ตาม

    Reference:
    https://crackstation.net/hashing-security.htm

  • CrystalReport : จัดการกราฟซ่อนแอบ

    จากที่ผู้เขียนช่วงนี้ได้มีการทำกราฟใน Crystal Report ทำไปทำมาผลปรากฎว่า
    กราฟไม่แสดงรูปซะงั้น (ไหงเป็นแบบนี้ได้หว่าาาาาา T T)

    จึงได้ลองค้นหาข้อมูลและพบว่า ต้องเพิ่ม Config เพิ่มเติมเข้าไปใน
    ” Web.config “
    ตาม Code ด้านล่างเลยจ้าาาา

    ส่วนแรก

    “System.web” ส่วน “httpHandlers”
    โดย Version จะต้องเป็น Version Crystal Report ที่เราใช้งานอยู่ อย่าลืมตรวจสอบให้ตรงกันด้วยนะ

    <configuration>
     <system.web> 
       <httpHandlers>       
          <add verb="GET" path="CrystalImageHandler*"/type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>     
       </httpHandlers>   
     </system.web>
    </configuration>

    ส่วนที่สอง

    “System.webServer” ส่วน “handlers”
    โดย Version จะต้องเป็น Version Crystal Report ที่เราใช้งานอยู่ อย่าลืมตรวจสอบให้ตรงกันด้วยนะ

    <configuration>
     <system.webServer>
       <validation validateIntegratedModeConfiguration="false"/>
         <handlers>
           <add name="CrystalImageHandler.aspx_GET" verb="GET" path="CrystalImageHandler*" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" preCondition="integratedMode"/>
         </handlers>
     </system.webServer>
    </configuration>

    หวังว่า Blog นี้จะช่วยเหลือท่านที่ประสบปัญหาเดียวกันอยู่นี้ไม่มากก็น้อยนะคะ

    แล้วพบกันใหม่ Blog หน้าค่าาาาาา 🙂