Đỉnh NGUYỄN

life's a journey not a destination


Leave a comment

[VS2015] – Các tính năng mới trong Visual Studio 2015 Preview và VS2013 Update 4


ASP.NET 5 Preview runtime

Visual Studio hỗ trợ tạo và phát triển ASP.NET 5 Preview apps. ASP.NET 5 Preview là .NET stack xây dựng các ứng dụng web hiện đại cho cloud và on-premises server.

·         ASP.NET MVC và Web API được gom vào 1 mô hình lập trình đơn nhất.

·         Phát triển không cần biên dịch

·         Cấu hình môi trường cho các chuyển đổi đến cloud

·         Dependency injection out-of-the-box.

·         NuGet tất cả mọi thứ, thậm chí chính runtime của nó.

·         Chạy trong IIS, hoặc self-hosted trong tiến trình

·         Tất cả mã nguồn mở thông qua .NET Foundation, đóng góp trong GitHub.

·         ASP.NET 5 chạy trên Windows với .NET Framework hoặc .NET Core.

·         .NET Core là 1 runtime mới được tối ưu hóa cho cloud.

·         ASP.NET 5 chạy trên OS X và Linux với Mono runtime.

Visual Studio 2015 Preview gồm Beta1 runtime của ASP.NET 5.

Một số liên kết hữu ích để bắt đầu với ASP.NET 5 Preview.

·         Introduction: https://github.com/aspnet/Home

·         Documentation: https://github.com/aspnet/Home/wiki

·         Music Store Sample: https://github.com/aspnet/musicstore

ASP.NET 5 Preview tooling features

Để tối ưu hóa việc phát triển ASP.NET 5 Preview, xem các tính năng mới khi tạo project gồm các template mới, project system mới, combined IntelliSense hỗ trợ multi-framework targeting, và NuGet package manager mới.

Template

ASP.NET 5 Template

“ASP.NET 5 Empty” và “ASP.NET 5 Starter Web” template được thêm vào hộp thoại “New ASP.NET Project”.

clip_image001

“ASP.NET 5 Class Library” và “ASP.NET 5 Console Application” template được thêm vào “New Project” dialog dưới “Visual C#/Web”.

clip_image002

ASP.NET 5 Template dùng project structure mới

ASP.NET 5 project structure chứa tập tin cấu hình project.json, và tập tin project “.kproj”. ASP.NET 5 project template dùng project layout mới, tạo 1 project folder dưới <solutionFolder>\src, và dùng tập tin global.json để chỉ định project preference folder.

Global.json chứa “source”:[“src”], chỉ ra folder “src” làm parent folder của project reference. Mặc định, project-to-project preference lookup sẽ dùng parent directory, cộng với các thư mục được định nghĩa global.json. Ví dụ, chúng ta có solution structure và project.json dependency:

 

Solution1\global.json

Content: {" sources": ["src"] }

Solution1\src\WebApp1

Possible Dependencies: "ClassLib1 " : ""

Solution1\src\ClassLib1

Possible Dependencies: "WebApp1" : ""

Solution1\test\TestProj1

Possible Dependencies: "WebApp1" : "", "ClassLib1 " : "", "TestProj2 " : ""

Solution1\test\TestProj2

Possible Dependencies: "WebApp1" : "", "ClassLib1 " : "", "TestProj1 " : ""

 

 

ASP.NET 5 application template chứa target framework “aspnet50” và “aspnetcore50” được chỉ định trong project.json. Chúng hiển thị như “ASP.NET 5.0” và “ASP.NET Core 5.0” dưới Reference của solution explorer.

clip_image003

ASP.NET 5 web project template

ASP.NET 5 web project template chứa layout được tối ưu hóa cho cả static content và package restore từ NPMBower. Template đặt static content dưới wwwroot folder được xác định bởi thành phần webroot của project.json.

“ASP.NET 5 Starter Web” template chứa bower.json để dùng với Bower để lấy frontend package, package.json dùng với NPM để lấy Grunt, và gruntfile.js để quản lý task được định nghĩa bởi project.json script. File project.json của template chứa “postrestore” và “prepare” script để dùng NPM, cũng như Grunt và Bower để cài đặt các package cần thiết cho project trong khi build. Nó cũng dùng thành phần “packExclude” để định nghĩa các folder và file sẽ được excluded trong suốt “KPM pack”.

clip_image004

ASP.NET 5 Starter Web template và EF

ASP.NET 5 Starter Web template chứa code first migration cho Entity Framework 7.0.0-beta.

Bạn có thể dùng k command từ command line để thực hiện Entity Framework code first migration nếu bạn chỉ định “ef”:”EntityFramework.Commands” là 1 lệnh của project.json. Ví dụ:

“k ef migration” từ command line sẽ trả về:

 

Usage: ef migration [options] [command]

Options:

-h|–help Show help information

Commands:

add Add a new migration

apply Apply migrations to the database

list List the migrations

script Generate a SQL script from migrations

 

Sample commands:

 

k ef migration add MyMigrationWithOnly1ContextInCode

k ef migration add MyMigration –context MyContext

        k ef migration script –context MyContext

        k ef migration apply –context MyContext

 

“ASP.NET 5 Stater Web” template và command line scaffolding

Bạn có thể dùng command line scaffolding bởi vì “gen”:”Microsoft.Framework.CodeGeneration” được chỉ định là 1 thành phần của project.json.

Projects and Builds

Project file không còn gồm các project directory item và reference

ASP.NET 5 project dùng <projectName>.kproj làm tập tin project. File .kproj không gồm bất kỳ tập tin nào trong thư mục hiện tại hay các thư mục con.

Project.json được dùng định nghĩa project information

Visual Studio dùng tập tin project.json cho reference và package dependencies, version definition, framework configuration, compile option, build event, package creation meta-data, và run command,… Bằng cách này, project được chỉnh sửa để chạy trên Linux và Mac OS X mà không có Visual Studio.

Dependencies node cho Bower và NPM dependencies

Solution Explorer cho ASP.NET 5 Web Application có 1 Dependencies node để hiển thị Bower và NPM dependencies. Bower dependencies là từ bower.json trong project folder. NPM dependencies là từ package.json trong project folder.

Trong Dependencies node, dưới Bower và NPM node, bạn có thể uninstall 1 package thông qua context menu, nó sẽ được loại bỏ khỏi tập tin JSON.

clip_image005

References node hiển thị tất cả framework được định nghĩa trong project.json

Trong solution explorer, References node   hiển thị tất cả framework được định nghĩa trong project.json.

Project’s property page được dùng định nghĩa runtime info

Property Page dùng chỉ định KRE target version, debug target, và binary và NuGet package sẽ được tạo ra khi Visual Studio build.

clip_image006

clip_image007

clip_image008

Fast build time với Visual Studio

Visual Studio dùng Roslyn engine để biên dịch ASP.NET 5 project lúc design time. Vì thế project đã được biên dịch trước khi bạn dùng “build”. Trong Visual Studio 2015 Preview, Visual Studio đơn giản truyền các output của design time compiler đến build request. Điều này tránh việc chờ đợi build và tăng hiệu suất khi build, run, hoặc debug.

Hỗ trợ NuGet Package Manager

Visual Studio hỗ trợ NuGet Package Manager và NuGet Package Console.

Hỗ trợ xUnit test trong Text Explorer

Visual Studio hỗ trợ chạy và debug cho ASP.NET 5 xUnit test thông qua test explorer. Tất cả những gì cần làm là thêm xUnit dependencies và test command vào project.json như bên dưới (GHI CHÚ: để cài đặt xUnit package, cần phải thêm https://www.myget.org/F/aspnetvnext/api/v2 vào NuGet package source).

 

"dependencies": {

"Xunit.KRunner": "1.0.0-beta1"

},

"commands": {

"test": "Xunit.KRunner"

},

 

clip_image009

Từ command line, dùng k test để lấy running result, k.cmd là từ targeting hiện tại K Runtime Environment.

clip_image010

Hỗ trợ Task Runner Explorer

Task Runner Explorer được tích hợp vào Visual Studio, có thể enabled bằng cách chọn context menu của gruntfile.js trong Task Runner Explorer, hoặc thông qua menu View>Other Windows>Task Runner Explorer.

clip_image011

IntelliSense và Error list

IntelliSense có khả năng chỉ ra framework được hỗ trợ và không.

clip_image012

Build error hiển thị lỗi liên quan đến target framework

clip_image013

NuGet Package Manager

NuGet Package Manager được viết lại dùng tool window style và có thể được xem trên mỗi project và solution. Mỗi project có thể mở 1 NuGet Package Manager window tại 1 thời điểm.

clip_image014

(Theo www.asp.net)

Advertisements


Leave a comment

[ASP.NET MVC 5] – Thêm 1 Controller



Tutorials \ ASP.NET MVC 


Bắt đầu với ASP.NET MVC 5 

(Cập nhật: 30/11/2013) 

—————————————————————————————————————

MVC là viết tắt của Model-View-Controller. MVC là một kiến trúc lập trình giúp các nhà phát triển dễ dàng kiểm thử và duy trì ứng dụng. Ứng dụng dựa trên MVC chứa:

·         Models: Các lớp đại diện cho cấu trúc dữ liệu của ứng dụng và cũng được dùng để kiểm chứng các quy tắc nghiệp vụ của dữ liệu.

·         Views: Các tập tin mẫu dùng để tạo ra HTML động khi có yêu cầu từ người dùng.

·         Controllers: Các lớp tiếp nhận yêu cầu đầu vào từ trình duyệt, truy xuất dữ liệu dựa trên model và chỉ định các mẫu view sẽ được trả về cho trình duyệt.

Bắt đầu bằng cách tạo 1 lớp controller. Trong Solution Explorer, click phải lên thư mục Controller và chọn Add, sau đó chọn Controller.

clip_image001

Trong hộp thoại Add Scaffold, chọn MVC 5 Controller – Empty, và chọn Add.

clip_image002

Đặt tên controller là “HelloWorldController” và chọn Add.

clip_image003

Chú ý trong Solution Explorer có 1 tập tin mới được tạo ra tên HelloWorldController.cs và 1 thư mục mới tên Views\HelloWorld. Controller cũng được mở trong IDE.

clip_image005

Thay thế / chỉnh sửa nội dung tập tin như sau:

 

using System.Web;

using System.Web.Mvc;

 

namespace MvcMovie.Controllers

{

    public class HelloWorldController : Controller

    {

        //

        // GET: /HelloWorld/

 

        public string Index()

        {

            return "This is my <b>default</b> action…";

        }

 

        //

        // GET: /HelloWorld/Welcome/

 

        public string Welcome()

        {

            return "This is the Welcome action method…";

        }

    }

}

 

 

Các phương thức của controller sẽ trả về chuỗi HTML như trong ví dụ. Controller đặt tên là HelloWorldController và phương thức đầu tiên tiên tên Index. Chạy ứng dụng (nhấn F5 / Ctrl-F5). Trong trình duyệt, bổ sung / thay đổi đường dẫn trên thanh địa chỉ; bạn sẽ nhìn thấy hệ thống trả về 1 số HTML.

clip_image006

ASP.NET sẽ gọi các lớp controller khác (và các phương thức khác trong controller) phụ thuộc vào địa chỉ URL. Quy tắc định hướng URL mặc định được dùng bởi ASP.NET MVC có định dạng sau:

/[Controller]/[ActionName]/[Parameters]

Bạn thêm / thay đổi định dạng cho việc định hướng URL trong tập tin App_Start/RouteConfig.cs:

 

public static void RegisterRoutes(RouteCollection routes)

{

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 

    routes.MapRoute(

        name: "Default",

        url: "{controller}/{action}/{id}",

        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

    );

}

 

 

 

Khi bạn chạy ứng dụng mà không chỉ định controller cụ thể, nó mặc định sẽ là “Home” controller và “Index” action method.

Phần đầu tiên trong URL sẽ xác định lớp controller được thực thi. Vì thế /HelloWorld sẽ ánh xạ với lớp HelloWorldController. Phần thứ hai của URL xác định phương thức hành động của lớp controller. Vì thế /HelloWorld/Index sẽ gọi phương thức Index của controller “HelloWorldController”. Lưu ý rằng chúng ta chỉ cần chỉ định rõ /HelloWorld, còn Index là mặc định được sử dụng. Đây là bởi vì phương thức Index mặc định sẽ được gọi khi 1 controller được gọi. Phần thứ ba của URL (Parameters) được dùng định hướng dữ liệu. Chúng ta sẽ bàn đến sau.

Khi gọi URL: http://localhost:xxxx/HelloWorld/Welcome. Phương thức Welcome sẽ được gọi và trả về chuỗi “This is the Welcome action method…”. Quy tắc định hướng mặc định của MVC là /[Controller]/[ActionName]/[Parameters]. Đối với trường hợp URL này, controller là HelloWorld và hành động là Welcome.Chúng ta chưa dùng đến [Parameters] của URL và đây là tùy chọn.

clip_image008

Bây giờ hãy thay đổi ví dụ trên 1 chút để có thể truyền 1 vài thamsố  từ URL đến controller (ví dụ, /HelloWorld/Welcome?name=DinhNN&numtimes=3). Thay đổi phương thức Welcome như bên dưới. Lưu ý là đoạn code có dùng đặc tính gọi là tham số tùy chọn của C#, tham số numTimes mặc định sẽ có giá trị bằng 1 nếu không được truyền.

 

public string Welcome(string name, int numTimes = 1) {

     return HttpUtility.HtmlEncode("Hello " + name + ", NumTimes is: " + numTimes);

}

 

 

Lưu ý về bảo mật: Đoạn mã trên dùng HttpServerUtility.HtmlEncode để bảo vệ ứng dụng khỏi các đoạn dữ liệu nhập chứa mã nguy hiểm (như JavaScript). Thông tin thêm, xem How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

Chạy ứng dụng và thay đổi URL (http://localhost:xxxx/HelloWorld/Welcome?name=DinhNN&numTimes=4). Bạn có thể thử các giá trị khác cho name và numtimes trong URL.

clip_image009

Trong ví dụ trên, đoạn URL segment (Parameters) cũng không được dùng, name và numtimes được truyền theo dạng query strings.Dấu chấm hỏi (?) trong URL trên chỉ là đường phân cách, và chuỗi query strings theo sau nó. Ký tự & phân tách các thành phần trong chuỗi query strings.

Thay đổi phương thức Welcome như sau:

 

public string Welcome(string name, int ID = 1)

{

    return HttpUtility.HtmlEncode("Hello " + name + ", ID: " + ID);

}

 

 

Chạy ứng dụng và nhập URL: http://localhost:xxxx/HelloWorld/Welcome/3?name=Rick

clip_image010

Đây chính là URL segment (Parameters) ánh xạ tham số ID. Phương thức Welcome chứa tham số ID khớp với quy tắc URL được đăng ký trong phương thức RegisterRoutes.

 

public static void RegisterRoutes(RouteCollection routes)

{

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 

    routes.MapRoute(

        name: "Default",

        url: "{controller}/{action}/{id}",

        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

    );

}

 

 

Trong ứng dụng ASP.NET MVC, có nhiều cách để truyền tham số cho controller (giống như đã làm với ID) thay vì dùng như query strings. Bạn có thể thêm quy tắc định hướng cho name và numTimes trong tham số của URL. Trong tập tin App_Start\RouteConfig.cs, thêm định hướng “Hello”:

 

public class RouteConfig

{

    public static void RegisterRoutes(RouteCollection routes)

    {

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 

        routes.MapRoute(

            name: "Default",

            url: "{controller}/{action}/{id}",

            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

        );

 

        routes.MapRoute(

             name: "Hello",

             url: "{controller}/{action}/{name}/{id}"

         );

    }

}

 

 

Chạy ứng dụng và nhập đường dẫn URL: http://localhost:xxxx/HelloWorld/Welcome/Scott/3.

clip_image011

Với định hướng mặc định làm việc tốt. Bạn sẽ học cách truyền dữ liệu dùng model binder, và vì thế cũng không cần thiết thay đổi định hướng URL mặc định.

Trong ví dụ này, controller đã mô tả được hành động “VC” trong MVC – đó là view và controller cùng hoạt động. Controller trả về trực tiếp HTML. Thực tế, bạn sẽ cần các tập tin giao diện mẫu giúp hiển thị HTML. Hãy theo dõi bài học kế tiếp.


Leave a comment

[ASP.NET MVC 5] – Bắt đầu với ASP.NET MVC 5



Tutorials \ ASP.NET MVC

Bắt đầu với ASP.NET MVC 5

(Cập nhật: 30/11/2013)

———————————————————————————————————————-

Bắt đầu

Bắt đầu bằng cách cài đặt và chạy Visual Studio Express 2013 hoặc Visual Studio 2013.
Visual Studio là môi trường phát triển tích hợp (Integrated Development Environment – IDE). Giống như bạn dùng Microsoft Word để viết tài liệu, bạn sẽ dùng IDE để tạo ra ứng dụng và website.

Tạo ứng dụng đầu tiên

Chọn New Project từ trang Start hoặc dùng menu và chọn File > New Project.

 
 

Trong hộp thoại New Project, chọn Visual C# bên tay trái, sau đó chọn Web và chọn ASP.NET Web Application. Đặt tên dự án là "MvcMovie" và chọn OK.


Trong hộp thoại New ASP.NET Project, chọn MVC và chọn OK.

image 

Visual Studio sẽ dùng các mẫu dự án mặc định có sẵn để tạo dự án ASP.NET MVC.

image

Click F5 Visual Studio sẽ khởi động IIS Express và chạy ứng dụng web.Visual Studio sẽ mở trình duyệt và truy xuất trang chủ của ứng dụng. Lưu ý thanh địa chỉ của trình duyệt có dạng localhost:port#. Đó là bởi vì localhost là địa chỉ máy tính cục bộ đang chạy ứng dụng. Khi Visual Studio chạy ứng dụng web, một cổng (port) ngẫu nhiên được dùng cho web server.

image 

Dùng chuột kéo các góc để thu gọn vùng hiển thị của trình duyệt. Các liên kết Home, About và Contact sẽ không hiển thị, phụ thuộc vào kích thước cửa sổ trình duyệt mà bạn nhìn thấy các liên kết Home, About, Contact hoặc phải click vào icon để nhìn thấy các liên kết.

image

image

Ứng dụng cũng hỗ trợ việc đăng ký và đăng nhập. Bước tiếp theo là xem cách hoạt động của ứng dụng và học một ít về ASP.NET MVC.


Leave a comment

ViewData, ViewBag và TempData – các tùy chọn truyền dữ liệu trong ASP.NET MVC


ASP.NET MVC cung cấp 3 tùy chọn ViewData, ViewBag và TempData để truyền dữ liệu từ controller vào view và trong request kế tiếp. ViewData và ViewBag tương tự như nhau, TempData thực hiện thêm nhiệm vụ. Chúng ta sẽ nói về điểm chính của 3 đối tượng:

Sự giống nhau giữa ViewBag và ViewData:

1. Giúp duy trì dữ liệu khi bạn di chuyển từ view vào controller

2. Được dùng để truyền dữ liệu từ controller vào view tương ứng

3. Chu kỳ tồn tại ngắn, giá trị sẽ thành null khi redirect xuất hiện. Đây là bởi vì mục tiêu thiết kế các đối tượng này là để giao tiếp giữa controller và view

Sự khác nhau giữa ViewBag và ViewData:

1. ViewData là 1 từ điển các đối tượng (dictionary) kế thừa từ lớp ViewDataDictionary và có thể truy cập dùng chuỗi key.

2. ViewBag là thuộc tính động (dynamic) mang đến thuận lợi từ đặc tính mới của C# 4.0

3. ViewData yêu cầu chuyển kiểu với các kiểu dữ liệu phức tạp và kiểm tra giá trị null để tránh lỗi

4. ViewBag không yêu cầu chuyển kiểu với các kiểu dữ liệu phức tạp

Ví dụ về ViewBag và ViewData:

public ActionResult Index()
{
    ViewBag.Name = "Ngoc Dinh NGUYEN";
    return View();
}
public ActionResult Index()
{
    ViewData["Name"] = "Ngoc Dinh NGUYEN";
    return View();
} 

 

Trong View:

@ViewBag.Name 
@ViewData["Name"]

TempData:

TempData cũng là 1 từ điển đối tượng (dictionary) kế thừa từ lớp TempDataDictionary, được lưu trong 1 chu kỳ rất ngắn. Điểm khác biệt chính là chu kỳ sống của đối tượng. TempData giữ thông tin trong khoảng thời gian HTTP Request. Điều này có nghĩa là chỉ từ 1 trang đến 1 trang khác. Điều này cũng hoạt động với 302/303 redirection bởi vì nó cùng HTTP Request. Giúp duy trì dữ liệu khi bạn di chuyển từ 1 controller sang 1 controller khác hoặc từ hành động này sang hành động khác. Nói cách khác, khi bạn redirect, TempData giúp duy trì dữ liệu giữa các redirect. Nó là biến cục bộ dùng trong session. Nó yêu cầu chuyển kiểu cho các kiểu dữ liệu phức tạp, và kiểm tra giá trị null để tránh lỗi. Thông thường nó dùng để lưu error message hoặc validation message.

public ActionResult Index()
{
    var model = new Review()
                {
                    Body = "Start",
                    Rating = 5
                };
    TempData["ModelName"] = model;
    return RedirectToAction("About");
}

public ActionResult About()
{
    var model = TempData["ModelName"];
    return View(model);
}

 


Leave a comment

JUICE UI – Các điều khiển jQuery UI cho ASP.NET WebForms


Juice UI là dự án mã nguồn mở gồm tập các thành phần (các điều khiển) ASP.NET dựa trên jQuery UI giúp tăng tính tương tác và dễ lập trình cho giao diện ứng dụng web.

– Xem trang demo các điều khiển jQuery UI: http://jqueryui.com/demos/

– Xem trang demo các điều khiển Juice UI: http://juiceui.com/controls/

Bạn có thể dùng Juice UI dựa trên thỏa thuận giấy phép nguồn mở MIT License hoặc GNU General Public License (GPL) Version 2.

Tải về Juice UI bằng 2 cách:

– NuGet: http://nuget.org/packages/JuiceUI

– GitHub: https://github.com/appendto/juiceui

image


Leave a comment

Ủy nhiệm (Event Delegation) trong ASP.NET : Phát sinh sự kiện từ User Control đến Parent Page


Delegate là gì? MọI ngườI thường hay gặp câu hỏI này khi còn ngồI trên ghế nhà trường và trong các cuộc phỏng vấn; câu trả lờI phổ biến là con trỏ hàm (function pointer). Trong phát triển Web, đây là kỹ thuật phổ biến để giao tiếp giữa các thành phần của Web (bản thân các hàm sự kiện của các controls được xây dựng sẵn trong ASP.NET đều dùng kỹ thuật này).

Ví dụ vớI 1 trang .ASPX và 1 User Control. User Control có 1 Button và khi click vào button này sẽ gọI 1 hàm trên trang .ASPX dùng delegate.

User Control:

C#

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Widget.ascx.cs" Inherits="Widget" %>

<asp:Button ID="btnTest" runat="server" 
    Text="I am Inside User Control" OnClick="btnTest_Click" />

Trên Widget.aspx.cs, viết xử lý sự kiện Delegate như sau:

Code-Behind

using System;

public partial class Widget : System.Web.UI.UserControl
{
    // Delegate declaration 
    public delegate void OnButtonClick(string strValue);
    // Event declaration 
    public event OnButtonClick btnHandler;
    
    // Page load 
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    
    protected void btnTest_Click(object sender, EventArgs e)
    {
        // Check if event is null 
        if (btnHandler != null)
            btnHandler(string.Empty);
        // Write some text to output 
        Response.Write("User Control’s Button Click <BR/>");
    }

}

Đoan code trên kiểm tra btnHandler khác null, phát sinh sự kiện bằng cách truyền đốI số

Trang .ASPX

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%@ Register Src="~/Widget.ascx" TagName="Widget" TagPrefix="uc1" %>

<!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">
    <div>
        <asp:Label ID="lblText" Text="I am On Main Page : " runat="server" />
        <asp:DropDownList ID="ddlTemp" runat="server">
            <asp:ListItem>Google</asp:ListItem>
            <asp:ListItem>Microsoft</asp:ListItem>
            <asp:ListItem>Apple</asp:ListItem>
        </asp:DropDownList>
        <br />
        <br />
        <uc1:Widget ID="Widget1" runat="server" />
    </div>
    </form>
</body>
</html>

Code-Behind

using System;

public partial class _Default : System.Web.UI.Page
{

    protected void Page_Load(object sender, EventArgs e)
    {
        // Declare and Define Event of User Control. When User Clicks on button 
        //(which is inside UserControl) 
        // below event is raised as I have called raised that event on Button Click 
        Widget1.btnHandler += new
            Widget.OnButtonClick(WebUserControl1_btnHandler);
    }

    void WebUserControl1_btnHandler(string strValue)
    {
        Response.Write("Main Page Event<BR/>Selected Value: " +
                    ddlTemp.SelectedItem.Text + "<BR/>");
    }

}


Leave a comment

Các tập tin temp của ASP.NET được lưu ở đâu?


Trước giờ tôi cũng không mấy khi quan tâm đến việc ASP.NET lưu trữ các tập tin tạm (temp) ở đâu. Gần đây tôi phát hiện ASP.NET cung cấp thuộc tính HttpRuntime.CodeGenDir cho phép xác định đường dẫn vật lý đến thư mục mà ASP.NET dùng lưu các tập tin temp (các tập tin mã nguồn được biên dịch, resources, …).

protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write(HttpRuntime.CodegenDir);
        }

image

Chạy trang web trên máy tôi, output như sau:

C:\Users\DinhNN\AppData\Local\Temp\Temporary ASP.NET Files\root\b399a079\3f506e15


Leave a comment

Kiểm tra Email trong ASP.NET không dùng Mail Server


Tôi muốn chia sẽ một kỹ thuật mà có thể nhiều lập trình viên chưa biết. Giả sử bạn tạo ứng dụng và cần kiểm tra module gởi mail ra với số lượng lớn. như Newsletter chẵn hạn. Ý nghĩ đầu tiên sẽ là cấu hình SMTP server để kiểm tra. Tuy nhiên có một thủ thuật bạn có thể dùng để kiểm tra.

Thiết lập web.config như sau:

<system.net>
  <mailSettings>
    <smtp deliveryMethod="SpecifiedPickupDirectory">
      <specifiedPickupDirectory pickupDirectoryLocation="C:\Mails\"/>
    </smtp>
  </mailSettings>
</system.net>

Thuộc tính specifiedPickupDirectory cấu hình thư mục cục bộ cho Simple Mail Transport Protocol (SMTP) server. Thuộc tính pickupDirectoryLocation là thư mục chứa các e-mail được lưu bởi ứng dụng sau khi được xử lý bởi SMTP server. Chắc rằng thư mục này tồn tại trước khi dùng nó.

Được rồi,. Kiểm tra như đoạn mã sau:

protected void btnMail_Click(object sender, EventArgs e)
{
    MailMessage message = new MailMessage("abc@somedomain.com", "abc@abcdefgh.com",
         "Newsletter", "This is a test mail");
     SmtpClient client = new SmtpClient();
     client.Send(message);
}

Chạy ứng dụng và nhấn nút Send. RồI sau đó mở thư mục Mails trong phân vùng C và bạn sẽ nhìn thấy e-mail test ở đây. Cũng giống như bạn có thể kiểm tra module Newsletter mà không cần gởi mail đến một địa chỉ thật sự.

image

Thật tuyệt, nhưng chỉ với và chắc rằng bạn đang dùng IIS, thêm nữa, bạn phải có quyền read-write trên thư mục này.


Leave a comment

Quan trọng: Lỗ hổng bảo mật ASP.NET


Ngày 17/09/2010, Microsoft Security Advisory đăng tải về lỗ hổng bảo mật trong ASP.NET. Lỗ hỏng này tồn tại và ảnh hưởng đến tất cả phiên bản ASP.NET. Lỗ hổng này đã được công bố công khai vào cuối thứ sáu tại một hội nghị bảo mật. Microsoft đề nghị tất cả khách hàng ngay lập tức áp dụng một workaround (được mô tả bên dưới) để ngăn kẻ tấn công dùng lổ hổng này tất công các ứng dụng ASP.NET của bạn.

Lỗ hổng này cho phép những gì

Kẻ tấn công khai thách lỗ hổng này để gởi yêu cầu (request) và tải tập tin trong ứng dụng ASP.NET như tập tin web.config (thường chứa dữ liệu quan trọng).

Kẻ tấn công khai thác lỗ hổng này có thể giải mã (decrypt) dữ liệu được gởi tới trình duyệt trong trạng thái mã hóa (như dữ liệu ViewState trong trang).

Lỗ hổng này hoạt động như thế nào

Để hiểu lỗ hổng này hoạt động thế nào, bạn cần biết về lý thuyết mã hóa.

Cách cô lập (workaround) lỗ hổng?

Bạn có thể ngăn chặn bị khai thác lỗ hổng bằng cách bật thẻ <customErrors>, cấu hình rõ ứng dụng luôn trả về cùng một trang lỗi – dù bất kỳ lỗi gì xảy ra trên máy chủ web. Bằng cách điều hướng tất cả các trang lỗi về một trang lỗi đơn duy nhất, bạn ngăn chặn kẻ tất công phân biết giữa các dạng lỗi khác nhau xuất hiện trên máy chủ.

Quan trọng: Bậc tính năng CustomErrors hoặc RemoteOnly là chưa đủ. Bạn cần chắc rằng tất cả các lỗi được cấu hình để trả về cùng một trang lỗi. Điều này đòi hỏi bạn phải thiết lập rõ thuộc tính defaultRedirect trong thẻ <customErrors> và đảm bảo rằng không có mã tình trạng lỗi được thiết lập (status-code).

Cách cô lập lỗ hổng trên ASP.NET v1.0 đến v3.5

Nếu bạn dùng ASP.NET 1.0, ASP.NET 1.1, ASP.NET 2.0, hoặc ASP.NET 3.5, bạn phải làm theo các bước sau để bật tính năng <customErrors> và điều hướng tất cả lỗi vào một trang đơn:

1) Sửa tập tin web.config ở thư mục gốc Web site, tạo nếu nó không tồn tại.

2) Tạo hoặc sửa thẻ <customErrors> của tập tin web.config như sau:

<?xml version="1.0"?>
<configuration>
    <system.web>
      <customErrors mode="On" defaultRedirect="~/error.html" />
    </system.web>
</configuration>

3) Bạn có thể thêm tập tin error.html để ứng dụng chứa thông báo lỗi phù hợp mà bạn chọn (nội dung bạn thích). Tập tin này sẽ xuất hiện bất cứ khi nào có lỗi trong ứng dụng.

Lưu ý: Điều quan trọng là thẻ customErrors được thiết lập là On, và tất cả các lỗi sẽ được điều hướng về trang chỉ ra bởi thuộc tính defaultRedirect. Không có bất kỳ mã trạng thái lỗi (status-code) nào được định nghĩa – nghĩa là không có thẻ <error> trong thẻ <customErrors>. Điều này tránh kẻ tấn công phân biệt được tại sao một lỗi xảy ra tại máy chủ và ngăn dữ liệu lỗi được công khai.

Cách cô lập lỗ hổng trên ASP.NET v.35 SP1 và v4.0

Nếu bạn dùng ASP.NET v3.5 SP1 hoặc ASP.NET v4.0, bạn phải làm theo các bước sau để bật tính năng <customErrors> và điều hướng tất cả lỗi vào một trang đơn:

1) Sửa tập tin web.config ở thư mục gốc Web site, tạo nếu nó không tồn tại.

2) Tạo hoặc sửa thẻ <customErrors> của tập tin web.config như bên dưới. Chú ý thuộc tính redirectMode=”ResponseWrite” trong ASP.NET v3.5 và ASP.NET v4.0

<?xml version="1.0"?>
<configuration>
    <system.web>
      <customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/error.aspx" />
    </system.web>
</configuration>

3) Bạn có thể thêm tập tin error.aspx để ứng dụng chứa thông báo lỗi phù hợp mà bạn chọn (nội dung bạn thích). Tập tin này sẽ xuấthiện bất cứ khi nào có lỗi trong ứng dụng.

4) Bạn nên thêm đoạn mã sau trong sự kiện Page_Load() xảy ra phía máy chủ trong trang error.aspx để tạo thời gian hoãn (delay) nhỏ, ngẩu nhiên. Điều này sẽ giúp xáo trộn lỗi.

<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Import Namespace="System.Security.Cryptography" %>
<%@ Import Namespace="System.Threading" %>

<script runat="server">
   void Page_Load() {
      byte[] delay = new byte[1];
      RandomNumberGenerator prng = new RNGCryptoServiceProvider();

      prng.GetBytes(delay);
      Thread.Sleep((int)delay[0]);
        
      IDisposable disposable = prng as IDisposable;
      if (disposable != null) { disposable.Dispose(); }
    }
</script>

<html>
<head id="Head1" runat="server">
    <title>Error</title>
</head>
<body>
    <div>
        An error occurred while processing your request.
    </div>
</body>
</html>

Cách xác định lỗ hổng đã bị cô lập

Một khi bạn đã áp dụng các cách cô lập lỗ hổng, bạn có thể kiểm tra để chắc rằng thẻ <customErrors> được cấu hình đúng bằng cách yêu cầu (request) một URL trông như sau:

http://mysite.com/pagethatdoesnotexist.aspx

Nếu bạn nhìn thấy trang lỗi (error.html hoặc error.aspx) xuất hiện (bởi vì trang bạn yêu cầu không tồn tại) thì chứng minh bạn đã cấu hình đúng. Nếu như bạn nhìn thấy trang lỗi ASP.NET thì bạn đã sai một trong các bước trên. Để xem thông tin nguyên nhân của vấn đề, bạn có thể thử thiết lập thẻ <customErrors mode=”remoteOnly”> – cho phép xem thông tin lỗi ASP.NET khi bạn yêu cầu Web site từ máy cục bộ.

Cách tìm lỗ hổng trong ứng dụng ASP.NET trên máy chủ Web

Microsoft đã tạo ra đoạn mã Visual Basic for Application (.vbs) mà bạn có thể chạy trên máy chủ Web để xác định ứng dụng ASP.NET nào được cài đặt, hoặc thẻ <customErrors> bật hay tắt, hoặc các thông tin lỗi khác nhau tùy theo mã trạng thái.

Bạn có thể tải đoạn mã .vbs tại đây. Mở cửa sổ command prompt với tài khoản admin và chạy “cscript DetectCustomErrors.vbs”. Nó sẽ quét qua tất cả ứng dụng trong máy chủ Web và xác định cấu hình <customErrors> có được thiết lập đúng.

image

Nó sẽ đánh dấu bất kỳ ứng dụng ASP.NET nào mà không có thẻ <customErrors> trong tập tin web.config ở thư mục gốc hoặc chưa cấu hình đúng cách cô lập lỗ hổng để tránh bị tấn công. Nó sẽ in ra chứ “ok” với mỗi ứng dụng thỏa. Hy vọng sẽ sớm giúp bạn xác định vấn đề.

Lưu ý: Microsoft chỉ phát triển đoạn mã này trong thời gian ngắn, và có thể sẽ cập nhật thay đổi trong tương lai. Hãy luôn quay trở lại để xem các bản cập nhật thay đổi.

Cách tìm thêm thông tin về lỗ hổng

Bạn có thể tìm thêm nhiều thông tin về lỗ hổng tại

Diễn đàn thảo luận

Microsoft đã tạo ra một góc thảo luận về lỗ hổng trên trang www.asp.net giúp thảo thuật và tìm câu trả lời cho các câu hỏi liên quan đến lỗ hổng.

Tổng kết

Microsoft đã đăng tải chi tiết thông tin lỗi, và cũng sẽ phát hành bản vá để khắc phục lỗ hổng này (tránh phải cô lập lỗ hổng một cách thủ công như trên).


2 Comments

Thiết kế cơ sở dữ liệu đa ngôn ngữ


Bài viết này dựa trên kinh nghiệm cá nhân và không hẳn là cách tốt nhất

Xây dựng website đa ngôn ngữ có nhiều vấn đề, 1 trong số đó là cách lưu trữ nội dung trong csdl cho từng ngôn ngữ

1. Hướng tiếp cận dạng cột

Cách này phổ biến, cơ bản là tạo ra nhiều cột lưu trữ nội dung từng ngôn ngữ

table pages

— id (uniqueidentified)

— title_vi (nvarchar)

— title_en (nvarchar)

— content_vi (ntext)

— content_en (ntext)

Cách này truy vấn bằng cách tự động chọn các cột theo ngôn ngữ

SELECT id, title_vi AS title, content_vi AS content FROM pages

Hoặc có thể chọn tất cả các cột và lấy đúng cột theo ngôn ngữ

string title = (string)dataReader["title_" + Session["currentLanguage"]];

Thuận lợi

– Nó không trùng thông tin vì chĩ có 1 dòng cho mỗi mẫu tin và chỉ có các cột ngôn ngữ được nhân bản

– Dễ cài đặt

Bất lợi

– Khó duy trì. Dù dễ dàng với 2-3 ngôn ngữ nhưng không thích hợp khi có nhiều ngôn ngữ hoặc nhiều cột

– Khó thêm ngôn ngữ mới

2. Hướng tiếp cận nhiều dòng

Tương tự như cách ở trên, cách này tạo ra nhiều dòng thay vì nhân bản các cột theo ngôn ngữ

table pages

— id (uniqueidentified)

— language_id (smallint)

— title (nvarchar)

— content (nvarchar)

Cách này sẽ có 3 dòng cho cùng 1 trang nếu có 3 ngôn ngữ

Thuận lợi

– Dễ thêm ngôn ngữ mới

Bất lợi

– Nhiều nội dung trùng tại các cột chứa nội dung chung không cần chuyển ngữ

3. Hướng tiếp cận dạng bảng

Cách này phức tạp hơn 2 cách trên, nhưng thích hợp cho website động, có nhiều ngôn ngữ và có ý định thêm ngôn ngữ mới dễ dàng

table languages

— id (smallint)

— name (nvarchar)

table pages

— id (uniqueidentified)

— language_id (smallint)

— title (int fk)

— content (int fk)

table translation

— id (uniqueidentified)

table translation_entry

— translation_id (uniqueidentified)

— language_id (smallint)

— content (ntext)

Thuận lợi

– Dễ dàng thêm ngôn ngữ mới

Bất lợi

– Truy vấn nhiều bảng để lấy được nội dung

– Tất cả nội dung chuyển ngữ nằm cùng bảng

– Trông hơi khó làm việc và duy trì

4. Hướng tiếp cận dạng bảng 2

Đây là 1 biến thể của cách tiếp cận trên để dễ dàng làm việc và duy trì

Thay vì chỉ có 1 bảng dùng chuyển ngữ cho tất cả các bảng khác, bây giờ sẽ có 1 bảng dùng chuyển ngữ tưng ứng với 1 bảng. Di chuyển các cột cần chuyễn ngữ sang bảng dùng chuyển ngữ, còn lại các cột dùng chung (các cột không cần chuyển ngữ)

table languages

— id (smallint)

— name (nvarchar)

table pages

— id (uniqueidentified)

table pages_translation

— id (uniqueidentified)

— page_id (uniqueidentified)

— language_id (smallint)

— title (nvarchar)

— content (ntext)

SELECT * FROM pages JOIN pages_translation ON pages.id = pages_translation.page_id WHERE languages_id='1'

Thuận lợi

– Dễ thêm ngôn ngữ mới

– Dễ truy vấn

– Tên các cột được giữ nguyên

Bất lợi

– Tạo ra nhiều bảng chuyển ngữ tương ứng với các bảng

Kết luận

Chắc chắn có nhiều phương pháp khác nhau tạo nên website đa ngôn ngữ. Các giải pháp trên là ý kiến dựa vào kinh nghiệm cá nhân và cũng là phù hợp với các website đang làm

Dạng chuẫn khi thiết kế csdl vẫn chưa được bàn đến trong các phương pháp trên, sẽ có 1 bài viết như thế.

Cuối cùng, phương pháp tốt nhất là phương pháp phù hợp nhất với từng website, phù hợp nhất với cách làm việc và duy trì của bạn

Nếu bạn có hoặc tìm thấy cách nào khác, vui lòng chia sẽ với tôi và mọi người!

Tham khảo thêm

http://www.ibm.com/developerworks/web/library/wa-dbdsgn2.html

http://stackoverflow.com/questions/929410/what-is-best-practices-for-multilanguage-database-design