by oclockvn at 11:28 PM 12/08/2016

ASP.NET MVC 5 P3: Đôi chút về extension method. ASP.NET MVC helpers.

Mục tiêu của bài viết này là để giới thiệu về helper. Tuy nhiên sẽ dễ dàng hơn nếu mình nói về extension method trước.

Extension method

Extension method (phương thức mở rộng) là 1 dạng phương thức tĩnh (static method) "đặc biệt". Đặc biệt là vì nó cho phép bạn gắn vào bất-cứ-đối-tượng-có-thể nào đó mà không cần phải thực hiện các bước truyền thống: viết ra lớp ra, viết phương thức ra, ... Nói thì khó hiểu lắm, giờ ví dụ cho đơn giản:

Ví dụ 1 phương thức tĩnh "bình thường" cho phép bạn ..ah..thêm prefix vào chuỗi:

public class NormalMethod 
{
    public static string Prefix(string original, string prefix)
    {
        // check null or empty, etc...

        return "[" + prefix + "] " + original;
    }
}

và tất nhiên bạn có thể dễ dàng gọi bằng cách:

var s = "hello world";
var r = NormalMethod.Prefix(s, "c#");

// => result: "[c#] hello world ;

Nhưng với extension method, bạn có thể viết như sau:

var r = "hello world".Prefix("c#");

bằng cách:

extension prefix

Ah ah, đơn giản vậy thôi:

  1. phải là static class
  2. Trong phương thức mở rộng, đối tượng muốn mở rộng (ở đây là string) phải đi kèm với từ khóa this.

Nếu bạn sử dụng sẽ thấy:

extension prefix using

Trong 1 project, nếu nhỏ mình sẽ đặt các phương thức mở rộng vào 1 thư mục Helpers, nếu là proj lớn thì mình sẽ viết ra 1 dll để dùng chung (tùy cách tổ chức của bạn)

extension structure

Lưu ý: Như hình ở trên, trong extension method mình chỉ sử dụng namespace trùng với tên solution, việc này đơn giản là để khỏi phải using namespace didongexpress.Helpers mỗi khi sử dụng extension method thôi.

Bạn có thể vào trang extensionmethod.net/csharp để tham khảo và sử dụng các extension method thông dụng nhất.

ASP.NET MVC helpers

Nó là 1 extension method được dùng để sinh ra đường dẫn (path/content/route...) 1 cách tiện nhất + đơn giản nhất + hiệu quả nhất.

Url.Content("~/path/to/server/file");

Url.Content("") sinh ra đường dẫn file trên server. Lưu ý khi sử dụng trong view, bạn sử dụng cú pháp razor nên sẽ viết @Url.Content("").

Ví dụ: thêm bootstrap.js vào layout

Mở _Layout.cshtml ra và gõ thẻ script vào (bạn có thể kéo thả để visual studio tự generate thẻ cũng được)

add script

Với Url.Content, bạn có thể viết:

add script helper

Kết quả ra thì như nhau cả thôi:

url content result

À, nhân đây thì bạn có để ý 2 thẻ script phía dưới cùng đó là gì không? Nó được visual studio sinh ra để enable chức năng auto link/live preview css (hoặc các extension khác). Nếu không muốn có 2 thẻ này, bạn có thể tắt nó đi bằng cách bỏ chức năng Enable Browser Link trong vs:

disable browser link

Alright, quay lại chủ đề chính. Nếu kết quả là như nhau, vậy thì dùng Url.Content có lợi gì?

"OK, 9 điểm, về chỗ. Good question" :v

Dĩ nhiên là nó có lợi hơn rồi, bạn cần phải kiểm chứng để nhớ lâu hơn đấy nhé. Ở đây mình sẽ nói 2 cái hay gặp nhất (có nhiều cái lợi lắm nhé):

  1. Bạn sẽ không phải lo lắng về url khi host website ở sub-domain, ví dụ như beta.phantienquang.com. Vì bạn (có thể chưa-)-biết đấy, sub-domain là 1 thư mục con của domain, do đó IIS sẽ không thể nào tìm thấy đường dẫn beta\Scripts\bootstrap.js. Url.Content sẽ xử lý vụ đó cho bạn mà bạn không cần viết thêm gì nữa cả.
  2. Dân SEO rất thích vẽ vời, và 1 trong số đó là chuyện absolute url. Bạn có thấy kết quả khi render ra không, nếu bạn muốn nó là:
<script src='/Scripts/bootstrap.js'></script>                         <!-- old -->
<script src='http://phantienquang.com/Scripts/bootstrap.js'></script> <!-- new -->

thì bạn phải làm sao? làm sao??? : ))) Một lần nữa, Url.Content xử được vụ này, bạn chỉ viết thêm vài dòng code thôi.

Có sự khác nhau giữa 2 đường dẫn sau, hãy "nhúng chàm" để biết sự khác nhau đó nhé :))

<script src="~/Scripts/bootstrap.js"></script>
<script src="/Scripts/bootstrap.js"></script>

Url.Action("ActionName", "ControllerName", [...] )

Đây là 1 helper cho phép sinh ra địa chỉ url. Lấy ví dụ cụ thể:

public class HomeController : ControllerName
{
    public ActionResult Index()
    {
        return View();
    }
}

Ở trên là 1 action cơ bản, và để tạo 1 url tới action này ta có các cách sau:

<!-- cách 1 -->
<a href='/Home/Index'>go to home</a>

<!-- cách 2: an toàn hơn -->
<a href='~/Home/Index'>go to home</a>

<!-- cách 3: sử dụng url.action -->
<a href='@Url.Action("Index", "Home")'>go to home</a>

Tất nhiên kết quả cũng sẽ như cách 1, nhưng tại sao bạn lại nên sử dụng Url.Action?

Tương tự như Url.Content (phân biệt nhé, Url.Content sinh ra đường dẫn tới file, Url.Action sinh ra url), Url.Action cũng có (nhiều) lợi ích sau (rất nhiều nhé, mình liệt kê vài cái thôi):

  1. Đảm bảo sinh ra url "chuẩn như Lê Duẩn" trong mọi trường hợp (sub domain, areas), kể cả absolute url (như trên Url.Content)
  2. Đảm bảo render đúng custom url mà bạn đã custom trên action...ừm, ví dụ cho dễ hiểu nè.

Chắc chắc bạn đã gặp trường hợp có 1 url "đẹp" như sau:

http://didongexpress.com/san-pham/samsung-galaxy-chay-no.html

Vậy hãy tưởng tượng, sẽ có 1 cái link như thế này:

<a href='/san-pham/samsung-galaxy-chay-no.html'>Samsung galaxy cháy nổ</a>

Vậy trên action sẽ là gì?

Bạn sẽ sớm biết ở những bài sau thôi, cái này gọi là custom route, bây giờ bạn xem cách làm nhé (chưa cần biết cách làm vội đâu):

public class ProductController : ControllerName
{
    [Route("san-pham/{slug}.html")]
    public ActionResult Detail(string slug)
    {
        return View();
    }
}

Và nếu dùng Url.Action, bạn chỉ đơn giản:

<a href='@Url.Action("Detail", "Product", new { slug = "samsung-galaxy-chay-no" })'>Samsung galaxy cháy nổ</a>

Yes, Url.Action sẽ xử lý route custom cho bạn, thậm chí nó có thể render thành absolute url nữa...

<!-- absolute -->
<a href='http://didongexpress.com/san-pham/samsung-galaxy-chay-no.html'>Samsung galaxy cháy nổ</a>

Cái Url.Action này phức tạp hơn Url.Content 1 tí thôi, bạn cần để ý những điều sau:

0. Nhớ là có dấu '' hoặc "" bọc ngoài cái "Url.Action()" nhé, không thì ăn lỗi đấy :)

  1. Nó có 10 overload gì đó, cứ vào gõ rồi tìm hiểu, nhưng cái phổ biến nhất vẫn là Url.Action("ActonName","ControllerName", routeValues: new {} )
  2. Để ý nhé, Action Name trước rồi mới tới Controller Name, và, Controller Name chỉ là tên controller thôi nhé, không có cái postfix phía sau.
  3. route values là các giá trị được truyền lên dưới dạng query string, được viết dưới dạng anonymous type của C# (ví dụ dưới).

Có thêm 1 cách nữa để sinh ra thẻ a đó là sử dụng Html.ActionLink, cá nhân mình thấy cái này chả tiện chút nào, bạn nào muốn dùng thì có thể gg nhé.

Ok, vài ví dụ về route values:

VD1: 1 tham số

<!-- nếu muốn thế này: -->
<a href='/Product/Detail/123456'>Samsung galaxy</a>

<!-- thì viết thế này -->
<a href='@Url.Action("Detail", "Product", new { id = 123456 })'>Samsung galaxy</a>
<!-- or -->
<a href='@Url.Action("Detail", "Product", new { 123456 })'>Samsung galaxy</a>

Á à, nếu route parameter là id, bạn có thể lược bỏ. Tại sao ư? Bạn sẽ biết sau này.

VD2: nhiều tham số

<!-- nếu muốn thế này -->
<a href='/Product/Detail/123456&cate=abc'>Samsung galaxy</a>
<!-- hoặc thế này -->
<a href='/Product/Detail?id=123456&cate=abc&page=2'>Samsung galaxy</a>

<!-- thì viết như này -->
<a href='@Url.Action("Detail", "Product", new { id = 123456, cate = "abc", page = 2 })'>Samsung galaxy</a>
<!-- hoặc cách này (*) -->
<a href='@Url.Action("Detail", "Product")?id=@id&cate=@cate&page=@page'>Samsung galaxy</a>

(*) @id, @cate, @page là các biến giả định, sử dụng cú pháp razor để binding giá trị. Chỗ này nghĩa là đoạn '@Url.Action("Detail", "Product")' sẽ render thành '/Product/Detail', sau đó thực hiện cộng chuỗi phía sau để được kết quả như trên.

Bạn sẽ hiểu cách binding từ query string vào Action sau nhé.

create/custom helpers

Trên đây là 2 build-in helper được sử dụng rất nhiều (tốt nhất là sử dụng hoàn toàn) trong mvc. Vậy làm sau để viết những helper của riêng mình? Đơn giản thôi:

create helper

2 bước:

  1. Khai báo với từ khóa @helper, bạn có thể thấy nó giống như 1 hàm vậy, có thuyền vào tham số.
  2. Gọi, 1 cách bình thường như ở huyện.

Ở trên là cách tạo helper trong view (sử dụng razor syntax), bạn cũng có thể tạo helper trong C#, nó đơn giản chỉ là 1 static method mà thôi.

Tham khảo cách viết helper trong C# tại creating custom html helpers cs.

Kết

Hy vọng bạn sẽ hiểu và tận dụng được sức mạnh của helper trong MVC, vì từ nay mình sẽ dùng nó khá nhiều trong proj. Nếu vẫn còn thắc mắc thì cứ comment hoặc pm mình vô tư, mình sẽ trả lời sớm nhất trong khả năng có thể ^^.

Trong bài tiếp theo mình sẽ đi vào thực hiện layout cho web, vì nó khá lâu nên mình sẽ quay clip và ghi những gì cần ghi :). Bạn nên chuẩn bị 1 số thứ sau:

  1. Cài đặt nodejs để thực hiện các task "nho nhỏ".
  2. Xem "sơ sơ" về scss tại trang chủ hoặc bài viết tại blog cũ của mình.
  3. Tìm hiểu về gulp

Hẹn gặp lại 1 ngày không xa ^^!

  • 0
  • 1190
  • 8
relate posts
by {{relate.UpdatedBy}} at 02/21/2018

{{relate.Title}}

  • {{relate.TotalComment}}
  • {{relate.View}}
  • {{relate.AveragePoint}}
[{{postCtrl.comments.length}}] comments
all comments {{ postCtrl.isHiddenComment ? 'show comments' : 'hide comments' }}
what do you want to say?

(*) markdown supported with html disabled