ทำอย่างไรให้เว็บไซต์ที่เราพัฒนาสามารถอัพโหลดไฟล์แบบคราวละหลายไฟล์ได้โดยไม่จำกัดจำนวน ด้วย ASP.NET(C#)

          ในการพัฒนาเว็บไซต์ บางครั้งอาจมีความจำเป็น หรือความต้องการจากผู้ใช้ที่ต้องการให้เว็บไซต์ดังกล่าวมีฟังก์ชั่นการทำงานในส่วนของการอัพโหลดไฟล์เพื่อแนบไฟล์เข้าไปในระบบและบันทึกลงฐานข้อมูล เพื่อให้สามารถเรียกดูข้อมูลการแนบไฟล์ดังกล่าวได้ในภายหลัง การอัพโหลดไฟล์จึงถือเป็นอีกหนึ่งฟังก์ชั่นการทำงานที่นักพัฒนาเว็บไซต์ควรทราบไว้ ซึ่งลักษณะการทำงานโดยทั่วไปส่วนใหญ่เราจะใช้ Control ที่มีเรียกว่า “FileUpload” แบบอัพโหลดครั้งละ 1 ไฟล์ และหากมีมากกว่านั้นก็จะมีการสร้างตัว FileUpload มาวางไว้ในหน้าจอเพิ่มตามจำนวนที่ต้องการแบบตายตัว เช่น หากในหน้าจอดังกล่าวต้องการสามารถให้ทำการอัพโหลดไฟล์ได้ไม่เกิน 5 ไฟล์ต่อการอัพโหลดแต่ละครั้งก็จะมีการลากคอนโทรล FileUpload มาวางไว้ในหน้าจอจำนวน 5 ตัว เพื่อให้สามารถรองรับความต้องการในการอัพโหลดไฟล์ของผู้ใช้ได้ แต่ผู้เขียนพบว่าการทำงานดังกล่าวอาจไม่รองรับความต้องการในการทำงานของผู้ใช้ที่จะเพิ่มไฟล์ได้ครั้งละหลายๆไฟล์โดยไม่จำกัดและผู้พัฒนาไม่จำเป็นต้องระบุหรือสร้างคอนโทรล FileUpload มาวางในหน้าจอในจำนวนที่ตายตัวโดยไม่จำเป็น โดยผู้ใช้สามารถคลิกปุ่มเพื่อเพิ่มจำนวนในการอัพโหลดไฟล์แต่ละครั้งได้เองเพื่อความยืดหยุ่นในการใช้งาน ในบทความนี้ ผู้เขียนจึงขอเสนอแนวทางในการพัฒนาเว็บไซต์โดยใช้ ASP.NET(C#) ในแบบที่มีการอัพโหลดไฟล์ได้คราวละหลายๆไฟล์ในแบบไม่ต้องจำกัดจำนวนคอนโทรล FileUpload ในหน้าจอโดยมีการระบุจำนวนไฟล์ที่สามารถอัพโหลดได้ในแต่ละครั้งโดยผู้พัฒนาแบบตายตัวอย่างเช่นที่กล่าวไว้ข้างต้น           หลังจากที่ได้มีการศึกษาเพิ่มเติม ผู้เขียนพบว่าใน .NET Framework เวอร์ชั่น 4.5 นั้นจะมีการเพิ่ม Feature การทำงานในส่วนนี้ให้กับคอนโทรล FileUpload ไว้แล้วผ่าน Properties ที่เรียกว่า AllowMultiple ซึ่งจะทำให้สะดวกต่อการพัฒนาและสามารถลดปัญหาดังกล่าวข้างต้นได้ แต่สำหรับเวอร์ชั่นที่ต่ำกว่ายังคงต้องมีการปรับปรุงพัฒนาเพิ่มเติมเอง ในบทความนี้จึงขอยกตัวอย่างการพัฒนาทั้ง 2 แบบในเบื้องต้นโดยจะเน้นไปในแบบเวอร์ชั่นที่ต่ำกว่า 4.5 เพื่อให้ผู้อ่านได้นำไปเป็นแนวทางในการพัฒนาต่อไป ดังนี้ 1. การอัพโหลดไฟล์คราวละหลายๆไฟล์โดยใช้ .Net Framework เวอร์ชั่นที่ต่ำกว่า 4.5           ในบทความนี้ ผู้เขียนขอเสนอแนวทางแบบที่เป็นการพัฒนาโดยใช้จาวาสคริปต์เข้ามาเป็นตัวช่วยให้สามารถอัพโหลดไฟล์ได้ครั้งละหลายไฟล์ต่อการอัพโหลดแต่ละครั้ง เพื่อลดจำนวนการโหลดของหน้าจอและทำให้ผู้ใช้รู้สึกว่าการทำงานดังกล่าวเป็นไปด้วยความรวดเร็วไม่ต้องใช้เวลานาน โดยจะอธิบายทีละขั้นตอน ดังนี้ 1) ออกแบบหน้าจอการทำงานในฝั่ง Client  ทำการออกแบบหน้าจอการทำงานไว้ในเบื้องต้น โดยมีการสร้างคอนโทรล FileUpload มาตั้งต้นไว้ 1 ตัว และมีปุ่มเพื่อให้ทำการเพิ่มคอนโทรล FileUpload ได้เองอัตโนมัติโดยตัวผู้ใช้เอง และปุ่มที่ใช้ในการอัพโหลดไฟล์จากคอนโทรล FileUpload ทั้งหมด ดังนี้ <body> <form id=”form1″ runat=”server”> <div> <div id=”fileUploadarea” class=”Divborder”> <div id=’divfirstUpload’><br /><asp:FileUpload ID=”fuMultiple” runat=”server” CssClass=”fileUpload” onchange=”javascipt:FileValidate(this,5);” />&nbsp; <input style=”display:inline;” id=”BtnRemove” type=”button” value=”Remove” onclick=”DelFileUpload(‘divfirstUpload’);” /> </div> </div> <br /> <div>&nbsp; <input style=”display:inline; background-color: #A4EDFF; color: #333333; width: 150px; font-weight: bold;” id=”btnAddMoreFiles” type=”button” value=”Add more files” onclick=”AddMoreFilesWithMax(6);” /> &nbsp; <asp:Button ID=”BtnUpload” runat=”server” onclick=”BtnUpload_Click” Text=”Upload” OnClientClick=”return ValidateFileUpload();” BackColor=”#3399FF” Font-Bold=”True” ForeColor=”White” Width=”150px” /> <br> <asp:GridView ID=”gvResult” runat=”server” AutoGenerateColumns=”False” CellPadding=”4″ ForeColor=”#333333″ GridLines=”None” Width=”410px”> <RowStyle BackColor=”#EFF3FB” /> <Columns> <asp:BoundField DataField=”Name” HeaderText=”ชื่อไฟล์”> <ItemStyle Width=”200px” /> </asp:BoundField> <asp:BoundField DataField=”FileSize” HeaderText=”ขนาดไฟล์(KB)”> <ItemStyle HorizontalAlign=”Right” Width=”120px” /> </asp:BoundField> </Columns> <FooterStyle BackColor=”#507CD1″ Font-Bold=”True” ForeColor=”White” /> <PagerStyle BackColor=”#2461BF” ForeColor=”White” HorizontalAlign=”Center” /> <SelectedRowStyle BackColor=”#D1DDF1″ Font-Bold=”True” ForeColor=”#333333″ /> <HeaderStyle BackColor=”#507CD1″ Font-Bold=”True” ForeColor=”White” /> <EditRowStyle BackColor=”#2461BF” /> <AlternatingRowStyle BackColor=”White” /> </asp:GridView> </div> </div> </form> </body> 2)

Read More »

สร้าง Shortcut ในการ Remote Desktop Connection

ในการพัฒนาระบบงานหลาย ๆ ระบบ ซึ่งแต่ละระบบก็ต้องมี Server ถ้าระบบมีปัญหาสิ่งแรก ๆ ที่ต้องเข้าไปดูปัญหานั่นคือการ Remote ไปยัง Server นั้น ๆ เช่นดู Process Task ต่าง ๆ มีอะไรรันอยู่ มีอะไรทำงานอยู่จึงทำให้ระบบช้า หรือทำให้ระบบมีปัญหาเป็นต้น เมื่อมีหลาย Server ครั้นจะมาจดจำ IP เครื่องที่จะ Remote ไป หรือบางเครื่องที่นาน ๆ จะเกิดปัญหาที ทางออกของปัญหามีค่ะ แค่เพียงสร้างเป็น Shortcut ในการ Remote Desktop Connection นั่นเอง มีขั้นตอนดังนี้ ที่หน้าจอ Desktop คลิกขวา New เลือกหัวข้อ Shortcut พิมพ์ข้อความดังนี้ C:\Windows\System32\mstsc.exe /v:192.168.100.170 /w:800 /h:600 –> 3.1 /v:ต่อด้วย IP Address:Port –> 3.2 /w:ต่อด้วยขนาดหน้าจอ ความกว้าง –> 3.3 /h:ต้อด้วยขนาดหน้าจอ ความสูง –> 3.4 อื่น ๆ เช่น /f หมายถึงเต็มหน้าจอ /admin หมายถึง Remote เข้าด้วย Session Admin คลิกปุ่ม Next ตั้งชื่อ Shortcut คลิก Finish จะเห็น Icon ของ Shortcut ที่ใช้ในการ Remote เพื่อเข้า Server ตามที่ได้สร้างไว้ที่หน้า Desktop

Read More »

การพัฒนา unit test โดย shim type

Shims เป็นหนึ่งใน technology ที่อยู่ใน Microsoft Fakes Framework ใช้ในการพัฒนา unit testing เพื่อแยก component ที่ต้องการทดสอบออกมาจากปัจจัยแวดล้อมต่างรอบๆ component ในกระบวนการทดสอบ โดย shims จะทำการเปลี่ยนทิศทางการเรียกใช้ method ที่กำหนด ไปยัง code ที่เขียนขึ้นมาใช้ในการทดสอบ ส่วนใหญ่เราจะใช้ shims เพื่อแยก component ที่ต้องการทดสอบออกจาก assemblies ที่ไม่ได้เป็นส่วนหนึ่งของ solution ในการพัฒนา (กรณีที่ต้องการแยก component ที่ต้องการทดสอบออกจาก solution ของตัวเอง ควรจะใช้ stubs ) method ที่พัฒนาส่วนใหญ่จะ return ผลการทำงานที่ต้องขึ้นกับเงื่อนไข ปัจจัยต่างๆจากภายนอก ในทางกลับกันสำหรับ shim  shim จะอยู่ภายใต้การควบคุมในกระบวนการทดสอบ สามารถที่จะ return ผลการทำงานตามที่กำหนดในทุกๆครั้งที่เรียกใช้งาน ซึ่งทำให้การเขียน unit testing ทำได้ง่ายขึ้นมาก ตัวอย่าง method การตรวจสอบวันที่เอกสารในปีงบประมาณ public static class Utility { public static bool IsInFiscalYear() { if (DateTime.Now < new DateTime(2015, 10, 1)) return false; else return true; } } เมื่อต้องการทดสอบ method “IsInFiscalYear” จะพบว่าการทำงานของ method ขึ้นอยู่กับ DateTime.Now ซึ่งเป็นเวลาปัจุจบันที่ได้จากระบบ ซึ่งทำให้การทดสอบยุ่งยากขึ้น (เมื่อทำการทดสอบต้องเปลี่ยน DateTime เพื่อทำการทดสอบ ซึ่งอาจจะกระทบกับส่วนอื่นๆ ไม่สามารถทำการทดสอบแบบอัตโนมัติได้ ) ซึ่งการทดสอบ method ที่มีการเรียกใช้ database, web service ก็เช่นเดียวกัน เนื่องจากกลไกการทำงานขึ้นอยู่กับปัจจัยภายนอก ซึ่ง shim จะเข้ามาช่วยตรงจุดนี้ Shim types จะให้กลไกการเปลี่ยนทิศทางการเรียกใช้ .NET method ไปยัง function ( หรือ user delegate) ที่เขียนขึ้น โดย shim types จะถูกสร้างโดย Fakes generator using (ShimsContext.Create() { ShimDateTime.NowGet = () => new DateTime(2016, 6, 1); var isIn = Utility.IsInFiscalYear(); Assert.AreEqual(true, isIn); } ShimDateTime คือ shim type ที่ถูกสร้างโดย Fakes generator เพื่อใช้ในการกำหนดกลไกการทำงานแทน DateTime.Now การเพิ่ม Fakes Assemblies ใน solution ทำได้โดย ใน solution explorer ขยาย References ของ unit test project เลือก assembly ที่มี class ที่ต้องการสร้าง shim type (จากตัวอย่างนี้ต้องการสร้าง shim type ของ DateTime ให้เลือก System.dll) click ขวา เลือก Add Fakes Assembly ในการใช้ shim type ใน unit test framework จะต้องเขียน test code อยู่ใน ShimsContext เพื่อควบคุม lifetime

Read More »

Auto remove schema in EDMX on build

Entity Framework (EF)  คือ data access technology ที่เริ่มเปิดตัวครั้งแรกเป็นส่วนหนึ่งของ .NET Framework 3.5 SP1 โดยตัว EF จะทำหน้าที่เป็น object-relational mapper ที่ทำให้ผู้พัฒนาไม่จำเป็นต้องเขียน code ในส่วน data access ก็สามารถใช้ข้อมูลจาก relational database โดยผ่าน object model การพัฒนาโปรแกรมโดยใช้ EF นั้นจำเป็นต้องมี Entity Data Model เป็น model ที่กำหนดรายละเอียดเกี่ยวกับ entity และ relationship ระหว่าง entity นั้นๆ การสร้าง Entity Data Model สามารถแยกออกเป็น 2 แนวทางคือ “Code First” เป็นการกำหนดรูปร่างของ model โดยการสร้าง class (เขียน code) จะมี database หรือไม่มีอยู่ก่อนก็ได้  และ “Database First” ที่จะทำการสร้าง model ( reverse engineer) จาก database ที่มีอยู่โดย EF Designer ซึ่ง model ที่ได้จะเก็บอยู่ใน EDMX file (.edmx) สามารถเปิดหรือแก้ไขเพิ่มเติมได้ด้วย EF Designer สำหรับ class ที่ใช้ในโปรแกรมจะถูกสร้างโดยอัตโนมัติจาก EDMX file ข้อมูล Entity Data Model ใน EDMX file อยู่ในรูปแบบ xml สามารถแบ่งออกเป็น 3 ส่วนคือ Storage model, Conceptual model และ Mapping ซึ่งในส่วนของ Storage model จะเป็นข้อมูลรายละเอียดของ entity จาก database เช่น ข้อมูล EntityType ที่ให้รายละเอียดของชื่อของ entity (table ใน database), ชื่อและประเภทของ property (column ของ table ใน database)  <EntityType Name=”VF_CONFIG_REPORT”> <Key> <PropertyRef Name=”ID” /> </Key> <Property Name=”ID” Type=”number” Precision=”38″ Scale=”0″ Nullable=”false” /> <Property Name=”REPORT_NAME” Type=”varchar2″ MaxLength=”512″ /> <Property Name=”REPORT_PATH” Type=”varchar2″ MaxLength=”512″ /> <Property Name=”GROUP_TYPE” Type=”number” Precision=”38″ Scale=”0″ /> <Property Name=”SIGN_NUM” Type=”number” Precision=”38″ Scale=”0″ /> <Property Name=”SIGNS” Type=”varchar2″ MaxLength=”128″ /> </EntityType> ข้อมูล EntitySet ที่ประกอบด้วย ชื่อ,ประเภทของ entity, schema และ query ที่ใช้ดึงข้อมูล <EntitySet Name=”VF_CONFIG_REPORT” EntityType=”Self.VF_CONFIG_REPORT” store:Type=”Views” store:Schema=”FINANCE”> <DefiningQuery> SELECT “VF_CONFIG_REPORT”.”ID” AS “ID”, “VF_CONFIG_REPORT”.”REPORT_NAME” AS “REPORT_NAME”, “VF_CONFIG_REPORT”.”REPORT_PATH” AS “REPORT_PATH”, “VF_CONFIG_REPORT”.”GROUP_TYPE” AS “GROUP_TYPE”, “VF_CONFIG_REPORT”.”SIGN_NUM” AS “SIGN_NUM”, “VF_CONFIG_REPORT”.”SIGNS”

Read More »

ทำความรู้จักและเรียนรู้การใช้งานเบื้องต้นกับ StringBuilder ใน .NET Framework(C#)

          โดยปกติแล้วนั้น ผู้พัฒนาโปรแกรมโดยใช้ .NET Framework มักจัดการข้อมูลที่เป็นอักษรหรือข้อความ (String) ด้วยคลาสของ String ที่มีใน .NET Framework ซึ่งประกอบไปด้วยฟังก์ชั่นหรือเมธอดที่หลากหลายที่ติดมากับตัวคลาส เพื่อเตรียมมาไว้ให้ใช้งาน และสามารถรองรับความต้องการในการจัดการข้อมูลของผู้ใช้แต่ละคน ซึ่งมีวิธีการใช้งานง่าย ไม่ยุ่งยากซับซ้อน มีมาตรฐานการใช้งานที่รู้จักโดยทั่วถึงกัน สะดวกและรวดเร็วทำให้ผู้พัฒนาสามารถเลือกวิธีจัดการข้อมูลได้อย่างมีประสิทธิภาพ อย่างไรก็ตาม แม้ว่าคลาสของ String จะมีเมธอดให้เราได้เลือกใช้กันอย่างมากมายและมีประสิทธิภาพอยู่แล้ว แต่ปัญหาอย่างหนึ่งที่พบในการใช้งานกับตัวแปรของคลาส String คือ การเชื่อมต่อหรือเปลี่ยนแปลงแก้ไขค่าข้อความของตัวแปรชนิด String ในแต่ละครั้ง จะไม่สามารถเปลี่ยนรูป หรือกลับไปแก้ไขค่าของตัวแปรบนพื้นที่หน่วยความจำเดิมที่ถูกจองไว้ให้กับตัวแปรได้ หรืออาจพูดในทางโปรแกรมแบบง่ายๆได้ว่า หากเราต้องการเปลี่ยนแปลงค่าของตัวแปรชนิด String เราจะไม่สามารถกลับไปแก้ไขค่าใน object ของตัวแปรที่ถูกสร้างขึ้นเดิมในหน่วยความจำ หรือ Memory ที่สร้างไว้ในตอนแรกได้ แต่จะมีการสร้าง object ตัวใหม่ขึ้นมา ทุกครั้งที่มีการแก้ไข/จัดการข้อมูลค่า หรือมีการใช้งานเมธอดในคลาส System.String และใช้วิธีให้ pointer ของตัวแปรชี้ไปยังตำแหน่งของ object ตัวใหม่ที่มีค่าของตัวแปรที่ถูกแก้ไขภายหลังแทน ซึ่งหากมีกรณีที่มีการเปลี่ยนแปลงค่าข้อมูล หรือเชื่อมต่อข้อความในตัวแปรดังกล่าวจำนวนหลายครั้ง หรือมีการวนลูปซ้ำในการเปลี่ยนแปลงค่าเป็นจำนวนมาก จะถือเป็นการใช้งานทรัพยากรหน่วยความจำอย่างสิ้นเปลือง เนื่องจาก object ของตัวแปรจะถูกสร้างขึ้นใหม่เรื่อยๆและมีการจองพื้นที่ให้กับ object ตัวที่ถูกสร้างขึ้นใหม่ตามจำนวนครั้งที่ทำการแก้ไขหรือเชื่อมต่อข้อความนั่นเอง ดังภาพ ภาพการจองพื้นที่ในหน่วยความจำของตัวแปรชนิด String [ที่มาของภาพ : http://www.tutorialsteacher.com/csharp/csharp-stringbuilder]                     จากภาพตัวอย่างจะเห็นได้ว่า เดิมทีมีการกำหนดค่าให้กับตัวแปรเป็นข้อความ “Hello World!!” แต่เมื่อมีการปรับแก้ค่าของตัวแปร จะมีการสร้าง object ตัวใหม่ โดยจะเก็บค่าที่มีการเปลี่ยนแปลงของข้อความไปเป็น “Hello World!! From Tutorials Teacher” และเลื่อนตำแหน่งของ pointer ของตัวแปรที่จะชี้ไปเพื่อให้ได้ค่าใหม่นั่นเอง           จากปัญหาดังกล่าว .NET Framework ก็ได้จัดเตรียมคลาสที่มีชื่อว่า “StringBuilder” ขึ้นมา ซึ่งเป็นคลาสที่ใช้ในการจัดการกับข้อมูลชนิดข้อความเช่นเดียวกับคลาส String โดยยินยอมให้มีการแก้ไขและปรับเปลี่ยนค่าในตัวแปรข้อความ(string) ดังกล่าวได้ใน object ตัวเดิมบนพื้นที่หน่วยความจำเดิม โดยไม่ต้องสร้าง object และทำการจองพื้นที่หน่วยความจำขึ้นใหม่ทุกครั้งที่มีการเปลี่ยนแปลงค่าของข้อความดังเช่นในคลาส String นั่นเอง ซึ่งจะทำให้สามารถประหยัดการใช้ทรัพยากรหน่วยความจำได้ในกรณีที่มีการเชื่อมต่อข้อความหรือเปลี่ยนแปลงค่าของตัวแปรจำนวนหลายครั้งได้  ภาพการจองพื้นที่ในหน่วยความจำของตัวแปรชนิด StringBuilder [ที่มาของภาพ : http://www.tutorialsteacher.com/csharp/csharp-stringbuilder]           ดังนั้น ในการจัดการข้อมูลที่เป็นตัวอักษร หรือข้อความ ผู้พัฒนาควรเลือกใช้วิธีการให้เหมาะสมกับประเภทและลักษณะการใช้งาน เพื่อให้การใช้งานบนพื้นที่หน่วยความจำ และทรัพยากรเกิดประสิทธิภาพสูงสุด ซึ่งในบทความนี้ ผู้เขียนจะขอพูดถึงวิธีการใช้งานในเบื้องต้นของการจัดการข้อมูลชนิด StringBuilder เพื่อเป็นอีกหนึ่งทางเลือกให้กับผู้พัฒนาต่อไป   หลักการทำงานและการจองพื้นที่ในหน่วยความจำของตัวแปรชนิด StringBuilder           โดยปกติแล้วนั้น ค่าของ “StringBuilder.Length” จะเป็นค่าของจำนวนตัวอักษรที่มีในตัวแปร object ของ StringBuilder และจะถูกเพิ่มขึ้นเรื่อยๆ เมื่อมีการเพิ่มตัวอักษรหรืออักขระเข้าไปในตัวแปรนั้นโดยไม่มีการจองพื้นที่หน่วยความจำเพิ่ม จนกว่าค่าของ Length เท่ากับจำนวนของความจุที่จองพื้นที่หน่วยความจำไว้ ซึ่งก็หมายถึงค่าของ “Capacity” นั่นเอง และหากการเพิ่มตัวอักษรดังกล่าวทำให้ค่าของ Length มากกว่าค่าของ Capacity ใน object นั้นๆ จะมีการจองพื้นที่หน่วยความจำเพิ่มเป็นเท่าตัว เช่น จากเดิม 16 ตัวอักษรจะถูกเพิ่มเป็น 32 ตัวอักษร โดยจะสามารถเปลี่ยนแปลงได้ไม่เกินค่าความจุสูงสุด หรือที่เรียกว่า “MaxCapacity” ซึ่งถ้าหากมีการเพิ่มตัวอักษรที่เกินค่าของ MaxCapacity แล้วนั้นจะทำให้เกิดข้อผิดพลาดได้ แต่หากไม่มีการกำหนดค่าให้กับ Capacity และ MaxCapacity แล้วนั้น ค่าตั้งต้นของ Capactity เริ่มต้นจะอยู่ที่ 16 ตัวอักษร และค่าของ MaxCapacity จะอยู่ที่ประมาณ 2 พันล้านตัวอักษร หรือเทียบเท่ากับค่าสูงสุดของ Int32.MaxValue นั่นเอง การอ้างอิง Namespace โดย Namespace ที่ต้องอ้างอิงเพิ่มเติมในการใช้งานคลาส StringBuilder มีดังนี้ using System; using System.Text; การประกาศตัวแปรของคลาส StringBuilder ในการประกาศตัวแปร object ของคลาส StringBuilder จะใช้หลักการเดียวกันกับการประกาศตัวแปร object ของคลาสโดยทั่วไป

Read More »