Thứ Tư, 7 tháng 8, 2013

ASP.NET MVC 4 & Web API

Hôm nay, ASP.NET MVC 4 Beta đã được phát hành, bản phát hành này có nhiều tính năng mới và nổi trội so với phiên bản ASP.NET MVC 4 Developer Preview, trong đó phải kể đến ASP.NET Web API.

Vào tháng 9/2011, tại hội nghị //BUILD/ chúng ta đã được giới thiệu về bản ASP.NET MVC 4 Developer Preview. Và hôm nay, ASP.NET MVC 4 Beta đã được phát hành, bản phát hành này có nhiều tính năng mới và nổi trội so với phiên bản ASP.NET MVC 4 Developer Preview, trong đó phải kể đến ASP.NET Web API.
Dưới đây là lời giới thiệu tổng quát về những cái mới của ASP.NET MVC 4 Beta và những tính năng nổi trội của ASP.NET MVC 4 nói chung:

ASP.NET Web API

Tính năng ASP.NET Web API trước đây được gọi là WCF Web API, nghĩa là WCF Web API đã được tích hợp vào ASP.NET, thay vì được xem là một thành phần của WCF, điều đó ít nhất cũng mang lại cho lập trình viên cảm giác thân thuộc và không phải sợ hãi khi nghe đến danh xưng WCF.
Vậy ASP.NET Web API là gì? Và tại sao dùng ASP.NET Web API?
ASP.NET MVC được thiết kể để phục vụ cho việc giao tiếp giữa người dùng và ứng dụng thông qua các trang web. Tình huống sử dụng chính là sản sinh ra các trang HTML và tương tác người dùng (như nhập dữ liệu, click chuột vào nút nhấn, link…) và rõ ràng là ASP.NET MVC làm rất tốt việc đó.
ASP.NET Web API được xây dựng cho phần còn lại, tức là những thứ không phải do người dùng tương tác. Ví dụ, như mã lệnh jQuery gởi đến một ajax request, hoặc một phần mềm trên smartphone cần lấy thông tin. Trong những trường hợp như vậy, các lời triệu gọi đến từ mã lệnh và yêu cầu dữ liệu có cấu trúc và có thể gởi thêm một số mã HTTP Status Codes.
Nói như vậy không có nghĩa là chúng ta không thể phục vụ các yêu cầu tượng tự bằng ASP.NET MVC, nhưng nó đòi hỏi lập trình viên phải làm nhiều việc hơn để mọi việc diễn ra suôn sẻ. ASP.NET Web API được tích hợp vào ASP.NET MVC đồng nghĩa với việc chúng ta vừa có thể xây dựng ứng dụng theo mô hình MVC vừa có thể cung cấp các HTTP Services thực sự.
ASP.NET Web API hỗ trợ các tính năng dưới đây:

·         Mô hình lập trình HTTP hiện đại: Truy xuất trực tiếp và khởi tạo các HTTP request và response bằng Web APIs sử dụng strongly typed HTTP object model. Có thể lập trình theo mô hình này ở phần client, bằng cách sử dụng kiểu HttpClient.
·         Hỗ trợ đấy đủ cho việc định tuyến: Web APIs hỗ trợ đầy đủ cho khả năng định tuyến, kể cả route parameters và các constraints. Hơn nữa, Web APIs còn hỡ trợ đấy đủ cho các HTTP Verbs (POST, GET, PUT, DELETE..) nên bạn sẽ không cần phải sử dụng các thuộc tính như là [HttpPost] cho các phương thức của bạn nữa.
·         Thương thảo về nội dung trả về: client và server có thể thảo thuận với nhau định dàng cần trả về từ một API. ASP.NET Web APIs hỗ trợ mặc định cho XML, JSON và định dạng Forrm URL-encoded, và bạn có thể mở rộng sự hỗ trợ này bằng cách định nghĩa các fortmatter của riêng bạn.
·         Model binding và validation: Model binders cung cấp cách thức giả nén dữ liệu từ các phần khác nhau của HTTP request và chuyển các phần nói trên thành .NET objects một cách dễ dàng bằng cách sử dụng các Web API actions.
·         Filters: Web APIs bây giờ đã hỗ trợ các bộ lọc, ví dụ như [Authorize].
·         Query composition: Chỉ cần trả về các IQueryable, bạn có thể truy vấn dữ liệu bằng cách sử dụng ODATA URL conventions.
·         Tăng cường khả năng kiểm thử các chi tiết HTTP:  bạn có thể làm việc với các đối tượng HttpRequestMessage, HttpResponseMessage đễ quy định các chi tiết của HTTP.
·         Cải thiện Inversion of Control (IoC) thông qua Dependency Resolver: Web API hiện nay đã sử dụng mẫu service locator pattern bằng cách sử dụng MVC dependency resolver để triệu gọi các đối tượng từ các lớp khác nhau.
·         Cấu hình dạng code-based (Code-based configuration): các thiệt lập cho Web API có thể thực hiện qua mã lệnh, và giúp cho tập tin cấu hình của bạn sạch sẽ hơn.
·         Self-host: Web APIs có thể được host trên tiến trình của bạn thay vì chỉ IIS mà vẫn tận dụng được tính năng định tuyến.
Dưới đây là giới thiệu sâu hơn về một số điểm đáng chú ý

Hỗ trợ định tuyến

Nếu như bạn đã từng sử dụng tính năng định tuyến trong ASP.NET, bạn sẽ thấy thoải mái và quen thuộc khi sử dụng ASP.NET Web API. Các tuyến được định nghĩa bên trong tập tin Global.asax. Trong một ứng dụng ASP.NET MVC nó sẽ như minh họa dưới đây:


routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);
 
 Một thay đổi nhỏ đó là ASP.NET Web API hỗ trợ các phương thức chuẩn của HTTP, do đó khi tạo một ApiController, nó sẽ như mã minh họa bên dưới:


public class ValuesController : ApiController
{
    // GET /api/values
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
 
    // GET /api/values/5
    public string Get(int id)
    {
        return "value";
    }
 
    // POST /api/values
    public void Post(string value)
    {
    }
 
    // PUT /api/values/5
    public void Put(int id, string value)
    {
    }
 
    // DELETE /api/values/5
    public void Delete(int id)
    {
    }
}
 
 Một request dạng GET sẽ được ánh xạ với Action Get, và bạn không cần phải làm gì thêm để quy định ánh xạ nữa.

Model Binding

Model Binding là tính năng thế mạnh của ASP.NET MVC (và bây giờ nó cũng được áp dụng cho Web Forms trong phiên bản ASP.NET 4.5). Nó giúp cho bạn viết phương thức nhận một đối tượng tùy biến như là một tham số, và bạn cũng có thể thực hiện điều đó với ASP.NET Web API. Model Binding sẽ giúp bạn tập trung vào việc cài đặt logic hơn là việc suy nghĩ làm cách nào để ánh xạ dữ liệu người dùng được đưa lên với các đối tượng .NET. Xem mã minh họa ở dưới đây:


public HttpResponseMessage PostComment(Comment comment) 
{
    comment = repository.Add(comment);
    var response = new HttpResponseMessage(comment, HttpStatusCode.Created);
    response.Headers.Location = new Uri(Request.RequestUri, "/api/comments/" + comment.ID.ToString());
    return response;
}
 

Filters

Filters là tính năng mạnh trong ASP.NET MVC. Bạn có thể dụng các thuộc tính để đưa các thủ tục xử lý trước và sau mỗi action, cả controller và có thể áp dụng với tất cả các action của ứng dụng. Filters cũng tồn tại trong ASP.NET API, và bạn có thể áp dụng nó như các áp dụng với các action trong ASP.NET MVC.

Tính năng Bundling được áp dụng mặc định

Một trong những tính năng rất hữu ích có từ bản developer preview đó là Bundling sẽ được áp dụng mặc định. Nội dung của thẻ ở _Layout.cshtml sẽ có dạng như mã đưới đây:


<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title - My ASP.NET MVC Application</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" rel="stylesheet" type="text/css" />
    <link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/themes/base/css")" rel="stylesheet" type="text/css" />
    <script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")"></script>
    <meta name="viewport" content="width=device-width" />
</head>
 
 Như vậy chúng ta sẽ không cần phải gọi các script hoặc file css riêng biệt, bởi vì tất cả các script được tham chiếu sẽ được đóng gói và nén lại.
Một trong như lợi ích của tính năng Bundling đó là việc phải tự tham chiếu các thư viện javascript. Ví dụ như, trong quá khứ, để cập nhật jQuery trong ASP.NET MVC, chúng ta phải thực hiện hai bước:
1.       Lấy phiên bản jQuery mới nhất từ NuGet.
2.       Tìm kiếm các tham chiếu đến thư viên jQuery cũ và cập nhật chúng lên phiên bản mới.
Với tính năng Bundling thì chúng ta chỉ cập nhật và lưu scripts trong thư mục /Scripts là xong và khỏi cần thực hiện bước 2.

Các cải tiến cho Razor

Một số cải tiến cho Razor (áp dụng luôn cho cả ASP.NET Web Pages 2)

URL Resolution – Hỗ trợ cú pháp ~/

Thay vì viết 


<script src="@Url.Content("~/Scripts/Site.js")"></script> 
 Bạn có thể viết:


<script src="~/Scripts/Site.js"></script> 
 Razor hiểu cú pháp ~/ và sẽ tự động phân tích và xử lý nó.

Render các thuộc tính điều kiện

Bạn có một thuộc tính có khả năng sẽ mang giá trị null, do đó bạn sẽ phải kiểm tra giá trị của thuộc tính như sau:


<
text>class="@myClass"</text> } }>Content</div>
 Bây giờ Razor sẽ thay bạn làm việc đó, và bạn chỉ cần viết như dưới đây:


<div class="@myClass">Content</div> 
 Nếu myClass là null thì kết quả khi render sẽ là:


<div>Content</div> 

Cài đặt ứng dụng theo dạng NuGet

Khi bạn tạo một ứng dụng ASP.NET MVC 4, bạn sẽ thấy rằng có nhiều packages từ NuGet được cài đặt. Đó là bởi vì mẫu dự án sử dụng tính năng phục hồi của NuGet. Trên thực tế thì ASP.NET MVC 4 cũng là một NuGet Packgake. Chính nhờ vậy mà bạn có thể dễ dàng lấy lại các thư viện NuGet mà không cần phải đưa các thư viện cần dùng lên source control (như Subversion, Git).

Cấu hình để có thể cài đặt ASP.NET MVC 4

Thành phần ASP.NET MVC 4 Beta cho Visual Studio yêu cầu phải có PowerShell 2.0 và VS2010 SP1 được cài đặt hoặc Visual Web Developer Express 2010 với bản SP1. Bản ASP.NET MVC 4 Beta không làm việc vởi bản Visual Studio 2011 Developer Preview.

Thứ Năm, 18 tháng 7, 2013

Singleton when multiple user access

Only providing one user access to a resource is not the purpose of a Singleton.  The Singleton pattern allows multiple users to share a single object.  

For example, say you had a complex program with many forms, but wanted your program to share a single data connection to a shared resource, so you weren't opening many connections.  You could use a singleton to allow every form within the application to access the same "Repository" instance for data.  In this case, a singleton would be a good option.

If you want to prevent multiple instances from using the same resource at the same time, you could modify your class to include some manual resource locking, preventing multiple simultaneous instances.  Here's an example:
using System;

public sealed class Singleton
{
    private class DispsoseHandle : IDisposable
    {
        public void Dispose()
         {
             lock(Singleton.lockObj)
             {
                 Singleton.available = true;
             }
         }
    }

    private static readonly Singleton sharedInstance = new Singleton();
    private static readonly object lockObj = new object();
    private static bool available = true;

    private Singleton()
    {
    }

    public IDisposable ResourceHandle
    {
        get
        {
            return new DispsoseHandle();
        }
    }

    // use a method instead, here
    public static bool TryGetInstance(out Singleton instance)
    {
        lock (lockObj)
        {
            if (available)
            {
                available = false;
                instance = sharedInstance;
                return true;
            }
            else
            {
                instance = null;
                return false;
            }
        }
    }
}
class Program 
{
        static void Main(string[] args)
        {
            Singleton instance;
            if (Singleton.TryGetInstance(out instance))
            {
                using (instance.ResourceHandle)
                {
                    // Do something with the singleton instance
                }
            }

            Console.ReadKey();
        }

}

Thứ Tư, 17 tháng 7, 2013

Phân biệt Interface và lớp Abstract trong OOP

 Interface vs Abstract class in OOP
Hiện nay mặc dù OOP (Object Oriented Programming) đã rất phổ biến nhưng đa số vẫn còn khá mơ hồ trong việc phân biệt và định nghĩa hai khái niệm lớp Interface và Abstract. Bài viết này chúng ta sẽ tìm hiểu kỹ hơn về khái niệm và sự khác biệt giữa chúng, lưu ý ở đây là Abstract Class chứ không phải là Abstract Method nhé!

 What is an Abstract Class?
Lớp trừu tượng đơn giản được xem như một class cha cho tất cả các Class có cùng bản chất. Do đó mỗi lớp dẫn xuất (lớp con) chỉ có thể kế thừa từ một lớp trừu tượng. Bên cạnh đó nó không cho phép tạo instance, nghĩa là sẽ không thể tạo được các đối tượng thuộc lớp đó.

 What is an Interface?
Lớp này được xem như một mặt nạ cho tất cả các Class cùng cách thức hoạt động nhưng có thể khác nhau về bản chất. Từ đó lớp dẫn xuất có thể kế thừa từ nhiều lớp Interface để bổ sung đầy đủ cách thức hoạt động của mình (đa kế thừa - Multiple inheritance).

Ví dụ:
- Abstract class ConVat có các lớp con Chim, Ca.
- Abstract class MayMoc có các lớp con MayBay, Thuyen
- Interface: iBay, iBoi, iChay.
=> MayBay, Chim sẽ có cùng Interface là iBay. Rõ ràng mặc dù MayBay, Chim có cùng cách thức hoạt động là bay nhưng chúng khác nhau về bản chất.
=> MayBay cũng có interface là iChay nhưng Chim không thể nào kế thừa thêm abstract classMayMoc

 Abstract Class vs Interface
 Nhìn chung cả 2 đều là "bản thiết kế" cho các lớp dẫn xuất, do đó chúng chỉ chứa các khai báo Properties và Method mà không quan tâm bên trong thực hiện những gì. Nhưng cụ thể thì Abstract Class là "bản thiết kế" cho Class còn Interface là "bản thiết kế" cho Method.
(Ở đây s dùng C# làm ngôn ngữ cho ví dụ)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//** Ví dụ 1
//** Abstract class
public abstract class Employee
    {
        //Khai báo Properties
        public abstract String ID
        {
            get;
            set;
        }
        //Khai báo Method
        public abstract String Add();
        public abstract String Update();
         
    }
}
//** Interface
public interface IEmployee
    {
        //Khai báo Properties
        String ID
        {
            get;
            set;
        }
        //Khai báo Method
        String Add();
        String Update();
         
    }
}
 Do được xem là bản thiết kế cho toàn Class, nên ngoài những khai báo Properties hoặc Method bắt buộc thì Abstarct class vẫn có thể chứa thêm các Method đã được triển khai hoặc các biến hằng. Ngược lại thì Interface hoàn toàn không thể làm được điều đó.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//** Ví dụ 2
//** Abstract class
public abstract class Employee
    {
        //Khai báo biến hằng (field and constant)
        public String id;
        public String name;
        //Khai báo Properties
        public abstract String ID
        {
            get;
            set;
        }
        //Khai báo Method
        protected abstract String Add();
         
        //Method đã triển khai không dùng abstract
        public String Update()
        {
            return "Update";
        }
    }
}
//** Interface
public interface IEmployee
    {
        //Khai báo Properties
        String ID
        {
            get;
            set;
        }
        //Khai báo Method
        String Add();
        String Update();
         
    }
}
 Toàn bộ những Method và Properties trong Interface không cần khai báo Access modifier vì mặc định là Public. Abstract class thì phải bắt buộc khai báo (Public, Protected) và bắt buộc có từ khóa abstract trong các Method và Properties được khai báo trừu tượng.
1
// Xem ví dụ 2
 Một điểm khác biệt nữa là ở lớp dẫn xuất của Interface class bắt buộc phải thực hiện toàn bộ những Method và Properties đã khai báo, ngược lại lớp dẫn xuất của Abstract class chỉ cần thực hiện những Method và Properties được khai báo trừu tượng (có từ khóa abstract)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//** Sử dụng Abstract class và Interface ở ví dụ 2
//** Lớp dẫn xuất Abstract class
 public class Employee1 : Employee
 {
    //Không cần khai báo lại biến hằng.
    //Triển khai Properties với từ khóa override
    public override String ID
    {
       get{ return id; }
       set{ id = value; }
    }
    //Triển khai Method với access modifier như ở Abstract class.
    protected override String Add()
    {
        return "Add";
    }
     
    //Không cần triển khai lại Update() mà chỉ việc sử dụng.
    // Phần triển khai của Employee1
    ...
 }
//** Lớp dẫn xuất Interface
 public class Employee1 : IEmployee
 {
     // Biến hằng được định nghĩa ở đây.
     protected String id;
     protected String name;
    // Triển khai Properties
    String ID
    {
       get{ return id; }
       set{ id = value; }
    }
    //Triển khai tất cả các Method có ở Interface
    public String Add()
    {
        return "Add";
    }
    public String Update()
    {
        return "Update";
    }
    // Phần triển khai của Employee1
    ...
     
 }
 Ở PHP, sự phân biệt này càng rõ ràng hơn với từ khóa implement cho Interface vàextend cho Abstract class. Thực vậy, lớp dẫn xuất của Abstract class chỉ là mở rộng (extend) còn Interface thì buộc là thực hiện (implement) tất cả.