Để 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:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" culture="auto"
meta:resourcekey="PageResource1" uiculture="auto" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h1><%=
HttpContext.GetLocalResourceObject("~/Views/Localization/TestLocalization",
"Title", System.Globalization.CultureInfo.CurrentUICulture)%></h1>
<h3><%= HttpContext.GetGlobalResourceObject("Messages", "LocalGreeting", System.Globalization.CultureInfo.CurrentUICulture)%></h3>
<p><%=
HttpContext.GetLocalResourceObject("~/Views/Localization/TestLocalization",
"Message", System.Globalization.CultureInfo.CurrentUICulture)%></p> <p><b>Localized Currency:</b> <%= ViewData["CurrencyExample"] %></p> <p><b>Localized Numbers:</b> <%= ViewData["NumberExample"] %></p>
<p><b>Localized Percentages:</b> <%= ViewData["PercentageExample"] %></p> <p><b>Localized Date & Time:</b> <%= ViewData["DateExample"] %></p>
<p><b><%= HttpContext.GetLocalResourceObject("~/Views/Localization/TestLocalization", "Copywrite", System.Globalization.CultureInfo.CurrentUICulture)%></b></p> </asp:Content> 9. MODULE KIỂM THỬ 9.1. 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ư.
9.2. 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);
ViewResult viewResult = actual as ViewResult; Assert.IsNotNull(viewResult.ViewData);
Assert.AreEqual("All Articles", viewResult.ViewData["PageTitle"]); var model = viewResult.ViewData.Model as IEnumerable<Article>; 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<Category>; 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]
{
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<Newsletter>;
Assert.IsNotNull(model); }
CHƯƠNG 4: SỬ DỤNG WEB FORMS TRONG ỨNG DỤNG ASP.NET MVC
1. 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 1.1. 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à:
1. 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
2. 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.
1.2. 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.
1.3. 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
uc Store Locator
Administrator
(from Actors)
User
(from Actors)
Locate Stores Add new store
Để 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.
2. MODULE TÌM CỬA HÀNG GẦN NHẤT 2.1. 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áchcho 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) .
2.2. 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
2.3. 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 đồ…
- 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.
2.4. 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ầnngườ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
2.5. 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; } }
///<summary>
/// Coordiate structure. Holds Latitude and Longitude.
///</summary>
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 {
} set { this._longitude = value; } } #endregion }
public class Geocode {
private const string _googleUri = "http://maps.google.com/maps/geo?q="; private const string _outputType = "csv"; // Available options: csv, xml, kml, json
///<summary>
/// Returns a Uri of the Google code Geocoding Uri.
///</summary>
///<param name="address">The address to get the geocode for.</param> ///<returns>A new Uri</returns>
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));
}
///<summary>
/// Gets a Coordinate from a address.
///</summary>
///<param name="address">An address.
/// <remarks> /// <example>
/// 3276 Westchester Ave, Bronx, NY 10461
/// /// or /// /// New York, NY /// /// or /// /// 10461 (just a zipcode) /// </example> /// </remarks> ///</param>
///<returns>A spatial coordinate that contains the latitude and longitude of the
address.</returns>
{
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
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
2.7. 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(newWebFormsRoute("Locator/Index", "~/WebForms/StoreLocator.aspx"));
routes.Add(newWebFormsRoute("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
2.8. 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 đó:
<!-- Configuration Extension For Preventing Direct Access To Web Form Pages--> <location path="Locator/AddNewStore"> <system.web> <authorization> <allow roles="Admin"/> <deny users="*"/> </authorization> </system.web> </location> <location path="WebForms/AddStoreLocation.aspx"> <system.web>
</system.web> </location>
CHƯƠNG 5: TRIỂN KHAI ỨNG DỤNG VÀ HƯỚNG PHÁT TRIỂN
1. TRIỂN KHAI ỨNG DỤNG
1.1. 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.
1.2. 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
1.3. Cấu hình IIS 7.0 cho Framework MVC sử dụng Microsoft Web Platform Installer 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 :
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.
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
1.4. 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ẽ
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
2. 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.
2.1. 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.
2.2. 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