Mã hóa chuỗi kết nối vào webconfig trong Nhibernate


Thông thường khi sử dụng Nhibernate để phát triển ứng dụng web hay ứng dụng winform chúng ta thường bỏ chuỗi kết nối ở file hibernate.cfg.xml , mình thấy bỏ thế nào không an toàn nên sau khi google với tìm hiểu mình đã tìm ra cách để bỏ vào webconfig và mã hóa chuỗi kết nối này cho nó an toàn nhằm tránh shell 爆笑

Thông thường thì chuỗi kết nối cơ sở dữ liệu thường bỏ ở file hibernate.cfg.xml như sau :

<property name="connection.connection_string">
      Chuỗi kết nối cơ sở dữ liệu ở đây

    </property>

Để mã hóa chuỗi kết nối ta viết một lớp là Crypto để mã hóa và giải mã trước đã

public static class Crypto
   {
       const string InitialVector = "4AQYuEmZ3Q7gNHdj";       
       public static string Encrypt(string data,string pass)
       {
           if (string.IsNullOrEmpty(data)) return "";

           var initialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
           var plainTextBytes = Encoding.UTF8.GetBytes(data);
           var keyBytes = Encoding.ASCII.GetBytes(pass);

           var symmetricKey = new RijndaelManaged();
           symmetricKey.Mode = CipherMode.CBC;
           byte[] cipherTextBytes = null;
           using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, initialVectorBytes))
           {
               using (var memStream = new MemoryStream())
               {
                   using (var cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write))
                   {
                       cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                       cryptoStream.FlushFinalBlock();
                       cipherTextBytes = memStream.ToArray();
                       memStream.Close();
                       cryptoStream.Close();
                   }
               }
           }
           symmetricKey.Clear();
           return Convert.ToBase64String(cipherTextBytes);         
       }     
       public static string Decrypt(string data,pass)
       {
           if (string.IsNullOrEmpty(data)) return "";

           var initialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
           var cipherTextBytes = Convert.FromBase64String(data);
           var keyBytes = Encoding.ASCII.GetBytes(pass);

           var symmetricKey = new RijndaelManaged();
           symmetricKey.Mode = CipherMode.CBC;
           var plainTextBytes = new byte[cipherTextBytes.Length];
           var byteCount = 0;
           using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, initialVectorBytes))
           {
               using (var memStream = new MemoryStream(cipherTextBytes))
               {
                   using (var cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read))
                   {
                       byteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                       memStream.Close();
                       cryptoStream.Close();
                   }
               }
           }
           symmetricKey.Clear();
           return Encoding.UTF8.GetString(plainTextBytes, 0, byteCount);           
       }    
   }

Mục đích của lớp này là mã hóa theo pass và giải mã theo pass một chuỗi, mục đích là mã hóa chuỗi kết nối.

Để sửa lại phương thức lấy chuỗi kết nối ta override lại lớp NHibernate.Connection.DriverConnectionProvider như sau :

public class MyConnectionProvider : NHibernate.Connection.DriverConnectionProvider
    {
        static string conn = "";
        protected override string ConnectionString
        {
            get
            {
                if (string.IsNullOrEmpty(conn))
                {

                    string connectionString = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
                    conn= Crypto.Decrypt(connectionString,"sokhanh03");
                }
                return conn;
            }
        }       
       
    }

Sửa file hibernate.cfg.xml như sau :

<property name="connection.provider">
      (Name space của MyConnectionProvider).MyConnectionProvider,Name space của MyConnectionProvider
      <!–NHibernate.Connection.DriverConnectionProvider–>
    </property>

Chú ý comment lại dòng NHibernate.Connection.DriverConnectionProvider

Sau đó vào file webconfig hay app.config sửa lại thành :

<connectionStrings>
        <add name="ApplicationServices" connectionString="Chuỗi kết nối đã mã hóa với pass là sokhanh03" providerName="System.Data.SqlClient"/>
    </connectionStrings>

Như vậy ta đã chuyển chuỗi kết nối từ file hibernate.cfg.xml sang file webconfig(app.config) đã mã hóa, sau đó tiến hành code bình thường.

Mục đích của việt này là tránh việc bị shell đọc file webconfig và lấy chuỗi kết nối

Chúc các bạn thành công!

Nếu vẫn không làm được vui lòng comment lại ở đây mình sẽ support cho 爆笑

Advertisements

Phân trang trong Nhibernate


Đây là lớp giúp phân trang trong Nhibernate với Lớp T

public abstract class Paging<T>
   {
      public IList<T> GetPagedData(int page, int pageSize, out long count, Order oder, params ICriterion[] criterion)
      {
          IMultiCriteria multiCriteria  = NHibernateHelper.CurrentSession.CreateMultiCriteria();
          ICriteria criteria1 = NHibernateHelper.CurrentSession.CreateCriteria(typeof(T));
          ICriteria criteria2 =
              NHibernateHelper.CurrentSession.CreateCriteria(typeof (T));//.SetProjection(Projections.RowCountInt64());
          foreach (var item in criterion)
          {
              criteria1.Add(item);
              criteria2.Add(item);
          }
          criteria2.SetProjection(Projections.RowCountInt64());
          criteria1.AddOrder(oder);         
          multiCriteria.Add(criteria1);
          multiCriteria.Add(criteria2);
         // page = page > 0 ? page : 1;
          criteria1.SetFirstResult(page * pageSize).SetMaxResults(pageSize);          
          IList result = multiCriteria.List();
          IList<T> all = (from object o in (IList) result[0] select (T) o).ToList();
          count = (long)((IList)result[1])[0];
          return all;
      }
   }

Lớp NHibernateHelper

public sealed  class NHibernateHelper
    {
      private static ISessionFactory factory = null;
      static NHibernateHelper()
        {
            Configuration cfg = new Configuration();
            cfg.Configure();
            factory = cfg.BuildSessionFactory();
        }

        public static ISession CurrentSession
        {
            get
            {
                if(factory==null)
                {
                    var configuration = new Configuration();
                    configuration.Configure();
                    factory = configuration.BuildSessionFactory();
                }
                return factory.OpenSession();
            }
        }
        public static void CloseSession()
        {
            factory.Close();
        }
    }

Chú ý : đối với hệ quản trị Mysql không hỗ trợ MultiCriteria ta có thể viết lại lớp Paging như sau :

public abstract class Paging<T>
   {

    public IList<T> GetPagedData(int page, int pageSize, out long count, Order oder, params ICriterion[] criterion)
        {
           // IMultiCriteria multiCriteria = NHibernateHelper.CurrentSession.CreateMultiCriteria();
            ICriteria criteria1 = NHibernateHelper.CurrentSession.CreateCriteria(typeof(T));
            ICriteria criteria2 =
                NHibernateHelper.CurrentSession.CreateCriteria(typeof(T));//.SetProjection(Projections.RowCountInt64());
            foreach (var item in criterion)
            {
                criteria1.Add(item);
                criteria2.Add(item);
            }
            criteria2.SetProjection(Projections.RowCountInt64());
            criteria1.AddOrder(oder);
           // multiCriteria.Add(criteria1);
           // multiCriteria.Add(criteria2);
            criteria1.SetFirstResult(page * pageSize).SetMaxResults(pageSize);
            count = long.Parse(criteria2.List()[0].ToString());
            return   criteria1.List<T>();
           // IList result = multiCriteria.List();
           // IList<T> all = (from object o in (IList)result[0] select (T)o).ToList();
           // count = (long)((IList)result[1])[0];
           // return all;
        }
    }

CodeRun – Online IDE cho các dự án web C#, PHP, Javascript


Được xây dựng trên  SharpKit C# to JavaScript Compiler, CodeRun (http://www.coderun.com) được sử dụng để tạo các dự án web để lập trình theo mô hình cloud computing (điện toán đám mây). CodeRun hỗ trợ nhiều loại dự án C# như  Sharpkit, Silverlight, Facebook, ASP.NET, …, bên cạnh đó còn có Javascript và PHP.

Giới thiệu

Giao diện của CodeRun rất đơn giản và thân thiện, có thể coi là một IDE rút gọn của Visual Studio.  Hiện tại CodeRun hỗ trợ các dự án C# (3.5), PHP (5.1), Javascript, HTML và CSS. Database hỗ trợ gồm có SQL Server 2005 và Amazon SimpleDB.

coderun-ide-new-project

Các tính năng và hỗ trợ của CodeRun được liệt kê trong bảng sau:

Language/ Platform

Syntax
Coloring

Code
Completion

Compilation

Server Side
Debugging

Hyperlink
code
sharing

Single Click
Deployment

C# / ASP.NET

Yes

Yes

Yes

Yes

Yes

Yes

C# / WPF

Yes

Yes

Yes

Yes

Yes

Yes

C# / Silverlight

Yes

Yes

Yes

Yes

Yes

Yes

PHP

Yes

No

N/A

No

Yes

Yes

JavaScript

Yes

No

N/A

No

Yes

Yes

HTML

Yes

No

N/A

No

Yes

Yes

CSS

Yes

No

N/A

No

Yes

Yes

 

Để bắt đầu, bạn hãy nút sau:

Một ví dụ với dự án PHP Web Site để hiển thị thông tin phiên bản PHP được sử dụng:

coderun-ide-php-info

Video hướng dẫn

CodeRun cung cấp một số video hướng dẫn, bạn có thể xem tại link sau hoặc xem trực tiếp từ các video bên dưới:

http://www.coderun.com/tv/

HOWTO: Create and run a simple ASP.NET application with CodeRun Online IDE

 

HOWTO: Debug an ASP.NET application with CodeRun Online IDE

 

HOWTO: Share runnable code with CodeRun Online IDE

 

Online Code Search

Các dự án của bạn lưu trên CodeRun sẽ public và được bình chọn, bạn có thể tìm kiếm cho mình những dự án nguồn mở hữu ích trên trang này (http://www.coderun.com/code/)

Sử dụng thư viện HtmlAgilityPack để xử lý văn bản html


Việc xử  lý văn bản html và trích xuất các phần tử  dom trong văn bản html thường gây cho LTV chúng ta gặp nhiều khó khăn, một giải pháp mà người ta hay dùng là dùng regex để tách các đoạn các thẻ trong văn bản html, nay chúng ta có thể sử  dụng thư  viện HtmlAgilityPack và dùng LINQ để truy vấn sẽ đơn giản hơn nhiều

Đầu tiên download thư  viện : HtmlAgilityPack tại đây

vào visual studio add file HtmlAgilityPack.dll vào Refercences

Ví dụ :

Đầu tiên tạo 1 request đến trang http://dantri.com.vn

string root = “http://dantri.com.vn&#8221;;
WebRequest request = WebRequest.Create(root);
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
var dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();

Sau khi thực hiện lệnh này mã html sẽ nằm ở biến responseFromServer chúng ta bắt đầu xử  lý sử  dụng thư  viện trên

Lấy tất cả link có trong trang :

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(responseFromServer);

List<HtmlNode> links = (from node in doc.DocumentNode.SelectNodes(“//a[@href]”).Cast<HtmlNode>()
where ((node.Attributes[“href”].Value.StartsWith(“/”)) & (node.Attributes[“href”].Value.EndsWith(“.htm”)))
select node).ToList<HtmlNode>();

Lấy tất cả thẻ div có class là : fon31 mt1

 var title = (from m in doc.DocumentNode.SelectNodes(“//div[@class]”).Cast<HtmlNode>()
where m.Attributes[“class”].Value == “fon31 mt1”
select m).ToList<HtmlNode>();

….

Để lấy được nội dung của đoạn text ta sử  dụng thuộc tính InnerHtml trong class HtmlNode 😀

Để xử  lý các truy vấn khác các bạn cần biết đến Xpath

Vậy ứng dụng của việc này để làm gì?

– Các bạn có thể một tool lấy tin tự  động từ  dân trí hay các trang khác ^_^!

– Sử  dụng để viết Web crawler 🙂

Nhận xét :

Có nhiều cách để làm được việc cần nói ở trên nhưng các này đơn giản và viết ngắn gọn hơn ^_^!

Giới thiệu Tuple trong .NET 4.0


Trong phiên bản sắp phát hành Microsoft .NET Framework 4.0 sẽ xuất hiện một kiểu dữ liệu mới là System.Tuple. System.Tuple là một kiểu tập hợp có kích thước cố định được dùng để lưu trữ tập các đối tượng có kiểu dữ liệu khác nhau. Cũng giống như kiểu mảng trước đây, một tuple sẽ có kích thước cố định và không thể thay đổi sau khi được khởi tạo thành công. Điểm khác biệt so với kiểu mảng là mặc dù các phần tử trong tuple có thể có kiểu dữ liệu khác nhau nhưng mỗi phần tử trong tuple được đảm bảo về kiểu dữ liệu của mình. Để hiểu rõ hơn, hãy xét một ví dụ sau đây:

 

Code Snippet
  1. static void Main(string[] args)
  2.         {
  3.             object[] objects = new object[3];
  4.             objects[0] = "This is a string";
  5.             objects[1] = 1;
  6.             objects[2] = new DateTime(2009, 10, 24);
  7.             PrintObjects((string)objects[0], (int)objects[1], (DateTime)objects[2]);
  8.         }
  9.         static void PrintObjects(string str, int i, DateTime dt)
  10.         {
  11.             Console.WriteLine("{0} {1} {2}", str, i, dt.ToString());
  12.         }

Ví dụ trên tạo ra một mảng gồm 3 phần tử có kiểu là object. Thoạt nhìn, đoạn code trên không có vấn đề gì nảy sinh. Nhưng nếu xét về mặt an toàn kiểu dữ liệu (type safety) thì đoạn code trên mắc rất nhiều lỗi. Khi khai báo một mảng các object như vậy, thì ta có thể đưa vào đó bất kỳ thứ gì ta muốn và không thể kiểm soát được. Trong trường hợp, nếu như tại phần tử thứ 2, ta đưa vào là một chuỗi ký tự như sau:

Code Snippet
  1. static void Main(string[] args)
  2.         {
  3.             object[] objects = new object[3];
  4.             objects[0] = "This is a string";
  5.             objects[1] = "This is an another string";
  6.             objects[2] = new DateTime(2009, 10, 24);
  7.             PrintObjects((string)objects[0], (int)objects[1], (DateTime)objects[2]);
  8.         }

Đoạn code sau khi sửa xong vẫn sẽ biên dịch thành công. Nhưng khi gọi thực thi phương thức PrintObjects thì sẽ bị lỗi InvalidCastException khi thực hiện việc chuyển đổi chuỗi “This is an another string” sang kiểu số int.

Bây giờ, cùng ví dụ trên, nhưng ta sử dụng System.Tuple

Code Snippet
  1. static void Main(string[] args)
  2.         {
  3.             System.Tuple<string, int, DateTime> tuple = new Tuple<string, int, DateTime>
  4.             ("This is a string", 1, new DateTime(2009, 10, 24));
  5.             PrintObjects(tuple.Item1, tuple.Item2, tuple.Item3);
  6.         }

Với cách giải quyết vấn đề bằng việc sử dụng System.Tuple, ta có thể loại bỏ các phép toán “ép kiểu” (cast operators) ra khỏi chương trình, điều này giúp cho việc kiểm tra lỗi tại thời điểm biên dịch tốt hơn. Với ví dụ vừa nêu ở trên, ta thấy rằng System.Tuple là một kiểu dữ liệu hữu ích và cần phải có trong .NET Framework.

System.Tuple và KeyValuePair

Hãy xem một phương thức khởi tạo của Tuple như sau:

public static System.Tuple<T1,T2> Create<T1, T2>(T1 item1, T2 item2)

Từ các phiên bản trước của .NET Framework, đã có một kiểu dữ liệu có tên là KeyValuePair<Tkey, Tvalue> nằm trong namespace System.Collections.Generic. Cả hai kiểu Tuple<T1, T2> và KeyValuePair<Tkey, Tvalue> đều rất giống nhau. Thật ra, giữa Tuple<T1, T2> và KeyValuePair<Tkey, Tvalue> có khá nhiều điểm khác biệt. Đối với KeyValuePair<Tkey, Tvalue>, ngoài việc lưu trữ 2 thành phần Tkey và Tvalue, nó còn mang kèm cả “mối quan hệ” giữa 2 thành phần này – và cũng với lý do này, KeyValuePair<Tkey, Tvalue> được dùng trong Dictionary class. Bên cạnh đó, tuples khi khởi tạo có thể thay đổi được kích thước lưu trữ, còn đối với KeyValuePair thì mặc nhiên chỉ lưu trữ duy nhất 2 thành phần là Tkey và Tvalue.

Đối với System.Tuple, ta có các phương thức khởi tạo sau:

Code Snippet
  1.         Tuple <T1>
  2.         Tuple <T1, T2>
  3.         Tuple <T1, T2, T3>
  4.         Tuple <T1, T2, T3, T4>
  5.         Tuple <T1, T2, T3, T4, T5>
  6.         Tuple <T1, T2, T3, T4, T5, T6>
  7.         Tuple <T1, T2, T3, T4, T5, T6, T7>
  8.         Tuple <T1, T2, T3, T4, T5, T6, T7, TRest>

 

Tham khảo bài viết CLR Inside Out: Building Tuple tại http://msdn.microsoft.com/en-us/magazine/dd942829.aspx

Introduction Windows Communication Foundation Part2


Bài viết này được dịch từ Chapter 25 – INTRODUCING WINDOWS COMMUNICATION FOUNDATION của sách Pro C# 2008 and the NET 3.5 Platform Fourth Edition.

The Role of WCF

– Như đã trình bày trong phần trước, việc có quá nhiều công nghệ distributed làm cho developer khó khăn trong việc lựa chọn. Thậm chí khi đã chọn được một công nghệ nào đó để sử dụng, việc build, maintain và config cho application cũng không mấy dễ dàng. Vì thế trước khi có .NET 3.0, rất khó để có thể “plug and play” các distributed API mà không có sự chuẩn bị cẩn thận từ trước. Ví dụ như bạn đang build hệ thống của mình bằng .NET remoting APIs, nhưng sau đó lại thấy rằng XML web services là giải pháp tốt hơn, khi đó có lẽ bạn phải chịu khó code lại.:bbpcuoi3:

– WCF là một distributed computing toolkit được giới thiệu trong .NET 3.0, nó có thể tổng hợp các công nghệ distributed trước đó. Khi sử dụng WCF, bạn có thể expose services của mình cho người khác mà không cần quan tâm xem người ta sử dụng công nghệ gì. Ví dụ như bạn đang build một “in-house” application, các máy trong hệ thống của bạn đều sử dụng hệ điều hành Windows, khi đó bạn có thể dùng nhiều TCP protocols khác nhau mà WCF hỗ trợ để được hiệu năng cao nhất. Đồng thời, service đó cũng có thể được expose ra ngoài bằng XML web service protocol để người khác có thể gọi các functions của service này mà không cần biết họ sử dụng ngôn ngữ lập trình nào cũng như chạy hệ điều hành gì.

An Overview of WCF Features

– Có thể sử dụng và phối hợp các APIs khác nhau mới chỉ là 2 chức năng nhỏ của WCF. Thêm vào đấy, WCF còn bổ trợ các kĩ thuật remoting mà nó expose. Các chứng năng đó như sau:

  • Hỗ trợ strongly typed cũng như untyped message. Hướng tiếp cận này cho phép các .NET application có thể dùng chung các custom types rất hiệu quả. Trong khi đó các software được build trên những platform khác như J2EE có thể hiểu được các loosely typed trong XML.
  • Hỗ trợ nhiều kiểu bindings khác nhau (HTTP, TCP, MSMQ, và named pipes) cho phép bạn chọn hình thức transport data hợp lý nhất.
  • Hỗ trợ các chuẩn web service specification mới nhất (WS-*)
  • Khả năng kết hợp toàn diện các mô hình bảo mật của Win32/.NET và các kĩ thuật bảo mật khác được xây dựng dựa trên những tiêu chuẩn của web services.
  • Hỗ trợ quản lý session state và cả mô hình "one-way stateless"message

– Không chỉ có những chức năng kể trên, WCF còn hỗ trợ tracing và logging, performance counters, publish và subscribe event model, hỗ trợ transaction và nhiều thứ khác.

An Overview of Service-Oriented Architecture

– Một lợi ích khác của WCF là nó hoàn toàn dựa trên một design principles nổi tiếng là Service – oriented architecture (SOA). SOA là một mô hình thông dụng trong ngành phần mềm và mô hình này có thể được hiện thực bằng nhiều cách. Đơn giản nhất, SOA là một cách để design một hệ thống distributed mà trong đó có nhiều service có thể tự hoạt động độc lập, giao tiếp với nhau bằng cách truyền đi các message dựa trên các interfaces đã được xác định trước. (“well – defined interfaces”)

– Trong công nghệ WCF, cụm từ “well – defined interfaces” được tạo ra bằng các CLR interface types. Tuy nhiên theo một nghĩa rộng hơn, interface của một service đơn giản chỉ mô tả một tập các chức năng có thể được gọi từ “external callers”

– Khi WCF được thiết kế ra, WCF team đã follow 4 tenets (tạm dịch là tiêu chí) của SOA design principles. Trong khi các tiêu chí này được tuân thủ tự động trong lúc build các WCF application, việc hiểu rõ được 4 nguyên tắc cốt yếu của SOA có thể giúp cho WCF tiến xa hơn nữa. Phần dưới đây sẽ giới thiệu 1 chút về các tiêu chí này:

Tenet 1: Boundaries Are Explicit
– Tiêu chí này lặp lại một sự thật rằng những chức năng của một WCF service được xác định thông qua các “well – defined interfaces”. Cách duy nhất để một application khác giao tiếp với một WCF service là thông qua các interfaces, và chương trình gọi client này sẽ không hề biết các service đó được xử lý như thế nào.

Tenet 1: Service Are Autonomous
– Khi nói rằng các service là những thực thể tự trị, chúng ta đang nói đến một sự thật rằng một WCF service là một chương trình có thể hoạt động độc lập với các vấn đề liên quan đến version, deployment và installation. Đế giải thích rõ hơn điều này, chúng ta hãy quay lại khía cạnh tiêu biểu của interface-based programming. Khi một interface được tạo ra, nó không nên bị thay đổi. Khi bạn muốn mở rộng một số chức năng nào đó trong WCF service của bạn, hãy tạo ra một interface khác cho các chức năng mới.

Tenet 3: Services Communicate via Contract, Not Implementation
– Tiêu chí thứ 3 này là một hệ quả của interface-based programming, trong đó những xử lý chi tiết của một WCF service không hề có một ảnh hưởng lớn đối với các externall caller. Các WCF clients giao tiếp với nhưng services duy nhất thông qua các interfaces được service expose. Hơn nữa, nếu những chức năng của service interface có sử dụng những custom types, thì các custom types này cần được khai báo chi tiết trong “data contract”để đảm bảo rằng mọi callers có thể map dữ liệu vào một data structure nào đó.

Tenet4: Service Compatibility Is Based on Policy
– Bởi vì các CLR interface cung cấp các strongly typed contracts cho tất cả WCF clients (và rất có thể được sử dụng đế generate WSDL liên quan dựa trên kiểu binding), rất quan trọng để thấy rằng một mình các interfaces/WSDL không đủ ý nghĩa để diễn tả những gì mà một service có thể làm được. Nói như vậy, SOA cho phép chúng ta định nghĩa các “policies” đế từ đó bổ xung cho các service (chẳng hạn như yêu cầu về bảo mật để có thể sử dụng được service). Khi sử dụng các policies này, chúng ta có thể tách rời giữa phần mô tả service (the exposed interfaces) ra khỏi những mô tả về cách chúng hoạt động và cách chúng được gọi.

*** Hi vọng là bài học về lịch sử công nghệ này đã giải thích vì sao WCF là một lựa chọn tốt hơn để build những distributed application sử dụng .NET 3.0 hoặc cao hơn. Bất khi nào bạn định build một “in-house” application sử dụng TCP protocol, trao đổi thông tin giữa các chương trình trong cùng một máy bằng named pipies, hoặc expose dữ liệu cho các application khác nhờ vào web service protocols, WCF luôn là API được recommended.:bbpraroi:
– Nói thế không có nghĩa là bạn không thể sử dụng các công nghệ distributed của của .NET như Webservices/ .NET remoting. Thực sự trong vài trường hợp bạn sẽ buộc phải chọn công nghệ cũ. Trong trường hợp bạn đã sử dụng các công nghệ cũ cho một vài projects, bạn sẽ thấy rằng WCF rất dễ học, WCF cũng sử dụng file xml config, .NET attributes và những tool để generate các lớp proxy.:bbpxtay:

Investigating the Core WCF Assemblies

– Toàn bộ framework WCF được đặt trong một số .NET assemblies installed trong GAC. Bảng dưới đây mô tả sơ bộ role của từng WCF assemblies mà bạn cần để build bất kì WCF application nào.:bbpraroi:

  • System.Runtime.Serializtion.dll: định nghĩa các namespace và các types được sử dụng để serializing và deserializing các objects bên trong WCF framework.
  • System.ServiceModel.dll: là core assembly chức các types sử dụng để build các kiểu WCF application.

– Hai assemblies trên định nghĩa một số namespace và types, trong số đó có các namespaces quan trọng mà chúng ta nên biết:

  • System.Runtime.Serialization: định nghĩa một số types được dùng để control việc serizlize và deserialize bên trong WCF framework
  • System.Service.Model: là namespace chính trong đó định nghĩa các loại binding và hosting cũng như các types liên quan đến security và transactional.
  • System.ServiceModel.Configuration: định nghĩa một số types cung cấp chức năng access vô file config của WCF.
  • System.ServiceModel.Discription: định nghĩa các types cung cấp một object model để các “addresses, bindings và contracts” của WCF có thể được định nghĩa trong các file config.
  • System.ServiceModel.MsmqIntegration: bao gồm các types để tương tác với MSMQ service
  • System.ServiceModel.Security: định nghĩa một số kiểu để control security trong WCF

A brief word regarding cardspace

– Ngoài 2 assemblies kể trên, WCF còn giới thiệu một assembly thứ 3 làSystem.IdentityModel.dll. Trong assembly này bạn sẽ tìm thấy một số namespace và types khác hỗ trợ WCF CardSpace API. Công nghệ này cho phé bạn sử dụng và quản lý digital identities bên trong một WCF application. Về bản chất, CardSpace API cung cấp một mô hình thống nhất đối với các vấn đề về security trong WCF applications, chẳng hạn như caller identity, user authentication/authorization services. (Document về CardSpace API có thể tìm thấy trong .NET Framework 3.5 SDK)

The Visual Studio WCF Project Templates

– Khi bạn muốn build một WCF service, bạn hoàn toàn được phép chọn kiểu project là Class Library rồi sau đó reference đến các WCF assemblies kể trên. Ngoài ra, bạn có thể tạo một WCF service bằng cách chọn kiểu project là WCF Service Library project template trong VS.NET 2008. Project template này sẽ tự động set các references đến những WCF assemblies cần thiết; tuy nhiên, nó còn tự động generate một số “started code” cho những ai chưa quen.:bbpraroi:

The Visual Studio 2008 WCF Service Library project template

Hình 1: The Visual Studio 2008 WCF Service Library project template

– Một lợi ích khác khi chọn WCF Service Library project template là nó còn giúp bạn sinh ra 1 file app.config, điều này có thể hơi lạ khi output của project này là một dll chứ không phải 1 file excutable. Tuy nhiên, file config này rất hữu dụng khi bạn muốn debug hoặc run WCF Service Library projet, VS.NET IDE sẽ tự động chạy WCF Test Client application. Chương trình client test này (WcfTestClient.exe) sẽ đọc những setting trong file app.config để host server của bạn trước khi test. Nội dung của file config này là những setting cơ bản nhất cho một WCF service. Bạn có thể copy và paste những config này vào file config của chương trình WCF hosting chính.

– Ngoài Service library template trên, category WCF project trong menu New Project của VS.NET 2008 còn có hai project WCF template kết hợp Windows Workflow Foundation vào WCF service và một template để build một RSS library.

The WCF Service Website Project Template

– Có một template khác về WCF trong VS.NET 2008 mà bạn sẽ thấy trong New Web Site dialog box như hình dưới đây:

The Visual Studio 2008 web-based WCF Service project template

Hình 2: The Visual Studio 2008 web-based WCF Service project template

– Template này rất có ích khi bạn muốn tạo một WCF service sử dụng web service protocol. Lựa chọn này sẽ tự động tạo một IIS virtual directory để host các WCF program files, tạo file web.config để expose server thông qua HTTP, và file svc. Theo cách này, web-based WCF Service project rất tiết kiệm thời gian vì IDE đã tự động setup mọi thứ cần thiết.

– Ngược lại, nếu bạn muốn build một WCF service bằng WCF Service Library template, bạn sẽ có thể host service của mình theo nhiều cách khác nhau thay vì trong IIS như trên (custom host, Windows service, …)

The Basic Composition of a WCF Application

– Tóm lại, khi bạn muốn sử dụng công nghệ WCF để build các hệ thống distributed, về cơ bản bạn phải tạo ra ít nhất 3 assemblies::bbpnghi:

  • WCF Service assembly: dll này sẽ chứa những classes và interfaces để mô tả các chức năng mà service của bạn muốn expose ra bên ngoài.
  • WCF Service host: chương trình này được dùng để host WCF service assembly
  • WCF Client: Chương trình này sẽ gọi các chức năng của WCF service trên

– Như đã nói, WCF service assembly là một .NET class library chứa một số các WCF contracts và code implementation. Assembly "Service host" lại chính xac là một .NET excutable application. Các bạn sẽ thấy rằng WCF service có thể được host trong bất kì loại application nào (Windows Forms, Windows service, WPF applications, …) Khi bạn muốn build một kiểu host application của mình, bạn phải sử dụng đến class ServiceHost cũng như một số file config liên quan. Tuy nhiên, nếu bạn đang sử dụng IIS để làm host cho WCF service, bạn không cần phải build một custom host làm gì.:bbpraroi:

– Assembly cuối cùng là một chương trình nào đó muốn gọi các service WCF và nó có thể là bất cứ dạng .NET application nào. Tương tự như chương trình host WCF service, client application cũng phải có sử dụng những file config để mô tả cách call các service trong WCF service host.

– Hình dưới mô tả (một cách high-level) mối quan hệ giữa những assemblies trên với nhau:

A high-level look at a typical WCF application

Hình 3: A high-level look at a typical WCF application

– Chúng ta cũng nên biết rằng việc sử dụng các file config là optional. Nếu muốn, chúng ta có thể hard-code chương trình host cũng như chương trình client các setting về (endpoints, binding, address, etc). Vấn đề chính khi làm như vậy là khi muốn thay đổi gì đó, bạn phải code lại, build lại và deploy lại một số assemblies. Khi sử dụng file config, hệ thống sẽ tương đối flexible. Ta chỉ cần update lại nội dung file config rồi restart lại application.:bbpskien:

Introduction Windows Communication Foundation Part1


Bài viết này được dịch từ Chapter 25 – INTRODUCING WINDOWS COMMUNICATION FOUNDATION của sách Pro C# 2008 and the NET 3.5 Platform Fourth Edition.

 .NET 3.0 giới thiệu một API mới hỗ trợ chúng ta build các hệ thống distributed gọi là Windows Communication Foundation (WCF). Không như những distributed APIs khác mà có thể bạn từng sử dụng (như DCOM, .NET Remoting, XML web services, …), WCF cung cấp một chuẩn lập trình thống nhất, dễ mở rộng và có thể tương tác được với các công nghệ distributed cũ. Loạt bài này sẽ giới thiệu sự cần thiết của WCF và những vấn đề sẽ giải quyết được bằng WCF, bắt đầu bằng một giới thiệu sơ qua các công nghệ distributed đã có.

A Potpourri of Distributed Computing APIs

– Hệ điều hành Windows đã cung cấp một số APIs để build những hệ thống distributed. Mọi người thường nghĩ rằng “distributed systems” thì phải có ít nhất 2 máy tính, nhưng theo nghĩa rộng thì khái niệm này nói đến 2 application nào đó cần trao đổi dữ liệu với nhau, dù chúng chạy trên cùng một máy tính. Nếu hiểu theo nghĩa này, việc chọn lựa công nghệ để sử dụng sẽ liên quan đến việc trả lời câu hỏi sau đây:

Liệu hệ thống được làm ra sẽ sử dụng “in-house”, hay nó có thể được những người bên ngoài sử dụng?

– Nếu bạn muốn build một hệ thống chỉ để sử dụng nội bộ, rất có khả năng rằng bạn sẽ phải bảo đảm mỗi máy tính trong toàn bộ hệ thống phải chạy cùng một hệ điều hành như nhau, cùng sử dụng một framework (.NET, COM, J2EE, v.v), và bạn sẽ có thể phải tuân theo các chuẩn của hệ thống bảo mật hiện tại khi implement các chứng năng như authentication và authorization. Trong tình huống như vậy, bạn buộc phải chọn đúng một công nghệ distributed API phù hợp với 1 hệ điều hành nào đó, tương thích với 1 framework nào đó.

– Ngược lại, nếu bạn đang build một hệ thống cho cả “nội bộ” lẫn những người ngoài mạng sử dụng, bạn sẽ phải đối mặt với rất nhiều vấn đề. Đầu tiên, bạn không thể buộc-không thể biết người khác phải sử dụng hệ điều hành gì, không thể ép họ dùng framework nào để tương tác với hệ thống của bạn cũng như không thể biết họ sử dụng nền tảng bảo mật nào.

– Hơn nữa, nếu bạn làm việc trong một công ty lớn hoặc trong một môi trường mạng sử dụng rất nhiều hệ điều hành khác nhau cũng như nhiều công nghệ lập trình khác nhau, thì khi đó application “nội bộ” của bạn cũng sẽ gặp vấn đề như trên. Trong những tình huống như vậy, bạn cần phải chọn một công nghệ distributed flexible để bảo đảm cho hệ thống tương lai của mình có thể được sử dụng thuận tiện nhất.

– Dựa trên lời giải đáp cho câu hỏi trên, bước tiếp theo của chúng ta là phải xác định xem chính xác là API nào nên được chọn. Phần dưới đây sẽ giới thiệu sơ lược các công nghệ distributed chính đã được sử dụng bởi những Windows developer. Sau khi xong bài học lịch sử này, bạn sẽ dễ dàng thấy được tính hữu ích của Windows Communication Foundation.:bbpxtay:

The Role of DCOM

– Trước thời của .NET, Distributed Component Object Model (DCOM) là lựa chọn tối ưu trong cách distrubuted APIs. Một lợi ích của DCOM là nó cho phép tính “không phụ thuộc vị trí” đối với các components. Nghĩa là nó cho phép những phần mềm phía client được lập trình sao cho “địa chỉ vật lý” của các remote objects không bắt buộc phải hard-code. Cho dù các remote object nằm cùng một máy tính hay trên các máy khác ở một network khác thì cũng không ảnh hưởng bởi vì “địa chỉ” thật sự được lưu bên ngoài hệ thống (bên trong registry).

– DCOM đã đạt được một số thành công nhất định đối với các phần mềm Windows. DCOM cũng đã được thử port sang một số hệ điều hành khác nhưng kết quả không mấy sáng lạn, DCOM một mình nó không đưa ra một bộ khung toàn diện để build những giải pháp liên quan đến nhiều hệ điều hành (Windows, Unix, Mac) hay có thể chia sẽ data giữa nhiều nền tảng công nghệ khác nhau (COM, J2EE, CORBA, …)

– Thông thường, DCOM là một lựa chọn khá thích hợp cho các ứng dụng nội bộ bởi vì expose các COM types ra phạm vi ngoài mạng công ty của bạn có thể gặp phải một số vấn đề phức tạp như firewalls. Với sự ra đời của .NET, DCOM nhanh chóng trở nên lạc hậu. Vì vậy, trừ khi bạn phải maintain 1 hệ thống cũ có sử dụng DCOM, còn không ta có thể xem nó như là một công nghệ của quá khứ.:bbpraroi:

The Role of COM+/Enterprise Services

– DCOM chỉ định nghĩa một cách để thiết lập một kênh giao tiếp giữa hai phần mềm COM. Để bổ sung những yêu cầu khác khi build một giải pháp distrubuted computing toàn diện, Microsoft vào phút cuối đã đưa ra một công nghệ khác là Microsoft Transaction Server (MTS) rồi sau đó đổi tên thành COM+ ở một release sau đó.

– Bất chấp tên gọi, COM+ không chỉ được dùng bởi những COM developer, nó còn được sử dụng bởi những .NET developer. Từ phiên bản đầu tiên của .NET đã có chứa một namespace là System.EnterpriseServices. Nhờ nó, người dùng .NET có thể tạo ra những managed library để có thể install vào môi trường COM+, để có thể truy xuất những COM services. Trong trường hợp nào đi nữa, một “COM+ aware library” khi được install vào “COM+ runtime” sẽ được gọi là một “serviced component”

– COM+ cung cấp một số features mà các serviced component có thể sử dụng, bao gồm transaction management, objet lifetime management, pooling services, role-based security system, không phụ thuộc mô hình event, v.v. Đó chính là những lợi ích chính vào thời điểm đó vì hầu hết các hệ thống distributed system đều cần những tính năng như vậy. Một trong những cái rất thuyết phục của COM+ là khả năng điều chỉnh các setting dễ dàng bằng các administrative tools.

– Trong khi COM+/Enterprise Services vẫn còn được sử dụng, công nghệ này một lần nữa lại là “Windows-only solution” và thực sự chỉ thích hợp với các giải pháp “in-house” hoặc đóng vai trò như một back-end service cho một hệ thống khác, một public website chẳng hạn có thể call 1 serviced components (COM+ objects) ở background.

– WCF không hỗ trợ build những serviced components. Tuy nhiên nó cung cấp một phương pháp để các WCF services giao tiếp với các COM+ objects. Nếu bạn muốn build một serviced components bằng C#, bạn phải dử dụng trực tiếp namespace System.EnterpriseServices. :bbpbuon:

The Role of MSMQ

– Microsoft Message Queuing (MSMQ) API cho phép developer build những hệ thống distributed cần tính tin cậy cao khi gửi/nhận những dữ liệu trong network. Như chúng ta đều biết, trong bất kì distributed system nào cũng đều có một nguy cơ là các server có thể bị down bất cứ lúc nào, database server offline hay các kết nối mạng bị đứt giữa chừng. Hơn nữa, có một số application cần được thiết kế để có thể lưu giữ những message để rồi có thể truyền đi sau đó (queuing data).

– Lúc đầu, MSMQ được đóng gói như một thư việc cấp thấp C và các COM objects. Khi sử dụng System.Message namespace, .NET developer có thể hook vào MSMQ và build những application có thể giao tiếp với những application mà không có kết nối liên tục. Thêm nữa, COM+ layer có thể kết hợp với các chức năng của MSMQ bằng một kĩ thuật gọi là Queued Components (QC).

– Bất kể bạn dùng kĩ thuật nào để tương tác với MSMQ runtime, cuối cùng bạn cần đảm bảo rằng application mình viết có thể gửi đi những Message đúng nơi đúng lúc. Cũng giống như COM+, MSMQ vẫn còn được sử dụng để build những distributed software trong môi trường Windows.:bbpbuon:

The Role of .NET Remoting

– Như đã nói ở trên, cùng với sự ra đời của .NET platform, DCOM mau chóng trở nên lỗi thời. Và thay vào đó là một .NET class libraries được đóng gói sẵn trong .NET remoting layer: System.Runtime.Remoting. API này cho phép nhiều máy tính có thể host nhiều remoted objects, tất nhiên chúng phải chạy những ứng dụng .NET.

– .NET remoting API có một số những tính năng rất hữu dụng. Trong đó, tính năng quan trọng nhất chính là khả năng sử dụng file xml config để có thể khai báo những seting quan trọng cho phép client và server có thể giao tiếp với nhau theo nhiều cách. Bằng cách này, sẽ rất dễ dàng để thay đổi tính năng của application chỉ với một vài chỉnh sửa file config và restart application.

– Thực sự rằng API này chỉ có thể sử dụng bởi những application .NET, nhờ đó bạn có thể thừa hưởng được nhiều lợi ích, như là data có thể được mã hóa và nén ở dạng binary, có thể sử dụng ngay các Common Type System (CTS) khi khai báo biến và return values. Thực ra với công nghệ này có thể sử dụng .Net để build những distributed system mà có thể chạy trên nhiều hệ điều hành khác nhau (sử dụng MONO), tương tác với các nền tảng khác như J2EE …:bbpskien:

The Role of XML Web Services

– Các distributed APIs ra đời trước đều hỗ trợ rất ít (nếu có) khả năng access đến các chức năng của hệ thống từ một caller chưa biết. Khi bạn cần đưa ra một số services để người khác có thể sử dụng không cần biết người đó sử dụng hệ điều hành gì và công nghệ nào thì XML web services có vẽ như là lựa chọn hợp lý nhất.

– Không như các web application thông dụng, một web service được sử dụng để expose các chứng năng của remote components nhờ vào web protocols. Trong phiên bản đầu của .NET, developer được cung cấp một số chức năng để build và gọi (consuming) XML web services trong namespaceSystem.Web.Services. Thực ra bây giờ người ta chỉ việc sử dụng attribute [WebMethod] cho mỗi public method mà bạn muốn người khác có thể sử dụng. Hơn nữa, Visual Studio 2008 còn cho phép bạn connect đến một remote web service chỉ với vài cái click.:bbpraroi:

– Web services cho phép developer build những .NET assemblies với những .NET types có thể được gọi thông qua giao thức HTTP đơn giản. Hơn nữa, một web service có thể mã hóa dữ liệu của nó theo chuẩn XML. Công nghệ Web service dựa trên các tiêu chuẩn của ngành phần mềm như HTTP, XML, SOAP thay vì một số kĩ thuật đặc thù như DCOM hay .NET remoting, chúng nâng cao khả năng giao tiếp tối đa giữa các hệ thống khác nhau.

– Tất nhiên không có một distributed API nào là hoàn hảo. Một trở ngại tiềm tàng của web services là vấn đề về performance (sử dụng HTTP và XML), và nó có thể không phải là một lựa chọn tốt để build những ứng dụng “in-house” khi mà TCP-based protocol và dữ liệu ở dạng binary format có thể được sử dụng mà không gặp bất cứ trở ngại nào.:bbpxtay:

XML web services allow for a very high degree of interoperability

Hình 1: XML web services allow for a very high degree of interoperability

Web Service Standars

– Một vấn đề dễ thấy nhất là có khá nhiều ông lớn như Microsoft, IBM và Sun Microsystems tạo ra các chuẩn Web Services của riêng mình và các chuẩn này không 100% tương thích với nhau. Hiển nhiên đó là một vấn đề rất đau đầu, chúng ta đều biết rằng mục đích của Web service là tạo ra khả năng tương tác cao giữa các hệ thống không phụ thuộc platforms và hệ điều hành.:bbptuc:

– Để bảo đảm tính độc lập môi trường của Web Service, những tổ chức như World Wide Web Consortium (W3C; http://www.w3.org) và Web Services Interoperatibility Organization (WS-I: http://www.ws-i.org) đã đứng ra xem xét các đặc tả để vạch ra những điều chi tiết để các software vendor (như IBM, Microsoft, Sun,..) nên build những công nghệ của họ như thế nào để bảo đảm tính tương thích với nhau.

– Tập hợp các đặc tả này được đặt tên theo kiểu prefix WS-, bao gồm các vấn đề về security, attachments, description của web services (Web Service Description Language, hay WSDL), policies, SOAP formats, và một số những vấn đề quan trọng khác.

– Có thể bạn đã biết rằng Microsoft đã hỗ trợ hầu hết các chuẩn trên trong Web Services Enhancements (WSE) 3.0 toolkit, bạn có thể download nó ở website: http://msdn2.microsoft.com/en-us/webservices

– Khi bạn build những WCF service applications, bạn sẽ không cần sử dụng trực tiếp các assemblies của WSE 3.0 toolkit. Ngoài ra, nếu bạn build những WCF service sử dụng HTTP-based binding, mặc định các đặc tả WS-* sẽ có sẵn cho bạn.

Named Pipes, Sockets, and P2P

– Nếu như DCOM, .NET Remoting, web services, COM+ và MSMQ vẫn chưa đủ “challenge” đối với bạn :bbpcuoi3:thì bạn có thể sử dụng các APIs giao tiếp khác như pipes, sockets và peer-to-peer (P2P) services. Những APIs cấp thấp này hứa hẹn sẽ có performance cao hơn nhiều đặc biệt đối với những máy LAN nhưng bù lại sử dụng chúng sẽ khá phức tạp.

– Nếu bạn phải build những hệ thống distributed mà các application chạy trên cùng một máy, bạn có thể sử dụng “named pipes” API trong namespace System.IO.Pipes (.NET 3.5). Kĩ thuật này là cách nhanh nhất để truyền data giữa các applications trong cùng một máy tính.

– Cuối cùng, nếu bạn build những applications cần đi sâu chi tiết cách truyền dữ liệu trên network thì sockets và P2P có thể được dùng trong các namespace System.Net.Sockets  System.Net.PeerToPeer.