Tìm hiểu và xây dựng ứng dụng web siêu thị trực tuyến với ASP.NET MVC

MỤC LỤC GIỚI THIỆU CHUNG1 CHƯƠNG 1: MỞ ĐẦU3 1.1.Tổng quan về ASP.NET MVC3 1.2.Tổng quan về ứng dụng thương mại siêu thị trực tuyến. 3 2.1.Yêu cầu đặt ra cho kiến trúc hệ thống. 4 2.2.Thiết kế kiến trúc hệ thống. 4 2.2.1.Thiết kế kiến trúc phân tầng. 5 2.2.2.Lựa chọn lưu trữ dữ liệu và thiết kế tầng truy xuất dữ liệu. 5 2.2.3.Thiết kế tầng logic nghiệp vụ. 9 2.2.4.Xây dựng vùng nhớ đệm - caching , sử dụng mạng phân phối nội dung tăng hiệu năng của hệ thống10 2.2.5.Tầng trình diễn (UI hay Views)10 CHƯƠNG 2: TÌM HIỂU ASP.NET MVC VÀ LINQ12 1.1.ASP.NET MVC là gì?. 12 1.1.1.Mô hình MVC cơ bản. 12 1.1.2.Một vài đặc tính của ASP.NET MVC12 1.2.Sự khác biệt so với Web Form13 1.3.Quá trình thực thi một ứng dụng nền web ASP.NET MVC15 2.1.Linq to SQL là gì?. 16 2.2.Mô hình hóa CSDL dùng Linq to SQL16 2.3.Tìm hiểu lớp DataContext18 2.4.Các ví dụ Linq to SQL18 2.5.Tổng kết21 CHƯƠNG 3: PHÂN TÍCH THIẾT KẾ ỨNG DỤNG22 1.1.Thiết kế hệ thống. 22 1.1.1.Các module của hệ thống. 22 1.1.2.Mối quan hệ giữa các module. 23 1.2.Đặc tả sơ lược các module. 23 1.2.1.Module hồ sơ và thành viên. 23 1.2.2.Module lấy ý kiến khách hàng. 23 1.2.3.Module thương mại23 1.2.4.Module gửi thư. 23 1.2.5.Module diễn đàn. 23 1.2.6.Module tìm kiếm siêu thị24 1.2.7.Module bài báo, tin tức, và blog. 24 1.2.8.Module quốc tế hóa. 24 1.2.9.Module kiểm thử. 24 2.1.Tổng quan về module. 25 2.2.Sơ đồ chức năng. 26 2.3.Các bảng DL của module. 26 2.3.1.Tạo bảng DL26 2.3.2.Cấu hình trong web.config cho membership, role và profile:27 2.4.Models. 28 2.4.1.Lớp UserInformation. 28 2.4.2.Lớp ProfileInformation. 28 2.5.Controllers. 29 2.6.Views. 30 2.7.Sử dụng Javascript31 2.8.Cấu hình định tuyến. 32 2.9.Xử lí xác thực người dùng. 32 3.1.Tổng quan về module. 33 3.2.Sơ đồ chức năng. 34 3.3.Tìm hiểu , sử dụng Paypal cho chức năng thanh toán (check out)34 3.3.1.Tạo tài khoản ảo cho mục đích kiểm thử. 35 3.3.2.Quá trình thanh toán với Paypal từ website thương mại35 3.4.Các bảng dữ liệu của module. 37 3.5.Lớp thiết lập cấu hình cho module thương mại37 3.6.Model38 3.7.Controller39 3.8.View40 3.9.Sử dụng JavaScript42 3.10.Cấu hình định tuyến. 45 4.1.Tổng quan về module. 47 4.2.Các vấn đề cần quan tâm khi xây dựng module:47 4.3.Sơ đồ chức năng. 50 4.4.Các bảng dữ liệu. 50 4.5.Thiết kế lớp cấu hình cho module. 51 4.6.Model51 4.7.Controller52 4.8.View52 4.9.Cấu hình định tuyến. 53 5.1.Tổng quan về module. 54 5.2.Sơ đồ chức năng. 54 5.3.Các bảng dữ liệu. 55 5.4.Thiết kế lớp cấu hình cho module. 56 5.5.Model56 5.6.Controller57 5.7.View58 5.8.Sử dụng javascript58 5.9.Cấu hình định tuyến. 63 6.1.Tổng quan về module. 65 6.2.Sơ đồ chức năng. 65 6.3.Các bảng dữ liệu. 66 6.4.Xây dựng lớp ForumsElement cho thiết lập cấu hình module. 66 6.5.Model66 6.6.Controller67 6.7.View68 6.8.Sử dụng javascript69 6.9.Cấu hình định tuyến. 73 6.10.Cấu hình trong tệp web.config. 74 7.1.Tổng quan về module. 75 7.2.Sơ đồ chức năng. 75 7.3.Các bảng dữ liệu. 76 7.4.Xây dựng lớp ArticleElement cho thiết lập cấu hình của module. 76 7.5.Model77 7.6.Controller78 7.7.View79 7.8.Sử dụng javascript80 7.9.Cấu hình định tuyến. 86 8.1.Tổng quan về module. 90 8.2.Xây dựng module. 90 8.2.1.Các Service hỗ trợ quốc tế hóa trong Framework của Microsoft90 8.2.2.Xây dựng các tệp tài nguyên. 91 8.2.3.Controller của module. 93 8.2.4.View tương ứng của module. 93 CHƯƠNG 4: SỬ DỤNG WEB FORMS TRONG ỨNG DỤNG ASP.NET MVC95 1.1.Các lí do cho sự kết hợp giữa 2 công nghệ. 95 1.2.Tại sao có thể thực hiện được sự kết hợp này. 95 1.3.Các bước để kết hợp các trang WebForms vào ứng dụng ASP.NET MVC95 2.1.Tổng quan về module. 96 2.2.Sơ đồ chức năng. 96 2.3.Phân tích cách xây dựng chức năng. 96 2.4.Bảng CSDL97 2.5.Các lớp hỗ trợ trong module. 97 2.6.View100 2.7.Thêm định tuyến cho các trang view của module. 101 2.8.Vấn đề bảo mật102 CHƯƠNG 5: TRIỂN KHAI ỨNG DỤNG VÀ HƯỚNG PHÁT TRIỂN103 1.1.Các bước triển khai103 1.2.Triển khai Global Store Site. 103 1.3.Cấu hình IIS 7.0 cho Framework MVC sử dụng Microsoft Web Platform Installer104 1.4.Thêm Global Store site vào IIS 7.0. 107 2.1.Hỗ trợ tìm kiếm sản phẩm mở rộng. 109 2.2.Mở rộng chức năng tìm kiếm cửa hàng gần nhất109 2.3.Xây dựng module báo cáo tình hình bán hàng của siêu thị kết xuất ra các tệp định dạng Execel , Pdf109 KẾT LUẬN110 TÀI LIỆU THAM KHẢO111 DANH MỤC HÌNH ẢNH112 GIỚI THIỆU CHUNG Trong chuyên đề tốt nghiệp này em thực hiện việc tìm hiểu ASP.NET MVC , mô hình thương mại điện tử trực tuyến của các chuỗi siêu thị lớn trên thế giới như http://www.bestbuy.com , http://www.walmart.com/ qua đó xây dựng hệ thống thương mại trực tuyến trên nền tảng gồm các module: · Module thành viên và hồ sơ. - Đăng kí tài khoản - Đăng nhập, đăng xuất - Quản lí hồ sơ - Quản lí vai trò người dùng, xóa , tạo vai trò - Quản lí người dùng, tìm kiếm người dùng theo tên – theo email , xóa người dùng, sửa đổi thông tin người dùng · Moudle thương mại - Duyệt toàn bộ các gian hàng trong siêu thị - Xem một gian hàng với danh sách các mặt hàng có trong gian hàng - Xem chi tiết một sản phẩm trong gian hàng , đưa vào giỏ hàng. - Quản lí các gian hàng, tạo một gian hàng - Quản lí các sản phẩm (chỉnh sửa thông tin sản phẩm, xóa sản phẩm), tạo sản phẩm - Quản lí các chọn lựa cách thức giao hàng (xóa, thêm cách thức giao hàng) - Quản lí các đơn đặt hàng (xem chi tiết đơn hàng) · Mudule tin tức – bài báo - blog - Xem toàn bộ bài báo - Xem theo đầu mục, chọn rss - Xem chi tiết , viết lời bình và đánh giá bài báo - Quản lí các đầu mục, tạo đầu mục - Quản lí các bài báo (chỉnh sửa, xóa), tạo bài báo mới - Quản lí các nhận xét bài báo · Module chưng cầu ý kiến khách hàng - Xem các chưng cầu - polls, cho ý kiến (vote) - Quản lí các chưng cầu (chuyển chưng cầu sang trạng thái đã lấy đủ ý kiến - archive, hiện hành, chỉnh sửa chưng cầu, xóa chưng cầu) , tạo chưng cầu mới · Module gửi thư từ hệ thống - Xem ,xóa các thư đã gửi - Tạo thư và gửi · Module định vị cửa hàng siêu thị gần nhất - Tìm các siêu thị trong khoảng cách nhất định - Tìm đường đi tới 1 siêu thị - Thêm vị trí siêu thị mới vào hệ thống · Module Forum - Duyệt các diễn đàn. - Xem các bài thảo luận, tham gia thảo luận , xác nhận thích hay không thích bài thảo luận, tạo bài thảo luận - Quản lí các diễn đàn (chỉnh sửa , xóa diễn đàn) - Quản lí các bài thảo luận (approve, đóng , xóa bài thảo luận) · Module quốc tế hóa - Hiển thị các thông tin địa phương ứng với thông tin địa phương trong hồ sơ người dùng như tiền dùng ở địa phương, thời gian, cách viết con số của địa phương, · Module kiểm thử - Kiểm thử phần bài báo, blog - Kiểm thử phần gửi thư

doc126 trang | Chia sẻ: lvcdongnoi | Lượt xem: 3043 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Tìm hiểu và xây dựng ứng dụng web siêu thị trực tuyến với ASP.NET MVC, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
{ var postId = $(this).attr("meta:id"); $.post( "/forum/removepost", { postId: postId }, function(data) { $("#post-" + data.object.postId).fadeOut("normal", function() { $(this).remove(); }); }, "json" ); return false; }); $(".reply .admin .remove").click(function() { var postId = $(this).attr("meta:id"); $.post( "/forum/removepost", { postId: postId }, function(data) { $("#reply-" + data.object.postId).fadeOut("normal", function() { $(this).remove(); }); }, "json" ); return false; }); Tệp forums.js /********************************************************************************************* * Forum Post *********************************************************************************************/ $("#title").focus(function() { ShowMessage(this, "Enter the title for your post."); }); $("#body").focus(function() { ShowMessage(this, "Enter the body of your post."); }); function ValidateTitle() { return VerifyRequiredField("#title", "required"); } function ValidateBody() { return VerifyRequiredField("#body", "required"); } function ValidatePost() { return ValidateTitle() && ValidateBody(); } $("form.post-create").validate(ValidatePost); /********************************************************************************************* * Rich Text Editor *********************************************************************************************/ var bodyEditor; $(document).ready(function() { bodyEditor = new tinymce.Editor("body", __editorConfig); bodyEditor.onChange.add(function(ed) { bodyEditor.save(); }); bodyEditor.onClick.add(function(ed) { ShowMessage("#body", "Enter the body of your article."); }); bodyEditor.render(); }); // clears the message from the description when another input gets focus $(":input") .focus(function() { HideMessage("#body"); }) .blur(function() { HideMessage("#body"); }); /********************************************************************************************* * Forum *********************************************************************************************/ function VoteSuccess(data) { if (data.object.error) { alert("You must be logged in to vote."); return; } var button = $(".post .vote-" + (data.object.direction > 0 ? "up" : "down")); var number = $(".post strong"); // remove current selections and select correct button $(".post .vote-button a").removeClass("selected"); button.addClass("selected"); // set new count value number.text(data.object.voteCount); } $(".post .vote-button a").click(function() { var postId = $("#postId").val(); var href = $(this).attr("href"); var direction = (href == "#up") ? 1 : -1; $.post( "/forum/vote", { postId: postId, direction: direction }, VoteSuccess, "json" ); return false; }); Cấu hình định tuyến Định tuyến cho người dùng có vai trò editor: routes.MapRoute( "ForumCreate", "editor/forums/create", new { controller = "Forum", action = "CreateForum" } ); routes.MapRoute( "ForumEdit", "editor/forums/edit/{forumId}", new { controller = "Forum", action = "EditForum", forumId = (int?)null }, new { forumId = "[0-9]+" } ); routes.MapRoute( "ForumRemove", "editor/forums/remove/{forumId}", new { controller = "Forum", action = "RemoveForum", forumId = (int?)null }, new { forumId = "[0-9]+" } ); routes.MapRoute( "ForumPostsManager", "editor/forums/posts", new { controller = "Forum", action = "ManagePosts" } ); routes.MapRoute( "ForumManager", "editor/forums", new { controller = "Forum", action = "ManageForums" } ); Các định tuyến cho người dùng với các vai trò còn lại của hệ thống routes.MapRoute( "ForumPostCreate", "forums/{forumId}/post", new { controller = "Forum", action = "CreatePost", forumId = (int?)null }, new { forumId = "[0-9]+" } ); routes.MapRoute( "ForumPostReply", "forums/posts/{parentPostId}/reply", new { controller = "Forum", action = "CreatePost", parentPostId = (int?)null }, new { parentPostId = "[0-9]+" } ); routes.MapRoute( "ForumsIndex", "forums", new { controller = "Forum", action = "Index" } ); routes.MapRoute( "Forum", "forums/{forumId}/{*path}", new { controller = "Forum", action = "ViewForum", forumId = (int?)null, path = (string)null, page = 1 }, new { forumId = "[0-9]+" } ); routes.MapRoute( "ForumPaged", "forums/{forumId}/{path}/page{page}", new { controller = "Forum", action = "ViewForum", forumId = (int?)null, path = (string)null, page = (int?)null }, new { forumId = "[0-9]+" } ); routes.MapRoute( "ForumPost", "forums/posts/{postId}/{*path}", new { controller = "Forum", action = "ViewPost", postId = (int?)null, path = (string)null, page = 1 }, new { postId = "[0-9]+" } ); routes.MapRoute( "ForumPostPaged", "forums/posts/{postId}/{path}/page{page}", new { controller = "Forum", action = "ViewPost", postId = (int?)null, path = (string)null, page = (int?)null }, new { postId = "[0-9]+" } ); Cấu hình trong tệp web.config MODULE BÀI BÁO, TIN TỨC , VÀ BLOG Tổng quan về module Global store với mục tiêu tạo một site thương mại tương tác cao nội dung phong phú nên trong hệ thống có module cho phép người dùng viết bài xung quanh các nội dung về sự kiện nào đó tổ chức tại siêu thị, chia sẻ các hình ảnh về siêu thị ,… Người dùng sử dụng module này có thể xem toàn bộ các bài báo, xem theo đầu mục, xem chi tiết bài báo , viết lời bịnh và đánh giá . Người dùng với vai trò là editor có thêm các chức năng như quản lí các đầu mục báo, tạo đầu mục mới , xóa đầu mục đang có trong hệ thống. Quản lí các bài báo (chỉnh sửa, xóa), tạo bài báo mới Sơ đồ chức năng Hình 3.24 – Sơ đồ chức năng của module bài báo, tin tức , và blog Các bảng dữ liệu Với module này ta sẽ cần ba bảng dữ liệu là Articles (chứa các thông tin liên quan đến các bài báo), Categories (Chứa các thông tin liên quan đến đầu mục các bài báo), Comments (Chứa các thông tin liên quan đến bình luận của các bài báo) Mổi quan hệ giữa bảng Articles với bảng Comments được thiết lập thông qua khóa ngoại là ArticleID với updates và deletes là kiểu Cascade do đó khi xóa một Artile thì các Comments tương ứng với Article đó cũng bị xóa. Tương tự quan hệ giữa 2 bảng Categories và Articles được thiết lập thông qua khóa ngoại là CategoryID với updates và deletes là kiểu do đó khi xóa một Category thì các bài báo thuộc Category đó cũng bị xóa. Hình 3.25 – Sơ đồ bảng Categories, Comments, Articles và quan hệ của chúng Xây dựng lớp ArticleElement cho thiết lập cấu hình của module Các thuộc tính cấu hình trong thành phần nằm trong phần thuộc tệp web.config sẽ được đọc bởi lớp ArticleElement . Lớp này kế thừa từ namespace System.Configuration.ConfigurationElement với thuộc tính thiết lập cấu hình như trong bảng sau. Thuộc tính Mô tả PageSize Số các bài báo mặc định có trên mỗi trang. Phần cấu hình của module bài báo, tin tức, blog trong tệp web.config Model Từ các bảng DL của module trong CSDL của hệ thống ta tạo được các lớp thực thể tương ứng thông quan LINQ-to-SQL như sau: Hình 3.26 – Sơ đồ các lớp thực thể Article, Comment, Category Để hỗ trợ cho việc truy vấn các bảng dữ liệu của module . Vì các lớp thực thể Article, Comment, Category đều là các lớp partial do đó có thể thêm các thuộc tính và phương thức vào các lớp này ở một tệp khác tệp chứa định nghĩa của các lớp đó . Như vậy có thể dễ dàng mở rộng các lớp thực thể LINQ-to-SQL được tạo tự động từ các bảng DL trong CSDL của hệ thống. Như sơ đồ dưới ta có mở rộng cho lớp Article thực thể bằng việc thêm ba thuộc tính AverageRating, Location, Published và 2 phương thức là IncrementViewCount, Rate.Thêm vào đó là một đối tượng ArticleCollectionWrapper Hình 3.27 – Sơ đồ các lớp mở rộng ArticlesQueries, Article, ArticleCollectionWrapper Controller Phương thức hành động Bảo mật Các tham số Index ---- string category, int page CategoryIndex ---- ---- ViewArticle ---- int id, string path RateArticle ---- int articleId, int rating ManageArticle Editor int page ManageCategory Editor ---- ManageComment Editor ---- CreateArticle Editor int? categoryId, string title, string summary, string body, string country, string state,string city, DateTime? releaseDate, DateTime? expireDate, bool? approved, bool? listed, bool? commentsEnabled, bool? onlyForMembers EditArticle Editor int articleId, int? categoryId, string title, string summary, string body, string country, string state, string city, DateTime? release-Date, DateTime? expireDate, bool? approved, bool? listed, bool? commentsEnabled, bool? onlyForMembers RemoveArticle Editor int articleId, string remove CreateCategory Editor string title, int? importance, string imageUrl, string description EditCategory Editor int categoryId, string title, int? importance, string imageUrl, string description RemoveCategory Editor int categoryId, int? newCategoryId,string remove CreateComment ---- int articleId, string name, string email,string body EditComment Editor int commentId, string name, string body RemoveComment Editor int commented View Tên trang Đặc tả Đường dẫn ảo Index.aspx Trang này hiển thị tất cả các bài báo hiện có trong hệ thống article articles/page{page}} articles/categories/{category} articles/categories/{category}/page{page} CategoryIndex.aspx Trang này hiển thị những đầu mục các bài báo articles/categories ViewArticle.aspx Trang này cho phép xem chi tiết bài báo, viết lời bình luận về bài báo, cho điểm bài báo articles/{id}/{*path} ManageArticle.aspx Trang này liệt kê các bài báo hiện có trong hệ thống với hỗ trợ phân trang, và cho phép chỉnh sửa , xóa bài báo editor/articles editor/articles/page{page} ManageCategory.aspx Trang này liệt kê các đầu mục báo hiện có trong hệ thống, và cho phép chỉnh sửa , xóa các đầu mục đó editor/articles/categories ManageComments.aspx Trang này hiển thị tất cả các lời bình theo thứ tự từ trên xuống từ tính theo thời gian và cho phép người dùng với vai trò editor xóa các lời bình đó editor/articles/comments editor/articles/comments/page{page} CreateArticle.aspx Trang này cho phép bạn tạo mới hay chỉnh sửa một bài báo có trong hệ thống editor/articles/create editor/articles/edit/{articleId} CreateCategory.aspx Trang này cho phép bạn tạo mới hay chỉnh sửa một đầu mục báo có trong hệ thống editor/articles/categories/create editor/articles/categories/edit/{categoryId} RemoveArticle.aspx Trang này được dùng để xác nhận lại việc có hay không xóa một bài báo editor/articles/remove/{articleId} RemoveCategory.aspx Trang này được dùng để xác nhận lại việc có hay không xóa một đầu mục báo editor/articles/categories/remove/{categoryId} Sử dụng javascript Tệp manage-category.js được sử dụng để thực thi các hành động phía người dùng trên trang CreateCategory.aspx Phần đầu của tệp này dùng cho thông điệp thông tin cho các mục trong form Create Category $("#title").focus(function () { ShowMessage(this, "Enter the title for your category."); }); $("#importance").focus(function () { ShowMessage(this, "(optional) Enter the order of importance that you want the categories shown in."); }); $("#imageUrl").focus(function () { ShowMessage(this, "The relative web path of an image you want to be shown with articles in this category."); }); $("#description").focus(function () { ShowMessage(this, "Enter a short description of the category to display to your users."); }); Với đoạn mã lệnh trên thì khi các textbox tittle, importance, imageUrl, hay description được sử dụng thì chúng sẽ hiển thị thông điệp được truyền vào phương thức ShowMessage . function ValidateTitle () { return VerifyRequiredField("#title", "required"); } function ValidateImageUrl () { return VerifyRequiredField("#imageUrl", "required"); } function ValidateDescription () { return VerifyRequiredField("#description", "required"); } 3 hàm này thực thi việc đảm bảo các trường title, imageUrl, và description có chứa giá trị bởi lẽ chúng buộc phải có để có thể lưu một bản category vào CSDL. function ValidateCategory () { var validTitle = ValidateTitle(); var validImage = ValidateImageUrl(); var validDescription = ValidateDescription(); return validTitle && validImage && validDescription; } $("form.category-create").validate(ValidateCategory); Hàm cuối cùng này của tệp manage-categories.js thực hiện việc đảm bảo cả ba trường đều phải chứa giá trị . Trong trường hơp cả ba trường đều có chứa giá trị nó sẽ trả về giá trị true và như vậy hệ thống sẽ tiếp tục submit Form tạo Category. Trong các trường hợp còn lại hệ thống sẽ không thể tiếp tục thực hiện việc submit Form nói trên. Tiếp đến là tệp manage-articles.js: Phần đầu của tệp này cũng thực hiện việc tương tự với tệp trên tuy nhiên là cho trang CreateArticles $("#title").focus(function () { ShowMessage(this, "Enter the title for your article."); }); $("#summary").focus(function () { ShowMessage(this, "(optional) Enter a summary for your article to be displayed instead of body."); }); $("#body").focus(function () { ShowMessage(this, "Enter the body of your article."); }); $("#country").focus(function () { ShowMessage(this, "(optional) Enter the country that is associated with this article."); }); $("#state").focus(function () { ShowMessage(this, "(optional) Enter the state that is associated with this article."); }); $("#city").focus(function () { ShowMessage(this, "(optional) Enter the city that is associated with this article."); }); $("#releaseDate").focus(function () { ShowMessage(this, "(optional) This is the date that you want this article to be first show on the site. If left blank todays day is used."); }); $("#expireDate").focus(function () { ShowMessage(this, "(optional) This is the date that you want this article to stop showing on the site."); }); function ValidateTitle () { return VerifyRequiredField("#title", "required"); } function ValidateBody () { return VerifyRequiredField("#body", "required"); } function ValidateArticle () { return ValidateTitle() && ValidateBody(); } $("form.article-create").validate(ValidateArticle); Phần tiếp theo của tệp này được dùng để tạo và gắn một thể hiện của TinyMCE với TextArea có tên là body: var bodyEditor; $(document).ready(function () { bodyEditor = new tinymce.Editor("body", __editorConfig); bodyEditor.onChange.add(function (ed) { bodyEditor.save(); }); bodyEditor.onClick.add(function (ed) { ShowMessage("#body", "Enter the body of your article."); }); bodyEditor.render(); }); Phần code cuối cùng của tệp này dùng để dấu thông điệp của phần body mỗi khi một vùng textbox trên trang CreateArticle được sử dụng: $(":input") .focus(function () { HideMessage("#body"); }) .blur(function () { HideMessage("#body"); }); Tệp manage-comment.js Phần mã lệnh javascript dùng để xóa một comment : $(".remove-comment").click(function () { var id = $(this).attr("meta:id"); $.post( "/article/removecomment", { commentId: id }, function (data) { $("#comment-" + data.object.commentId).next(".admin").fadeOut("slow", function () { $(this).remove() }); $("#comment-" + data.object.commentId).fadeOut("slow", function () { $(this).remove() }); }, "json" ); return false; }); Phần mã lệnh chỉnh sửa comment: $(".edit-comment").click(function () { var id = $(this).attr("meta:id"), comment = $("#comment-" + id), bodyText = comment.find(".body").text(), nameText = comment.find(".name").text(); // hide all the childrend comment.children().hide(); var commentText = ""; commentText += "Commentor's Name"; commentText += "Comment Body" + bodyText + "Update Cancel"; var commentForm = $(commentText); // update the form commentForm.find(".update").click(function () { var id = $(this).attr("meta:id"); var nameFormText = $(this).prevAll(".edit-name").val(); var bodyFormText = $(this).prevAll(".edit-body").val(); $.post( "/article/editcomment", { commentId: id, name: nameFormText, body: bodyFormText }, function (data) { var comment = $("#comment-" + data.object.commentId); comment.children("form").remove(); comment.children(".body").text(data.object.body); comment.children(".name").text(data.object.name); comment.children().show(); }, "json" ); }); // cancel the update commentForm.find(".cancel").click(function () { $(this).parents(".comment").children(":hidden").show(); $(this).parents("form").remove(); }); // add the form to the current comment comment.append(commentForm); return false; }); Tệp article.js Phần code cho điểm một bài báo (rating article) . Để cho điểm một bài báo thì việc đầu tiên là phải gắn kết mã lệnh javascript xử lí việc cho điểm với sự kiện submit trên form cho điểm bài báo để mỗi khi người dùng nhấn nút cho điểm thì một yêu cầu AJAX sẽ được gửi tới phương thức hành động /article/ratearticle: $("form.rate-article").submit(function () { $.post( "/article/ratearticle", { articleId: $("#articleId").val(), rating: $("#rating").val() }, RateArticleSuccess, "json" ); // don't allow submit because this is an ajax request return false; }); Bởi lẽ cái yêu cầu cho điểm này là bất đồng bộ nên ta sẽ cung cấp một phương thức callback là RateArticleSuccess . Phương thức này được gọi khi mà việc cho điểm thành công và trả về trình duyệt của người dùng function RateArticleSuccess (data) { var value = data.object.averageRating; var imagePosition = "50"; if (value <= 1.3) imagePosition = "10"; else if (value <= 1.8) imagePosition = "15"; else if (value <= 2.3) imagePosition = "20"; else if (value <= 2.8) imagePosition = "25"; else if (value <= 3.3) imagePosition = "30"; else if (value <= 3.8) imagePosition = "35"; else if (value <= 4.3) imagePosition = "40"; else if (value <= 4.8) imagePosition = "45"; $("#article-rating-value") .replaceWith(""); $("form.rate-article :input").attr("disabled", "true"); $("form.rate-article").append("Your rating has been applied!"); } Phần code cho xử lí thêm comment cũng như phần cho điểm bài báo phải thực hiện 2 việc : Một là tạo một yêu cầu bất đồng bộ, hai là thực hiện đáp trả yêu cầu function ValidateCommentName () { return VerifyRequiredField("#comment-name", "required"); } function ValidateCommentEmail () { return VerifyRequiredField("#comment-email", "required"); } function ValidateCommentBody () { return VerifyRequiredField("#comment-body", "required"); } function CreateCommentSuccess (data, textStatus) { $(".new-comment").removeClass("new-comment").show("normal"); var commentText = ""; commentText += ""; commentText += "Comment posted by " + data.object.name + " 0 sec ago"; commentText += "" + data.object.body + ""; commentText += ""; var comment = $(commentText); // clear the body box $("#comment-body").val(""); // add the new comment to the other comments comment .hide() .appendTo("#article-comments") .slideDown("slow"); } $("form.comment-create").submit(function () { var valid = ValidateCommentName() && ValidateCommentEmail() && ValidateCommentBody(); if (valid) { $.post( "/article/createcomment", { articleId: $("#articleId").val(), name: $("#comment-name").val(), email: $("#comment-email").val(), body: $("#comment-body").val() }, CreateCommentSuccess, "json" ); } // don't allow submit because this is an ajax request return false; }); Cấu hình định tuyến Phần cấu hình định tuyến các trang dành cho mọi người dùng: routes.MapRoute( "ArticleView", "articles/{id}/{*path}", new { controller = "Article", action = "ViewArticle", id = (string)null, path = (string)null }, new { id = "[0-9]+", path = "[a-zA-Z0-9\\-]*" } ); routes.MapRoute( "ArticleCategoryViewIndex", "articles/categories/{category}", new { controller = "Article", action = "Index", category = (string)null, page = 1 }, new { category = "[a-zA-Z0-9\\-]+", page = "[0-9]+" } ); routes.MapRoute( "ArticleCategoryViewIndexPaged", "articles/categories/{category}/page{page}", new { controller = "Article", action = "Index", category = (string)null, page = (int?)null }, new { category = "[a-zA-Z0-9\\-]+", page = "[0-9]+" } ); routes.MapRoute( "ArticleCategoryIndex", "articles/categories", new { controller = "Article", action = "CategoryIndex" } ); routes.MapRoute( "ArticleIndex", "Articles", new { controller = "Article", action = "Index", category = (string)null, page = 1 } ); routes.MapRoute( "ArticleIndexPaged", "articles/page{page}", new { controller = "Article", action = "Index", category = (string)null, page = (int?)null }, new { page = "[0-9]+" } ); Phần cấu hình định tuyến dành riêng cho người dùng có vai trò editor routes.MapRoute( "ArticleCreate", "editor/articles/create", new { controller = "Article", action = "CreateArticle" } ); routes.MapRoute( "ArticleEdit", "editor/articles/edit/{articleId}", new { controller = "Article", action = "EditArticle", articleId = (int?)null }, new { articleId = "[0-9]+" } ); routes.MapRoute( "ArticleRemove", "editor/articles/remove/{articleId}", new { controller = "Article", action = "RemoveArticle", articleId = (int?)null }, new { articleId = "[0-9]+" } ); routes.MapRoute( "ArticleManage", "editor/articles", new { controller = "Article", action = "ManageArticles", page = 1 } ); routes.MapRoute( "ArticleManagePaged", "editor/articles/page{page}", new { controller = "Article", action = "ManageArticles", page = (int?)null }, new { page = "[0-9]+" } ); routes.MapRoute( "ArticleCategoryCreate", "editor/articles/categories/create", new { controller = "Article", action = "CreateCategory" } ); routes.MapRoute( "ArticleCategoryEdit", "editor/articles/categories/edit/{categoryId}", new { controller = "Article", action = "EditCategory", categoryId = (int?)null }, new { categoryId = "[0-9]+" } ); routes.MapRoute( "ArticleCategoryRemove", "editor/articles/categories/remove/{categoryId}", new { controller = "Article", action = "RemoveCategory", categoryId = (int?)null }, new { categoryId = "[0-9]+" } ); routes.MapRoute( "ArticleCategoryManage", "editor/articles/categories", new { controller = "Article", action = "ManageCategories" } ); routes.MapRoute( "ArticleCommentManage", "editor/articles/comments", new { controller = "Article", action = "ManageComments", page = 1 } ); routes.MapRoute( "ArticleCommentManagePaged", "editor/articles/comments/page{page}", new { controller = "Article", action = "ManageComments", page = (int?)null }, new { page = "[0-9]+" } ); #endregion #endregion #region Polls routes.MapRoute( "PollsIndex", "polls", new { controller = "Poll", action = "Index", page = 1 } ); routes.MapRoute( "PollsIndexPaged", "polls/page{page}", new { controller = "Poll", action = "Index", page = (int?)null }, new { page = "[0-9]+" } ); MODULE QUỐC TẾ HÓA Tổng quan về module GlobalStore Pte. có chuỗi các siêu thị có mặt ở nhiều nước vì vậy hệ thống siêu thị trực tuyến của GlobalStore Pte. cần đáp ứng được việc thể hiện hệ thống dưới nhiều ngôn ngữ khác nhau và sử dụng đúng các số liệu như tiền, cách viết ngày tháng, con số theo địa phương của người sử dụng hệ thống. Người sử dụng hệ thống sẽ chọn lựa chức năng này của hệ thống thông qua quá trình đăng kí hồ sơ hoặc chỉnh sửa hồ sơ chọn ngôn ngữ hiển thị của site. Xây dựng module Các Service hỗ trợ quốc tế hóa trong Framework của Microsoft Namespace System.Globalization cung cấp một số các service hỗ trợ cho việc quốc tế hóa ứng dụng chẳng hạn như lớp CultureInfo được dùng để định dạng ngày và số ứng với những nơi khác nhau. Tất cả các tiến trình của .NET đều xử lí ,theo dấu đối tượng CurrentCulture ( một đối tượng của lớp CultureInfo xác định các định dạng , các thiết lập sắp xếp) và đối tượng CurrentUICulture (cũng là một đối tượng của lớp CultureInfo xác định ngôn ngữ nào được dùng cho văn bản thể hiện trên giao diện người dùng). Visual Studio có chương trình soạn thảo tài nguyên sẵn trong nó và giúp ta có thể trực tiếp quản lí việc dịch các chuỗi sang các ngôn ngữ khác. Trong quá trình phát triển ta có thể truy cập tới các chuỗi này thông qua tính năng intelliSense của Visual Studio bởi lẽ mỗi tài nguyên chuỗi khi được tạo ra thì Visual Studio sẽ sinh ra một lớp với các thuộc tính tác biệt cho mỗi chuỗi tài nguyên. Tại thời điểm chạy chương trình, các thuộc tính này gọi System.Resources.ResourceManager (trình quản lí tài nguyên) để trả về phần dịch chuỗi tài nguyên tương ứng với tiến trình hiện thời của đối tượng CurrentUICulture . Đa số các phương thức định dạng chuỗi đều thực hiện tốt với tiến trình của đối tượng CurrentUICulture có nghĩa là nó sẽ hiển thị chuẩn các thông tin như ngày tháng, con số, và tiền tệ trên giao diện người dùng ứng với Culture hiện hành của UI. Ta hoàn toàn có thể sử dụng tài nguyên ở cấp độ trang với ASP.NET 2.0 trở lên bằng việc xây dựng tài nguyên cho trang cụ thể bên cạnh tài nguyên toàn cục (global resource) Ta có thể gắn kết một điều khiển phía máy chủ với các chuỗi tài nguyên bằng việc sử dụng cú pháp sau "/> Lớp Cultural Information Phương thức Miêu tả CurrentCulture Trả về một đối tượng CultureInfo cung cấp thông tin về văn hóa được sử dụng trong tiến trình hiện hành CurrentUICulture Trả về một đối tượng CultureInfo cung cấp thông tin về văn hóa được sử dụng bởi trình quản lí tài nguyên của hệ thống DateTimeFormat Cung cấp cho bạn đối tượng DateTimeFormatInfo văn hóa cụ thể InstalledUICulture Trả về một đối tượng CultureInfo cung cấp thông tin văn hóa trên hệ điều hành được cài đặt ở máy chủ NumberFormat Cung cấp cho bạn đối tượng NumberFormatInfo như vậy bạn sẽ có các con số , tiền tệ, và phần trăm ứng với một văn hóa cụ thể Xây dựng các tệp tài nguyên Trong hệ thống siêu thị trực tuyến ta sẽ chỉ xây dựng 3 tệp tài nguyên toàn cục (global resouce files) và 2 tệp tài nguyên cục bộ (local resource files) . Mỗi một tệp trong số 3 tệp tương ứng sẽ có một tệp dành cho các thông tin bằng tiếng Anh còn lại là bằng tiếng Việt và một tệp dành cho tiếng Ý. Mỗi một tệp sẽ cung cấp thông tin văn hóa tương ứng như đơn vị tiền tệ,đơn vị phần trăm, cách viết ngày tháng Tạo thư mục App_GlobalResources và trong thư mục này ta sẽ tạo 3 tệp tài nguyên là Message.resx, Message.it-IT.resx và tệp Message.vn-Vn.resx .Việc tạo 3 tệp hết sức đơn giản như hình sau: Hình 3.28 – Tệp Message.resx Hình 3.29 – Tệp Message.vn-VN.resx Hình 3.30 – Tệp Message.it-IT.resx Tạo thư mục localization trong thư mục View,rồi tạo thư mục App_LocalResources trong thư mục localization . Trong thư mục mới tạo này ta sẽ tạo 3 tệp tài nguyên là TestLocalization.resx , TestLocalization.it-IT.resx, Test.Localization.vn-Ve.resx . Việc tạo các tệp các tệp này cũng giống như các tệp trên và được thể hiện như hình vẽ dưới: Hình 3.31 – Tệp TestLocalization.resx Hình 3.32 – Tệp TestLocalization.vn-VN.resx Hình 3.33 – Tệp TestLocalization.it-IT.resx Ghi chú: Vậy là ta đã có đủ dữ liệu để xây dựng thử nghiệm module quốc tế hóa Controller của module Trong thư mục Controller tạo tệp chứa với tên là LocalizationController.cs chứa controller mới của module. Controller này cho phép ta thiết lập văn hóa hiện hành của một tiến trình dựa trên thông tin trong hồ sơ người dùng và định dạng một vài kiểu thông tin theo định dạng tương ứng của văn hóa hiện hành đó: namespace GlobalStore.Controllers { [HandleError] public class LocalizationController : Controller { public ActionResult TestLocalization() { Thread.CurrentThread.CurrentCulture = new CultureInfo(HttpContext.Profile.GetPropertyValue("Language") + "-" + HttpContext.Profile.GetPropertyValue("ContactInformation.Country"), false); Decimal amount = new Decimal(5); ViewData["CurrencyExample"] = String.Format(CultureInfo.CurrentCulture.NumberFormat, "{0:c}", amount); ViewData["PercentageExample"] = String.Format(CultureInfo.CurrentCulture.NumberFormat, "{0:p}", amount); ViewData["NumberExample"] = String.Format(CultureInfo.CurrentCulture.NumberFormat, "{0:N}", amount); ViewData["DateExample"] = Convert.ToDateTime(DateTime.Now, CultureInfo.CurrentCulture.DateTimeFormat); return View("TestLocalization"); } } } View tương ứng của module Để tạo view cho module quốc tế hóa có tính minh họa ta sẽ không cần tạo quá nhiều thông tin mà chỉ cần các thông tin như tiền địa phương , cách viết con số của địa phương , cách viết phần trăm của địa phương, cách viết ngày và thời gian địa phương.. Tạo tệp TestLocalization.aspx trong thư mục Views/Localization như sau: Localized Currency: Localized Numbers: Localized Percentages: Localized Date & Time: MODULE KIỂM THỬ Tổng quan về module Việc kiểm soát mã lệnh theo từng phần bộ phận tách biệt luôn là mong muốn của lập trình viên. Với ứng dụng ASP.NET việc thực hiện Unitest là hầu như không thể. Tuy nhiên thực hiện Unit test với ứng dụng ASP.NET MVC lại dễ dàng và dự án xây dựng với công nghệ .NET MVC có thể kiểm tra được toàn bộ. Tuy nhiên với ứng dụng siêu thị trực tuyến ta chỉ thực hiện kiểm thử với module bài báo , tin tức và blog, và module gửi thư. Code cho module Với module Bài báo, Tin tức , và Blog ta sẽ kiểm thử với phương thức hành động Index (xem tất cả các bài báo có trong hệ thống) , CategoryIndex (xem tất cả các đầu mục báo) : Kiểm thử Index : [TestMethod] public void IndexTest() { ArticleController target = new ArticleController(); ActionResult actual = target.Index("", 0); Assert.IsNotNull(actual); Assert.IsInstanceOfType(actual, typeof(ViewResult)); ViewResult viewResult = actual as ViewResult; Assert.IsNotNull(viewResult.ViewData); Assert.AreEqual("All Articles", viewResult.ViewData["PageTitle"]); var model = viewResult.ViewData.Model as IEnumerable; Assert.IsNotNull(model); } Kiểm thử Category Index: [TestMethod] public void CategoryIndexTest() { ArticleController target = new ArticleController(); ActionResult actual = target.CategoryIndex(); Assert.IsNotNull(actual); Assert.IsInstanceOfType(actual, typeof(ViewResult)); ViewResult viewResult = actual as ViewResult; Assert.IsNotNull(viewResult.ViewData); Assert.AreEqual("All Categories", viewResult.ViewData["PageTitle"]); var model = viewResult.ViewData.Model as IOrderedQueryable; Assert.IsNotNull(model); } Với Module gửi thư ta cũng kiểm thử với phương thức hành động Index của module này và kiểm thử với phương thức hành động ManageNewsleters() trong lớp NewsletterController: Kiểm thử với Index: [TestMethod] public void IndexTest() { NewsletterController target = new NewsletterController(); ActionResult actual = target.Index(); Assert.IsNotNull(actual); Assert.IsInstanceOfType(actual, typeof(ViewResult)); ViewResult viewResult = actual as ViewResult; Assert.IsNotNull(viewResult.ViewData); Assert.AreEqual("Newsletters", viewResult.ViewData["PageTitle"]); } Kiểm thử với ManageNewsletters: [TestMethod] public void ManageNewslettersTest() { NewsletterController target = new NewsletterController(); ActionResult actual = target.ManageNewsletters(); Assert.IsNotNull(actual); Assert.IsInstanceOfType(actual, typeof(ViewResult)); ViewResult viewResult = actual as ViewResult; Assert.IsNotNull(viewResult.ViewData); Assert.AreEqual("Manage Newsletters", viewResult.ViewData["PageTitle"]); var model = viewResult.ViewData.Model as IOrderedQueryable; Assert.IsNotNull(model); } CHƯƠNG 4: SỬ DỤNG WEB FORMS TRONG ỨNG DỤNG ASP.NET MVC TỔNG QUAN VỀ VIỆC KẾT HỢP CÔNG NGHỆ ASP.NET MVC VÀ WEBFORMS TRONG CÙNG MỘT ỨNG DỤNG Các lí do cho sự kết hợp giữa 2 công nghệ Có 2 trường hợp thường xảy ra nhất khi ta có mong muốn kết hợp 2 công nghệ xây dựng ứng dụng nền tảng web vào một ứng dụng đó là: Xây dựng ứng dụng MVC nhưng lại muốn sử dụng công nghệ WebForms trong ứng dụng đó: Có thể bạn muốn tận dụng các trang WebForms,các web control, hay các control người dùng từ các dự án trước đó mà không có đủ thời gian để xây dựng lại tất cả từ đầu sử dụng công nghệ .NET MVC Bạn có một ứng dụng WebForms đã hoàn thiện và muốn nâng cấp ứng dụng đó để hỗ trợ công nghệ MVC. Tại sao có thể thực hiện được sự kết hợp này Kết hợp ASP.NET webforms and ASP.NET MVC vào một ứng dụng là hoàn toàn có thể và thực tế là việc này khá dễ dàng . Lí do là ASP.NET MVC framework được xây dựng dựa trên chính ASP.NET . Thực tế là chỉ có một khác biệt duy nhất đáng quan tâm đó là toàn bộ công nghệ ASP.NET thì gói gọn trong System.Web trong khi ASP.NET MVC thì ngoài nằm trong System.Web nó còn nằm ở System.Web.Routing , System.Web.Abstractions , và System.Web.MVC. Điều này có nghĩa là nếu ta thêm 3 thư viện này vào ứng dụng ASP.NET thì ta có thể kết hợp giữa 2 công nghệ . Với ứng dụng ASP.NET MVC ta có thể trực tiếp thêm các trang webforms vào điều duy nhất ta phải làm là thiết lập thêm định tuyến cho các trang webforms để ASP.NET MVC định tuyến tới các tệp .aspx này. Các bước để kết hợp các trang WebForms vào ứng dụng ASP.NET MVC Trong chuyên đề này em sẽ xây dựng module Store Locator theo công nghệ ASP.NET để minh họa cho việc kết hợp trang WebForms vào ứng dụng ASP.NET MVC . Để thực hiện được trước tiên em sẽ xây dựng các trang webforms của module trong thư mục WebForms sau đó thêm định tuyến cho các trang này vào tệp Global.asxc. MODULE TÌM CỬA HÀNG GẦN NHẤT Tổng quan về module Công ty GLOBAL STORE có các chuỗi cửa hàng ở khắp nơi trên thế giới. Các khách hàng khi mua hàng của Global Store họ thường có nhu cầu tìm cửa hàng gần nơi họ ở nhất theo khoảng cách cho trước là 5, 10,15,20,30,40,50 dặm. Việc tìm kiếm này được thực hiện thông qua module store locator. Trong dự án GLOBAL STORE trực tuyến này CSDL dành cho module store locator sử dụng địa chỉ các cửa hàng của bất kì làm ví dụ minh họa. Địa chỉ cửa hàng mới được thêm vào bởi người dùng có vai trò quản trị (admin) . Sơ đồ chức năng Hệ thống có 2 chức năng như trong phân tích. Một là chức năng tìm kiếm cửa hàng gần nhất dành cho mọi người dùng , một là thêm địa chỉ cửa hàng mới chỉ dành cho người dùng có vai trò quản trị. Hình 4.1 – Sơ đồ chức năng của module Store Locator Phân tích cách xây dựng chức năng Với chức năng tìm kiếm vị trị cửa hàng gần nhất: Thông tin đầu vào: Địa chỉ (ở dạng đầy đủ và mã gửi thư – zip code) mà qua đó người dùng muốn tìm các cửa hàng gần địa điểm (của địa chỉ đó) trong bán kính là một trong các lựa chọn 5, 10,15,20,30,40,50 dặm Kết quả : Hiển thị địa chỉ các cửa hàng nằm trong bán kính đó theo thứ tự về khoảng cách, hiển thị bản đồ Google với các Marker đánh dấu các vị trí tìm được trên bản đồ… ta sẽ phải thực hiện được những việc sau: Xác định được (latitude, longtitude) của vị trí từ địa chỉ có được ở ô dành cho việc điền địa chỉ. Tính được khoảng cách của các cửa hàng có trong CSDL tới địa điểm của địa chỉ đó từ đó chọn ra các cửa hàng gần địa điểm đó trong bán kính yêu cầu. Hiển thị kết quả tìm được. Với chức năng thêm cửa hàng mới : Thông tin đầu vào : Tên cửa hàng, địa chỉ đầy đủ, tên thành phố, tên bang , mã gửi thư. Kết quả đầu ra: lưu toàn bộ thông tin về cửa hàng vào CSDL gồm các thông tin đầu vào và cả thông tin longitude, latitude. Trong trường hợp địa chỉ cửa hàng không xác định hệ thống sẽ đưa ra thông báo cho người dùng. Ta sẽ phải thực hiện việc: Qua Google map api tìm được (longtitude, latitude) của cửa hàng thông qua các thông tin đầu vào. Thực hiện việc lưu thông tin xuống CSDL. Bảng CSDL Theo phân tích chức năng thì ta cần một bảng Location để lưu thông tin vị trí của cửa hàng : Hình 4.2 – Bảng Locations Thủ tục GetNearByLocations: Tính toán và lọc ra các cửa hàng gần người dùng nhất . Thủ tục InsertLocation: Chèn một vị trí mới vào bảng Locations 3 hàm XAxis, YAxis, và ZAxis, được dùng dành cho việc tính toán của thủ tục GetNearByLocations . Các lớp hỗ trợ trong module Trong chức năng tìm kiếm các cửa hàng gần nhất cũng như chức năng thêm cửa hàng vào CSDL việc xác định ta đều cần thông tin (Latitude , Longtitude ) của địa chỉ người dùng nhập và cả 2 thông tin đó đều cần thiết cho việc tính toán khoảng cách của thủ tục GetNearByLocations cũng như cần thiết cho việc hiển thị Marker trên bản đồ Google vậy để xác định được ta phải sử dụng Google Map API và xây dựng lớp GeoCode như sau: namespace GoogleGeocoder { public interface ISpatialCoordinate { decimal Latitude { get; set; } decimal Longitude { get; set; } } /// /// Coordiate structure. Holds Latitude and Longitude. /// public struct Coordinate : ISpatialCoordinate { private decimal _latitude; private decimal _longitude; public Coordinate(decimal latitude, decimal longitude) { _latitude = latitude; _longitude = longitude; } #region ISpatialCoordinate Members public decimal Latitude { get { return _latitude; } set { this._latitude = value; } } public decimal Longitude { get { return _longitude; } set { this._longitude = value; } } #endregion } public class Geocode { private const string _googleUri = ""; private const string _outputType = "csv"; // Available options: csv, xml, kml, json /// /// Returns a Uri of the Google code Geocoding Uri. /// /// The address to get the geocode for. /// A new Uri private static Uri GetGeocodeUri(string address) { string googleKey = ConfigurationManager.AppSettings["googleApiKey"].ToString(); address = HttpUtility.UrlEncode(address); return new Uri(String.Format("{0}{1}&output={2}&key={3}", _googleUri, address, _outputType, googleKey)); } /// /// Gets a Coordinate from a address. /// /// An address. /// /// /// 3276 Westchester Ave, Bronx, NY 10461 /// /// or /// /// New York, NY /// /// or /// /// 10461 (just a zipcode) /// /// /// /// A spatial coordinate that contains the latitude and longitude of the address. public static Coordinate GetCoordinates(string address) { WebClient client = new WebClient(); Uri uri = GetGeocodeUri(address); /* The first number is the status code, * the second is the accuracy, * the third is the latitude, * the fourth one is the longitude. */ string[] geocodeInfo = client.DownloadString(uri).Split(','); return new Coordinate(Convert.ToDecimal(geocodeInfo[2]), Convert.ToDecimal(geocodeInfo[3])); } } } Và trước khi tìm địa chỉ các cửa hàng gần nhất ta sẽ gọi tới hàm GetCoorDinates trong lớp Geocode để lấy Latitude và Longtitude của địa chỉ người dùng nhập vào như sau: //Get the coordinate of the address Coordinate coordinate = Geocode.GetCoordinates(addressTextBox.Text); Ngoài ra ta sẽ phải xây dựng DataSet cho việc chứa các địa chỉ cửa hàng tìm được gần địa chỉ mà khách hàng nhập vào nhất gồm 2 tệp một tệp chứa design của DataSet là LocationsData.xsd ,một tệp chứa code LocationsData.Designer.cs Hình 4.3 – Tệp LocationsData.xsd View Module này có 2 view một dành cho mọi người dùng tìm kiếm siêu thị gần họ nhất , view còn lại chỉ dành cho người dùng có vai trò quản trị để thêm vị trí cửa hàng mới Tên trang Đặc tả Đường dẫn ảo StoreLocator.aspx Trang này cho phép người dùng tìm kiếm siêu thị gần họ nhất Locator/Index AddStoreLocation.aspx Trang này dành cho người dùng với vai trò quản trị thêm vị trí cửa hàng mới vào CSDL Locator/AddStore Thêm định tuyến cho các trang view của module Khi mà ta yêu cầu một trang web sử dụng Url tương ứng với trang đó trên ổ đĩa tức là ta đã hoàn toàn tránh không sử dụng hệ thống định tuyến của ASP.NET MVC. Tuy nhiên trong module này ta muốn yêu cầu trang web StoreLocator.aspx và AddStoreLocation.aspx thông qua hệ thống định tuyến đó bằng cách sử dụng phương pháp: Tạo phương thức sinh URL hướng tới thư mục nằm ngoài thư mục Views . Cụ thể thư mục đó là WebForms. Đây là đoạn code của lớp chứa phương thức đó: //Create route class for WebForms public class WebFormsRoute : Route { //Constructor is hard-coded to use the special WebFormsRouteHandler public WebFormsRoute(string url, string virtualPath) : base(url, new WebFormsRouteHandler { VirtualPath = virtualPath }) { } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { //Only generate outbound URL when "virtual Path" matches this entry string path = ((WebFormsRouteHandler)this.RouteHandler).VirtualPath; if ((string)values["VirtualPath"] != path) return null; else { // var valuesExceptVirtualPath = new RouteValueDictionary (values); valuesExceptVirtualPath.Remove("virtualPath"); return base.GetVirtualPath(requestContext , valuesExceptVirtualPath); } } private class WebFormsRouteHandler : IRouteHandler { public string VirtualPath { get; set; } //Compiles the ASPX file if needed and instantiates the web form public IHttpHandler GetHttpHandler(RequestContext requestContext) { return (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath(VirtualPath, typeof(IHttpHandler)); } } } Ở đây ta đã sử dụng tới lớp BuildManager để định vị, dịch và tạo thể hiện của các trang webforms. Với lớp này ta có thể tạo ngay định tuyến cho các tệp StoreLocator.aspx và AddStoreLocation.aspx trong thư mục WebForms và thêm các định tuyến này vào bảng định tuyến: #region Locator routes.Add(new WebFormsRoute("Locator/Index", "~/WebForms/StoreLocator.aspx")); routes.Add(new WebFormsRoute("Locator/AddStore", "~/WebForms/AddStoreLocation.aspx")); #endregion Ghi chú: Đến đây ta đã hoàn tất việc kết hợp các trang webforms vào dự án asp.net mvc Vấn đề bảo mật Một vấn đề ở đây là chúng ta cần thêm luật xác thực cho định tuyến Urls mới tạo để bảo vệ các trang khỏi kiểu truy cập trực tiếp sử dụng định tuyến đó: CHƯƠNG 5: TRIỂN KHAI ỨNG DỤNG VÀ HƯỚNG PHÁT TRIỂN TRIỂN KHAI ỨNG DỤNG Các bước triển khai Công việc triển khai được chia làm 2 bước: Triển khai cơ sở dữ liệu và triển khai gobal store site. Về phần CSDL do IIS hỗ SQL server express cho nên CSDL này sẽ được gắn với ứng dụng GlobalStore khi ta triển khai ứng dụng này. Ở đây GlobalStore site chỉ sử dụng như là một site nhỏ nên ta chỉ cần dùng SQL server express để chứa CSDL. Triển khai Global Store Site Ta sẽ thực hiện triển khai Global Store Site với chức năng Public từ Visual Studio như hình dưới đây sau khi chạy Visual Studio với vai trò administrator: Hình 5.1 – Triển khai Global Store Site Cấu hình IIS 7.0 cho Framework MVC sử dụng Microsoft Web Platform Installer Công cụ cài đặt Web Platform này là một công cụ mới của Microsoft hỗ trợ cài đặt trọn bộ Web Platform của Microsoft. Sau khi cài công cụ này khởi động nó ta sẽ thấy trên màn hình : Hình 5.2 – Màn hình chọn lựa Paltform để cài đặt Ta phải đảm bảo rằng .NET framework và ASP.NET MVC mới nhất được cài đặt bằng cách nhấn vào link Customize mục Framworks and Runtimes như hình dưới đây nếu đã có dấu tích chìm ứng với các mục cần cài thì tức là chúng đã được cài đặt vào máy của ta. Hình 5.3 – Màn hình kiêm tra các cài đặt của .NET Framework và ASP.NET MVC Kiểm tra xem đã cài SQL Server express 2008 chưa bằng việc chọn liên kết Customize ở mục Database nếu như có dấu tích chìm ở phần SQL Server Express 2008 ở màn hình mới mở ra thì tức là SQL server express 2008 đã được cài đặt. Hình 5.4 – Màn hình kiểm tra việc cài đặt SQL server express 2008 Ghi chú: Ở đây ta đã cài đặt mọi thứ nên không phải cài đặt thêm gì. Thêm Global Store site vào IIS 7.0 Chạy máy chủ quản lí thông tin Internet của Microsoft – IIS 7.0 như trong hình vẽ Hình 5.5 – IIS Manager Nhấn vào node của máy chủ rồi nhấn chuột phải chọn Add Web Site ta sẽ thấy màn hình như sau Hình 5.6 – Add Web Site Dialog Ở đây sẽ cần một số các thiết lập như đặt tên cho site, gán Host header … Hướng phát triển ứng dụng Do thời gian và phạm vi làm chuyên đề tốt nghiệp cũng như hiểu biết còn hạn chế nên em đã chỉ có thể đa phần là áp dụng những kĩ thuật cơ bản trong lập trình ứng dụng nền tảng web sử dụng công nghệ .NET MVC và ASP.NET của Microsft. Trên thực tế hệ thống còn có thể mở rộng theo một số hướng như sau để trở nên hữu ích và hiệu quả hơn. Hỗ trợ tìm kiếm sản phẩm mở rộng Với một hệ thống lớn như Global Store việc xây dựng chức năng tìm kiếm sản phẩm mở rộng là cần thiết giúp khách hàng tiết kiệm được thời gian tìm kiếm cũng như khiến cho hệ thống trở nên hữu ích hơn. Mở rộng chức năng tìm kiếm cửa hàng gần nhất Việc tìm kiếm cửa hàng gần nhất là một tiện ích khá thú vị của hệ thống tuy nhiên mục tiêu cần hướng tới là trong trường hợp khách hàng có lựa chọn sản phẩm vào giỏ hàng thì hệ thống cần thiết phải thông báo cho khách hàng biết sản phẩm mà khách hàng muốn mua đó có hay không có ở các siêu thị mà họ định tới . Ngoài ra cũng cần có các thông tin bổ trợ về siêu thị như giờ mở cửa , giờ đóng cửa ,… Xây dựng module báo cáo tình hình bán hàng của siêu thị kết xuất ra các tệp định dạng Execel , Pdf Đây là một module khá cần thiết cho một ứng dụng kiểu như siêu thị trực tuyến , ông chủ của Global Store Pte luôn có nhu cầu nắm bắt các thông tin bán hàng của từng siêu thị . Để xây dựng được module này ở mức cao như yêu cầu thực tế của những site như www.bestbuy.com hay www.walmart.com không phải là điều dễ dàng xong xây dựng để mô phỏng thì không khó và là cần thiết. KẾT LUẬN Sau khi thực hiện xong chuyên đề tốt nghiệp xây dựng hệ thống siêu thị trực tuyến em đã tìm hiểu được một số công nghệ xây dựng ứng dụng nền tảng web của Microsoft: ASP.NET MVC ASP.NET Tìm hiểu và ứng dụng cách kết hợp 2 công nghệ xây dựng ứng dụng web của Microsoft là ASP.NET MVC và ASP.NET Tìm hiểu và sử dụng các webservices sử dụng trong chức năng thanh toán với Paypal, hay chức năng hiển thị bản đồ Google của module định vị cửa hàng gần nhất. Tìm hiểu và sử dụng AJAX cho các hành động phía Client, kĩ thuật xây dựng bộ nhớ đệm,… TÀI LIỆU THAM KHẢO Tiếng Anh: Về chức năng tham khảo các trang , . ScottGu (5/2007) , Using LINQ to SQL , xem trên blog của ScottGu ( Troy Mageniss (2010), LINQ to Object using C# 4.0, Chapter 3,4 ASP.NET MVC, các bài từ cơ bản đến nâng cao về framework asp.net mvc trên trang dành cho .NET MVC của microsoft ( Steven Sanderson (2009) , Pro ASP.NET MVC framework , p540 tới p546 – Internationlization , p555 tới p576 commbination of ASP.NET and ASP.NET MVC technology in one application. Bear Bibfault, (11/2008), JQuery in action, Chapter 8 Talk to the server with Ajax p217 tới p266. Google developers, Google map API, xem ở ( . Paypal developers, Paypal API , xem ở (https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/howto_api_reference ) DANH MỤC HÌNH ẢNH Hình 1.1 – Kiến trúc ứng dụng – Trang 5 Hình 1.2 - Mối quan hệ giữa các tầng giao diện, logic nghiệp vụ, truy cập CSDL và lưu trữ CSDL – Trang 7 Hình 2.1 – Mô hình MVC cơ bản – Trang 12 Hình 2.2 – Mô hình LINQ to SQL – Trang 17 Hình 2.3 – Mô hình NorthwindDataContext – Trang 19 Hình 2.4 – Hình minh họa lấy sản phẩm từ CSDL với LINQ - Trang 19 Hình 2.5 – Hình minh họa cập nhật sản phẩm từ CSDL với LINQ – Trang 19 Hình 2.6 – Chèn sản phẩm mới vào CSDL – Trang 19 Hình 2.7 – Xóa một sản phẩm – Trang 20 Hình 2.8 – Gọi một thủ tục – Trang 20 Hình 2.9 – Lấy các sản phẩm và phân trang – Trang 21 Hình 3.1 – Các module của hệ thống siêu thị trực tuyến – Trang 22 Hình 3.2 – Sơ đồ tổng quan người dùng và các chức năng của module – Trang 25 Hình 3.3 – Sơ đồ tổng quan chức năng của module theo mô hình UC – Trang 26 Hình 3.4 Bảng Langugage – Trang 26 Hình 3.5 Sơ đồ lớp UserInformation – Trang 28 Hình 3.6 Sơ đồ lớp ProfileInformation – Trang 29 Hình 3.7 Sơ đồ chức năng theo mô hình UC của module thương mại – Trang 34 Hình 3.8 – Các tài khoản kiểm thử với sandbox – Trang 35 Hình 3.8 Sơ đồ quan hệ các bảng dữ liệu trong module thương mại – Trang 37 Hình 3.9 – Sơ đồ các lớp thực thể LINQ-to-SQL của module – Trang 38 Hình 3.10 – Các lớp xây dựng thêm hỗ trợ cho module – Trang 39 Hình 3.11 – Sơ đồ chức năng của module - Trang 50 Hình 3.12 – Bảng Newsletters – Trang 50 Hình 3.13 – Sơ đồ Model Newsletter – Trang 52 Hình 3.14 – Sơ đồ chức năng của module lấy ý kiến người dùng – Trang 54 Hình 3.15 – Sơ đồ mối quan hệ giữa 2 bảng DL của module lấy ý kiến người dùng – Trang 55 Hình 3.16 – Sơ đồ thiết kế bảng PollOptions – Trang 55 Hình 3.17 – Sơ đồ thiết kế bảng Polls – Trang 56 Hình 3.18 – Sơ đồ lớp PollOption và Poll – Trang 57 Hình 3.19 – Sơ đồ lớp PollQueries – Trang 57 Hình 3.20 – Sơ đồ chức năng module Forum – Trang 65 Hình 3.21 – Các bảng dữ liệu của module forum – Trang 66 Hình 3.22 – Sơ đồ các lớp thực thể LINQ-to-SQL Post, Forum , Vote – Trang 67 Hình 3.23 – Sơ đồ lớp ForumQueries – Trang 67 Hình 3.24 – Sơ đồ chức năng của module bài báo, tin tức , và blog – Trang 75 Hình 3.25 – Sơ đồ bảng Categories, Comments, Articles và quan hệ của chúng – Trang 76 Hình 3.26 – Sơ đồ các lớp thực thể Article, Comment, Category – Trang 77 Hình 3.27 – Sơ đồ các lớp mở rộng ArticlesQueries, Article, ArticleCollectionWrapper - Trang 78 Hình 3.28 – Tệp Message.resx – Trang 91 Hình 3.29 – Tệp Message.vn-VN.resx – Trang 91 Hình 3.30 – Tệp Message.it-IT.resx – Trang 92 Hình 3.31 – Tệp TestLocalization.resx – Trang 92 Hình 3.32 – Tệp TestLocalization.vn-VN.resx – Trang 92 Hình 3.33 – Tệp TestLocalization.it-IT.resx – Trang 92 Hình 4.1 – Sơ đồ chức năng của module Store Locator - Trang 96 Hình 4.2 – Bảng Locations – Trang 99 Hình 4.3 – Tệp LocationsData.xsd – Trang 102 Hình 5.1 – Triển khai Global Store Site – Trang 105 Hình 5.2 – Màn hình chọn lựa Paltform để cài đặt – Trang 106 Hình 5.3 – Màn hình kiêm tra các cài đặt của .NET Framework và ASP.NET MVC – Trang 107 Hình 5.4 – Màn hình kiểm tra việc cài đặt SQL server express 2008 – Trang 108 Hình 5.5 – IIS Manager – Trang 109 Hình 5.6 – Add Web Site Dialog – Trang 110

Các file đính kèm theo tài liệu này:

  • docTìm hiểu và xây dựng ứng dụng web siêu thị trực tuyến với ASPNET MVC.doc
Luận văn liên quan