(002).NET大型B2C开源项目nopcommerce解析——安装页面

        本文主要介绍安装页面涉及到实现的功能以及原理。

        初次启动nopcommerce会进入一个URL为”/install”的页面,这个页面涉及到了2个功能:1.页面全球化;2.数据准备工作。

0.储备知识

特性

javascript事件

cookie

多活动结果集

1.页面全球化

1.1显示区域文字

        在安装页面右下角有一个选择区域语言功能,可以看到里面有相当多的语言可供选择。选择完对应区域后,页面的文字也会相应变化。

        页面全球化有一种最简单的实现就是分文件夹建站,比如微软的MSDN,但是同一个页面共有的基础设计恐怕非常冗余——我是指最差的情况。

        而微信的实现则是路由参数,比如。

        nopcommerce的页面是强类型视图。开发者在Nop.Web-InstallController-Index()里定义好了视图模型InstallModel然后往页面输出。

[Validator(typeof(InstallValidator))]
    public partial class InstallModel : BaseNopModel
    {
        public InstallModel()
        {
            this.AvailableLanguages = new List<SelectListItem>();
        }
        [AllowHtml]
        public string AdminEmail { get; set; }
        [AllowHtml]
        [DataType(DataType.Password)]
        public string AdminPassword { get; set; }
        [AllowHtml]
        [DataType(DataType.Password)]
        public string ConfirmPassword { get; set; }


        [AllowHtml]
        public string DatabaseConnectionString { get; set; }
        public string DataProvider { get; set; }
        public bool DisableSqlCompact { get; set; }
        //SQL Server properties
        public string SqlConnectionInfo { get; set; }
        [AllowHtml]
        public string SqlServerName { get; set; }
        [AllowHtml]
        public string SqlDatabaseName { get; set; }
        [AllowHtml]
        public string SqlServerUsername { get; set; }
        [AllowHtml]
        public string SqlServerPassword { get; set; }
        public string SqlAuthenticationType { get; set; }
        public bool SqlServerCreateDatabase { get; set; }

        public bool UseCustomCollation { get; set; }
        [AllowHtml]
        public string Collation { get; set; }


        public bool DisableSampleDataOption { get; set; }
        public bool InstallSampleData { get; set; }

        public List<SelectListItem> AvailableLanguages { get; set; }
    }

        这里特性和继承基类先不要管。大致说明一下就是,这个特性是视图验证框架FluentValidation用的,而父类是领域对象基类。

        页面设计地区区域的字符串通过GetResource(string resourceName)方法统一生成。

/// <summary>
        /// Get locale resource value
        /// </summary>
        /// <param name="resourceName">Resource name</param>
        /// <returns>Resource value</returns>
        public string GetResource(string resourceName)
        {
            var language = GetCurrentLanguage();
            if (language == null)
                return resourceName;
            var resourceValue = language.Resources
                .Where(r => r.Name.Equals(resourceName, StringComparison.InvariantCultureIgnoreCase))
                .Select(r => r.Value)
                .FirstOrDefault();
            if (String.IsNullOrEmpty(resourceValue))
                //return name
                return resourceName;

            return resourceValue;
        }

        这个方法的总流程(包括调用的子方法)是:

  1. 获取“nop.installation.lang”的cookie值
  2. 遍历并读取“/App_Data/Localization/Installation/”目录下符合命名要求(正则表达式)的XML文件,将其中子节点信息(页面所用字符串)储存在InstallationLanguage对象中,将 根节点(<Language Name="简体中文" IsDefault="false" IsRightToLeft="false">)储存在List<InstallationLocaleResource> 中。
  3. 根据List<InstallationLocaleResource>中的Code属性匹配cookie值,得出当前语言对象InstallationLanguage
  4. 如果cookie匹配不上(没有cookie),则根据浏览器中Request.UserLanguages的首选项(httpContext.Request.UserLanguages.FirstOrDefault())匹配Code属性
  5. 如果还是匹配不上,则返回IsDefault属性为true的XML对应的InstallationLanguage
  6. 如果完全匹配不上,则返回任意XML对应的InstallationLanguage
  7. 如果出什么意外,GetCurrentLanguage返回null的话就直接输出传过来的字符串
  8. 如果没什么意外的话就根据字符串在 List<InstallationLocaleResource>匹配符合条件的信息并返回

以上操作涉及到的实现类主要是InstallationLocalizationService。

        而功能就完成了。

1.2变更区域文字

        页面输出的下拉框是这样子的:

        nopcommerce的实现则是下拉框变更触发onchange事件(onchange="window.location.href = this.value;"),继而发出get请求页面。

        从结果上看页面的路由没有变化,但其实这是ChangeLanguage重定向的结果:

public ActionResult ChangeLanguage(string language)
        {
            if (DataSettingsHelper.DatabaseIsInstalled())
                return RedirectToRoute("HomePage");

            _locService.SaveCurrentLanguage(language);

            //Reload the page
            return RedirectToAction("Index", "Install");
        }

        而中间的_locService.SaveCurrentLanguage(language);将名为“nop.installation.lang”的cookie的值变更为请求的语言类型。

public virtual void SaveCurrentLanguage(string languageCode)
        {
            var httpContext = EngineContext.Current.Resolve<HttpContextBase>();

            var cookie = new HttpCookie(LanguageCookieName);
            cookie.HttpOnly = true;
            cookie.Value = languageCode;
            cookie.Expires = DateTime.Now.AddHours(24);
            httpContext.Response.Cookies.Remove(LanguageCookieName);
            httpContext.Response.Cookies.Add(cookie);
        }

        因为cookie变更了,所以GetResource方法得到字符串也会根据当前区域变更。

        第一句代码正如其表述一般,是判断数据库已经安装后,根据HomePage这个规则,重定向到主页。

2.数据准备工作

        导入数据相比就比较简单。通过一系列判断后执行多活动结果集(sql脚本)。主要是由于强类型属性比较多,所以其POST action if else 比较多。这些操作执行完后其实还有一个插件安装和权限安装的流程,自己看源代码吧。

        InstallController-public ActionResult Index(InstallModel model)

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。