[譯]MVC網站教程(一):多語言網站框架


本文簡介

本博文介紹了 Visual Studio 工具生成的 ASP.NET MVC3 站點的基本框架;怎樣實現網站的語言的國際化與本地化功能,從零開始實現用戶身份認證機制,從零開始實現用戶注冊機制,實現自定義的MVC驗證特性……

本系列包含四篇,在codeproject中都評級為4+顆星。我會全部翻譯出來,感興趣的園友可以關注我的博客。

1)   MVC網站教程(一):多語言網站框架

2)   MVC網站教程(二):異常管理

3)   MVC網站教程(三):動態布局和站點管理(涉及技術:AJAX、jqGrid、Controller擴展、HTML Helpers等等)

4)   MVC網站教程(四):MVC4網站中集成jqGrid表格插件(涉及技術:AJAX,JSON,jQuery,LINQ和序列化)

 

在運行示例代碼之前

在運行示例代碼之前,你應該做下面事情:

1.        在你的SQL Server服務器中創建一個名為MvcBasicSite的數據庫,然后用我提供的MvcBasicSiteDatabase.bak文件進行數據庫還原。

2.        修改MVC示例應用程序中Web.config文件中的鏈接字符串。

 

本博文示例下載:

1)   ASP.NET MVC 3.0 For VS2010 安裝文件

2)   多語言網站框架—示例源代碼

3)   多語言網站框架—數據庫bak

 

介紹

MVC網站教程”系列的目的是教你如何使用 ASP.NET MVC 創建一個基本的、可擴展的網站。

ASP.NET MVC 是微軟提供的一個web開發框架,它整合MVCModel View Controller)架構模式的高效與簡潔,並從敏捷開發中吸取了最新的概念和技術……融入ASP.NET平台。

clip_image001

 

MVC應用程序包含下面幾個組件:

1)   Models:模型對象,做為應用程序的數據域,通常,模型對象在數據庫中檢索和存儲它們的狀態。

2)   Views:視圖,(模型對象提供數據,)顯示應用程序的用戶界面。

3)   Controllers:控制器,處理用戶交互信息,與model協同工作,最后選擇一個view顯示處理結果頁。

 

本文是“MVC網站教程”系列的首篇,主要講解如何去創建一個多語言MVC網站,同時也講解了用戶認證和注冊機制的實現。使用了微軟的Entity Framework框架和LINQ查詢技術。

從用戶界面的角度來看,本文提供的MVC網站框架包括:主頁面(主要布局項:菜單,頁眉,頁腳),“Home”和“About”導航索引,實現“LogOn(登陸)”和“Register(注冊)”功能頁,還提供通用的用戶信息和地址信息編輯的部分功能頁(_UserAndAddress.cshtml)

    整個用戶界面語言完全實現國際化與本地化功能,提供三種語言支持:EnglishRomanian (Română) German (Deutch)。並且支持擴展其他語言。

clip_image003

    當用戶通過上圖右上角的下拉列表改變用戶語言時,用戶界面的文本、數字、驗證信息和錯誤提示消息都將從這一刻更改為特定的語言。

 

軟件環境

1.   .NET 4.0 Framework

2.   Visual Studio 2010 (or Express edition)

3.   ASP.NET MVC 3.0

4.   SQL Server 2008 R2 (or Express Edition version 10.50.2500.0, or higher version)

 

網站框架

本文示例的解決方案包含兩個項目:

1.   MvcBasicSite:是ASP.NET MVC 3站點項目。包含部分Models、所有Views和所有Controllers,還包含其他用戶資源文件和相關代碼。下面會進行詳細介紹。

2.   MvcBasic.Logic:是一個類庫項目。包含Entity Framework的實體映射圖(.edmx),以及自動生成的相關實體部分類,和手動創建的邏輯實體部分類。這個項目將在“MVC網站教程”系列的第二篇中詳細介紹。

clip_image004

上圖,是ASP.NET MVC3 項目自動生成的文件架構:

1.   App_code:可選特殊文件夾,包含應用程序級別代碼。如在本示例中,該文件夾包含一個Content.cshtml文件,它定義了一個Razor語法的 @helper幫助器方法,編譯器會將其編譯為“Content”(和文件名一樣)的類,你可以在應用程序的任何視圖模版中使用該幫助器方法。(該文件夾下的文件在應用程序運行時動態編譯為程序集並且自動鏈接到應用程序,而不需要手動添加程序集引用。但是,需要注意的是該文件夾的更改會導致整個應用程序重新編譯。對於大型項目,因為很耗時,這可能不受歡迎。為此,鼓勵大家將代碼進行模塊化處理到不同的類庫中)

2.   App_Data:可選特殊文件夾,包含數據的物理存儲文件。本示例中為空文件夾。

3.   App_GlobalResources:可選特殊文件夾,包含用於實現應用程序多語言特性的資源文件。注意,文件的命名非常重要,並且每一個資源文件包含站點中每個要顯示文本的特定語言版本。在本示例中包含3個特定語言的資源文件:

1)   Resource.resx:是默認資源文件,關聯 English 語言。

2)   Resource.de.resx:是關聯 German 語言的資源文件。(語言代碼:de-DE

3)   Resource.ro.resx:是關聯 Romanian 語言的資源文件。(語言代碼:ro-RO

4.   Content:是靜態文件推薦存放的文件夾,比如CSS,圖片,主題等等。在本示例中,該文件夾存放有:

1)   Images:子文件夾,包含圖片文件(gifpng…)。

2)   Theme:子文件夾,包含基本的jQueryUI主題的css文件。

3)   dd.css:改變語言的下拉列表控件的樣式文件。

4)   site.css:站點主要的css文件。

5.   Controllers:這是控制器Controller推薦存放的文件夾,在MVC架構中控制器需要以”Controller”的文件名結尾。在本示例中該文件夾包含三個控制器:

1)   BaseController:基本控制器,是本示例中其他Controller的基類,提供公共數據和公共函數。

2)   AccountController:管理用戶注冊,登陸和退出。

3)   HomeController:管理導航頁“Home”和“About”的操作。

6.   ModelMVC網站應用程序的數據模型集合。在本示例中真實的模型對象被放在MvcBasic.Logic類庫項目中(即與數據庫表對應的模型對象Domain Model)。在Model文件夾下只包含2個類文件。

1)   LogOnModel:此模型用於LogOn頁面的用戶身份認證功能。

2)   SiteSession:此模型用於保存站點的特定用戶會話信息,egUserIdUsernameUserRoleCurentUICulture

7.   Scripts:這是應用程序腳本文件推薦存放的文件夾。創建MVC項目默認會包含ASP.NET AJAX腳本庫和jQuery腳本庫。

8.   Views:這是應用程序視圖推薦存放的文件夾。該文件夾針對每個控制器都對應一個子文件夾,子文件夾命名為對應控制器的前綴。默認情況下,還有個命名為Shared的子文件夾,它不對應任何控制器,但包含被多個控制器共享的視圖。在本示例中該文件夾包含以下子文件夾:

1)   Account:控制器AccountController對應的視圖。

a)   Logon.cshtml:用於用戶的身份認證。

b)   Register.cshtml:用於用戶的注冊。

c)   RegisterFinalized.cshtml:用於用戶成功注冊。

2)   Home:控制器HomeController對應的視圖。包含About.cshtmlIndex.cshtml頁面。

3)   Shared:包含被多個控制器共享的視圖。

a)   _Address.cshtml:部分視圖,用於地址數據的編輯。

b)   _Header.cshtml:部分視圖,用於網站的頁眉。

c)   _Layout.cshtml:母版頁,是站點的主要布局風格。

d)   _UserAndAddress.cshtml:部分視圖,用於用戶數據和其對應的地址數據的編輯。

e)   Error.cshtml:錯誤頁面,用於顯示站點的異常信息。

4)   _ViewStart.cshtml:指定整個站點使用的布局模版頁URL

5)   Web.config:網站配置文件,僅僅作用於視圖頁面。通常情況下無需手動更改。

9.   Global.asax:包含MvcApplication類(繼承自HttpApplication),用於設置全局URL路由規則,也管理一些全局事件如Session_End

10.packages.config:是NuGet的基礎設施,用於跟蹤擴展安裝包以及版本信息。

11.Web.config:網站的主要配置文件。包含Web.Debug.configWeb.Release.config兩個版本。

clip_image006

從上圖中,我們得知BaseController類包含兩個成員:

1)   _db:是一個MvcBasicSiteEntities類型的上下文對象,用於從數據庫中訪問站點的實體數據。

2)   CurrentSiteSession:是一個SiteSession類型的屬性,用於訪問當前登錄用戶的重要數據,它緩存在Session會話中。通過這種方式保存了用戶的重要信息,包括:UserIdUsernameUserRoleCurentUICulture等。

 

所有該MVC站點的控制器都將繼承自BaseCOntroller類,因為這個類提供了公共數據SiteSession和通過重寫 ExecuteCore() 方法實現程序國際化和本地化功能,該類還通過重寫 OnException() 方法管理未處理異常。

 

從零開始實現用戶身份認證機制

    當你創建一個新的 ASP.NET MVC 項目時,Visual Studio 工具可以幫助我們生成默認的用戶認證機制,即membership機制與生成其關聯的SQL數據庫及表。這種方式在大部分應用程序中是可以的,但是在項目實際情況下你可能不想使用membership機制(eg:你已經有與其他軟件公用用戶數據表),所以在這些場景從零開始實現自己的用戶認證機制是非常有用的。

    LogOnModel是用戶認證的模型對象。它包含兩個標注驗證特性的屬性,這些驗證特性使用多語言資源文件的文本描述錯誤信息。

 

Note 1:對於模型對象的每個驗證信息,我們應該在每個語言資源文件中添加相同的資源鍵並關聯到模型。資源文件中的文本必須轉換為其對應的語言版本。

[Required(ErrorMessageResourceType = typeof(Resource), ErrorMessageResourceName =  "ValidationRequired")]
[DataType(DataType.Password)]
public string Password { get; set; }

    在上例,Password屬性標注了兩個特性:

1)   DataType:指定這是密碼字段,所以文本不能顯示為明文。

2)   Required:用於驗證,並有兩個屬性:

a)   ErrorMessageResourceType:指定驗證錯誤信息將從特定的資源文件中讀取。(注意命名是不帶任何后綴的(如.de.resx.ro.resx),因為選擇哪個資源文件是由用戶動態選擇的,應用程序將在BaseController中根據用戶會話信息進行匹配)

b)   ErrorMessageResourceName:指定資源文件中要顯示的資源鍵。

AccountController控制器實現了完整的用戶身份認證和注冊機制,並且管理整個站點當前語言環境的改變。當用戶單擊右上角的Logon連接時將觸發AccountController控制器LogOn操作。

public ViewResult LogOn()
{
    //
    // Create the model.
    //
    LogOnModel model = new LogOnModel();
    model.Username = string.Empty;
    model.Password = string.Empty;
    //
    // Activate the view.
    //
    return View(model);
}

    這個方法創建一個新的LogOnModel模型對象,並將它傳遞給LogOn.cshtml視圖。

 

    請看下面例子,在LogOn.cshtm視圖中,所有文本信息如titleheadlabellinkbutton都是通過語法 @Resource.ResourceKeyName 將顯示文本與資源文件文本關聯起來。所有文本框textbox都擁有兩個指令,第一個指令通過 @Html.TextBoxFor 語法關聯到模型對象屬性;第二個指令通過 @Html.ValidationMessageFor 語法關聯到驗證信息。

<div class="editor-label"/>
    @Resource.LogOnModelUsername
</div/>
<div class="editor-field"/>
    @Html.TextBoxFor(m => m.Username)
    @Html.ValidationMessageFor(m => m.Username)
</div/>

 

Note 2:解決方案中的每個視圖,所有在用戶界面使用的文本項信息(egtitleheadlinklabelbutton等等)都應該通過資源文件獲取。並且這些文本項信息在每個特定語言的資源文件中都應該存在對應鍵。

    用戶認證功能先使用在LogOnModel模型對象上設置的驗證規則做基本的數據驗證,然后再觸發AccountController控制器上的LogOn方法。

[HttpPost]
public ActionResult LogOn(LogOnModel model)
{
    if (ModelState.IsValid)
    {
        //
        // Verify the user name and password.
        //
        User user = _db.Users.FirstOrDefault(item => 
            item.Username.ToLower() == model.Username.ToLower() 
            && item.Password == model.Password);
        if (user == null)
        {
            ModelState.AddModelError("", Resources.Resource.LogOnErrorMessage);
            //
            return View(model);
        }
        else
        {
            //
            // User logined succesfully ==> create a new site session!
            //
            FormsAuthentication.SetAuthCookie(model.Username, false);
            //
            SiteSession siteSession = new SiteSession(_db, user);
            Session["SiteSession"] = siteSession; // Cache the user login data!
            //
            return RedirectToAction("Index", "Home");
        }
    }
    //
    // If we got this far, something failed, redisplay form!
    //
    return View(model);
}

LogOn方法將驗證用戶的namepassword,並在出錯的時候將錯誤信息顯示在LogOn.cshtml視圖頁面。若無錯則登陸成功,會創建一個SiteSession對象用於存儲用戶登陸數據,然后將SiteSession對象緩存到當前的HTTP會話中,最后用戶被重定向到home站點頁面(即Index.cshtml視圖)。

 

改變並且緩存當前環境語言

    當用戶通過用戶界面改變當前語言環境時,將觸發AccountController控制器的ChangeCurrentCulture操作。

public ActionResult ChangeCurrentCulture(int culture)
{
    //
    // Change the current culture for this user.
    //
    SiteSession.CurrentUICulture = culture;
    //
    // Cache the new current culture into the user HTTP session. 
    //
    Session["CurrentUICulture"] = culture;
    //
    // Redirect to the same page from where the request was made! 
    //
    return Redirect(Request.UrlReferrer.ToString());
}

    在上面代碼中,SiteSession類中靜態屬性CurrentUICulture被調用。

 

public static int CurrentUICulture
{
    get
    {
        if (Thread.CurrentThread.CurrentUICulture.Name == "ro-RO")
            return 1;
        else if (Thread.CurrentThread.CurrentUICulture.Name == "de-DE")
            return 2;
        else
            return 0;
    }
    set
    {
        //
        // Set the thread's CurrentUICulture.
        //
        if (value == 1)
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("ro-RO");
        else if (value == 2)
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
        else
            Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
        //
        // Set the thread's CurrentCulture the same as CurrentUICulture.
        //
        Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture;
    }
}

從上面代碼可以得知,CurrentUICulture屬性可以獲取或設置當前使用語言環境,並且返回具有特定意義的int值(即:0 = InvariantCulture, 1 = ro-RO, 2 = de-DE)。

    注意,當前使用的語言環境是設置在服務器響應請求的當前線程上,並且客戶端每次請求都會丟失。

    為了重新找回當前語言環境,我們在BaseController類中重寫保護方法ExecuteCore方法,並且設置SiteSession對象的CurrentUICulture屬性值。ASP.NET MVC會在操作控制器上任何一個操作之前自動調用ExecuteCore方法。

protected override void ExecuteCore()
{
    int culture = 0;
    if (this.Session == null || this.Session["CurrentUICulture"] == null)
    {
        int.TryParse(System.Configuration.ConfigurationManager.AppSettings["Culture"], out culture);
        this.Session["CurrentUICulture"] = culture;
    }
    else
    {
        culture = (int)this.Session["CurrentUICulture"];
    }
    //
    SiteSession.CurrentUICulture = culture;
    //
    // Invokes the action in the current controller context.
    //
    base.ExecuteCore();
}

我們還能從上面代碼中得知,當用戶第一次訪問應用程序時,會從web.config配置文件中讀取默認的語言環境。

 

從零開始實現用戶注冊機制

    當我們創建一個新的ASP.NET MVC項目時,Visual Studio開發工具自動生成的架構也會包含用戶注冊機制,和用戶驗證機制一樣使用ASP.NET membership機制實現。在這個解決方案中,我從零開始實現一個可擴展的用戶注冊機制,它使用兩個可重用的部分視圖。將在“MVC網站教程”系列的第二篇中詳細介紹。

    用戶注冊頁面可以通過LogOn頁面的”Register”鏈接觸發。

clip_image008

    在上圖,你能看到所有菜單、label文本、button文本和用戶注冊驗證信息被顯示為German語言。因為在頁面右上角將當前環境語言設置為”Deutch”。這些驗證機制是通過在UserAddress實體類上設置驗證規則實現的。(將在“MVC網站教程”系列的第二篇中詳細介紹)

    所以用戶必須填寫正確的信息,然后繼續注冊,控制器會調用AccountController.Register()方法。

[HttpPost]
public ViewResult Register(User model, Address modelAddress)
{
    if (ModelState.IsValid)
    {
        //
        // Verify if exists other user with the same username.
        //
        User existUser = _db.Users.FirstOrDefault(item => 
            item.Username.ToLower() == model.Username.ToLower());
        if (existUser == null)
        {
            //
            // Save the user data.
            //
            MvcBasic.Logic.User user = new MvcBasic.Logic.User();
            user.Username = model.Username;
            user.Password = model.Password;
            user.UserRole = UserRoles.SimpleUser;
            user.Email = model.Email;
            //
            if (modelAddress.CountryID <= 0)
                modelAddress.CountryID = null;
            //
            user.Address = modelAddress;
            //
            _db.Users.AddObject(user);
            _db.SaveChanges(); 
            //
            // Go to RegisterFinalized page!
            //
            return View("RegisterFinalized");
        }
        else
        {
            //
            // Exists other user with the same username, so show the error message.
            //
            ModelState.AddModelError("", Resources.Resource.RegisterInvalidUsername);
            model.Address = modelAddress;
            //
            return View(model);
        }
    }
    //
    // If we got this far, something failed, redisplay form!
    //
    model.Address = modelAddress;
    //
    return View(model);
}

    該方法會檢查是否已經存在相同用戶名的用戶,如果存在,注冊頁面將收到一條錯誤提示信息,並且用戶需要更改其用戶名;若不存在,將創建一個新用戶並保存到數據庫中,然后顯示RegisterFinalized.cshtml頁面。

 

數據實體模型和邏輯類

    MvcBasic.Logic項目中,我添加了一個“ADO.NET 實體數據模型”的新項(*.edmx),然后將其與數據庫表進行關聯,最后對每個實體對象都創建了一個單獨的擴展部分類文件,這些部分類包含了實體額外的操作邏輯。

clip_image010

    因此,MvcBasic.Logic項目中包含的手動創建的部分類與自動生成的實體部分類相關聯,手動創建的部分類中還包含其他一些業務邏輯。這個項目包含了如下類:

1)   MvcBasicSiteEntities:是主要數據上下文,用於從數據庫中獲取數據存入實體對象集合。

2)   User:是與數據庫中存儲用戶數據的Users表相關聯的實體類,這個模型類用於Register視圖和_UserAndAddress部分視圖。

3)   Address:是與數據庫中存儲地址數據的Addresses表相關聯的實體類,這個模型類用於_Address部分視圖。

4)   Country:是與數據庫中存儲城市數據的Countries表相關聯的實體類。

5)   UserValidation:為User實體定義驗證規則和錯誤提示信息。所有屬性都有驗證特性,它們的錯誤文本都來自當前項目的資源文件,就像下面示例:

[Required(ErrorMessageResourceType = typeof(Resource), ErrorMessageResourceName = "ValidationRequired")]
[Email(ErrorMessageResourceType = typeof(Resource), ErrorMessageResourceName = "ValidationEmail")] 
[Compare("Email", ErrorMessageResourceType = typeof(Resource), ErrorMessageResourceName = "ValidationComfirmEmail")]
[DataType(DataType.EmailAddress)]
[StringLength(128)]
public string ComfirmEmail { get; set; }

6)   AddressValidation:為Address實體定義驗證規則和錯誤提示信息。

7)   EmailAttribute:擴展基類RegularExpressionAttribute並且通過正則表達式實現郵箱驗證。這個特性用於UserValidation類的Email屬性來驗證用戶郵箱。

8)   EmailValidationRule:擴展基類ModelClientValidationRule並且定義郵箱驗證規則。

    注意,在示例中的驗證類中,所有特性使用的驗證信息都來自MvcBasic.Logic項目中的資源文件。

    實體類和驗證類是通過在實體類上定義MetadataType特性將它們關聯起來的。

 

 

    本文翻譯到此結束,如果喜歡本系列翻譯分享,還請多幫推薦!!!

 

原文鏈接:MVC Basic Site: Step 1 – Multilingual Site Skeleton

作者:Raul Iloc

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM