zoukankan      html  css  js  c++  java
  • ASP.NET MVC实现通用设置

    网站中的设置实现方式有好几种,其中有将设置类序列化然后保存到文件中(例如使用XML序列化然后以XML形式保存在文件中),或者将设置信息保存到数据库中。

    保存到数据库中的方式就是将设置的项作为key,设置的值作为value,以key-value(键值对)的形式保存。

    下面使用保存到数据库中的例子来说明,首先是设置信息数据库表结构:

     

     Name是设置项,Value是设置值。对应的实体类如下:

    public class Setting : ISettings
        {
            public int Id { get; set; }
    
            public string  Name { get; set; }
    
            public string Value { get; set; }
        }
    View Code

    这里是使用Entity Framework,下面是数据库上下文实体类:

    public partial class SettingContext : DbContext
        {
            public SettingContext():base("name=MyConnection")
            {
            }
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                Database.SetInitializer< SettingContext>(null);
                modelBuilder.Configurations.Add(new SettingMap());
                base.OnModelCreating(modelBuilder);
            }
          
            public IQueryable<Setting> Table
            {
                get
                {
                    return Set<Setting>();
                }
            }
            public IQueryable<Setting> TableNoTracking
            {
                get
                {
                    return Set<Setting>().AsNoTracking();
                }
            }
            public void Insert(Setting entity)
            {
                if (entity == null)
                {
                    throw new ArgumentException("entity");
                }
                Set<Setting>().Add(entity);
                SaveChanges();
            }
    
            public void Update(Setting entity)
            {
                if (entity == null)
                {
                    throw new ArgumentException("entity");
                }
                Set<Setting>().Attach(entity);
                Entry(entity).State = EntityState.Modified;
                SaveChanges();
            }
            /// <summary>
            /// 加载"设置"
            /// </summary>
            /// <typeparam name="T">设置必须实现接口ISettings</typeparam>
            /// <returns></returns>
            public T LoadSetting<T>() where T : ISettings, new()
            {
                //创建设置实例,然后再对其属性赋值
                var setting = Activator.CreateInstance<T>();
                Type t = typeof(T);
    
                //获取所有的属性
                PropertyInfo[] props = t.GetProperties();
                //获取数据库中所有的设置
                var allSetting = TableNoTracking.ToList();
                if (allSetting!= null && allSetting.Count > 0)
                {
                    foreach (PropertyInfo p in props)
                    {
                        if (!p.CanRead || !p.CanWrite)
                        {
                            continue;
                        }
                        string key = t.Name + "." + p.Name;
                        key = key.Trim().ToLowerInvariant();    //转换为小写
                        var obj = allSetting.Where(s => s.Name == key).FirstOrDefault();
                        if (obj == null)
                        {
                            continue;
                        }
                        string valueStr = obj.Value;
                        //判断是否可以转换为
                        if (!TypeDescriptor.GetConverter(p.PropertyType).CanConvertFrom(typeof(string)))
                        {
                            continue;
                        }
                        if (!TypeDescriptor.GetConverter(p.PropertyType).IsValid(valueStr))
                        {
                            continue;
                        }
                        object value = TypeDescriptor.GetConverter(p.PropertyType).ConvertFromInvariantString(valueStr);
                        p.SetValue(setting, value);
                    }
                }
                return setting;
            }
            /// <summary>
            /// 保存设置
            /// </summary>
            /// <typeparam name="T">设置必须实现接口ISettings</typeparam>
            /// <param name="setting"></param>
            public void SaveSetting<T>(T setting) where T : ISettings, new()
            {
                var allProperties = typeof(T).GetProperties();
                var allSettings = Table.ToList();
                foreach (PropertyInfo prop in allProperties)
                {
                    if (!prop.CanRead || !prop.CanWrite)
                    {
                        continue;
                    }
                    //判断是否可以转换
                    if (!TypeDescriptor.GetConverter(prop.PropertyType).CanConvertFrom(typeof(string)))
                    {
                        continue;
                    }
                    string key = typeof(T).Name + "." + prop.Name;
                    key = key.Trim().ToLowerInvariant();
                    dynamic value = prop.GetValue(setting, null);
                    if (value == null)
                    {
                        value = "";
                    }
                    var obj = allSettings.Where(s => s.Name == key).FirstOrDefault();
                    //需要转换为string
                    string valueStr = TypeDescriptor.GetConverter(prop.PropertyType).ConvertToInvariantString(value);
                    //已存在设置则更新,不存在则添加
                    if (obj != null)
                    {
                        obj.Value = valueStr;
                        Update(obj);
                    }
                    else
                    {
                        obj = new Setting
                        {
                            Name = key,
                            Value = valueStr
                        };
                        Insert(obj);
                    }
                }
            }
        }
    View Code

    由于需要用到泛型约束,所以要求设置类必须实现接口ISettings

    EF映射类:

    public class SettingMap : EntityTypeConfiguration<Setting>
        {
            public SettingMap()
            {
                this.ToTable("Setting");
                this.HasKey(s => s.Id);
                this.Property(s => s.Name).HasMaxLength(512);
            }
        }
    View Code

    基础设置类:

    /// <summary>
        /// 基础设置
        /// </summary>
        public class BaseSetting : ISettings
        {
            [DisplayName("网站名称")]
            public string SiteName { get; set; }
            [DisplayName("备案号")]
            public string SiteICP { get; set; }
            [DisplayName("联系方式")]
            public string SiteTel { get; set; }
            [DisplayName("版权信息")]
            public string Copyright { get; set; }
            [DisplayName("状态")]
            public bool Status { get; set; }
            [DisplayName("缓存时间")]
            public int CacheTime { get; set; }
        }
    View Code

    在控制器中如下:

    public class SettingController : Controller
        {
            SettingContext settingContext = new SettingContext();
            // GET: Setting
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult Base()
            {
                var setting = settingContext.LoadSetting<BaseSetting>();
                return View(setting);
            }
            [HttpPost]
            public ActionResult Base(BaseSetting model)
            {
                if (ModelState.IsValid)
                {
                    settingContext.SaveSetting<BaseSetting>(model);
                }
                return View(model);
            }
        }
    View Code

    视图代码(其实使用了Edit视图基架):

     

    @model SettingDemo.Models.BaseSetting
    
    @{
        ViewBag.Title = "Base";
    }
    
    <h2>Base</h2>
    
    
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        
        <div class="form-horizontal">
            <h4>BaseSetting</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.SiteName, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.SiteName, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.SiteName, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.SiteICP, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.SiteICP, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.SiteICP, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.SiteTel, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.SiteTel, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.SiteTel, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Copyright, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Copyright, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Copyright, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Status, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    <div class="checkbox">
                        @Html.EditorFor(model => model.Status)
                        @Html.ValidationMessageFor(model => model.Status, "", new { @class = "text-danger" })
                    </div>
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.CacheTime, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.CacheTime, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.CacheTime, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Save" class="btn btn-default" />
                </div>
            </div>
        </div>
    }
    
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
    View Code

    浏览前台:

    填写设置,保存,查看数据库

    这里设置项使用的是类名.属性名,也可以使用完全名称(完全命名空间.类名.属性名),只需适当修改代码即可。扩展自己的设置类需要类似BaseSetting那样,实现接口ISettings。

    参考资料:nopcommerce商城系统

  • 相关阅读:
    11 对象的构造
    10 问题分析一
    9 新型的类型转换
    8 C++ 中的新成员
    7 函数重载
    6 函数参数的扩展
    5 内联函数
    查找算法总结Java实现
    九大排序算法Java实现
    帝国cms所有一级栏目遍历,如果有子栏目的话,遍历出来
  • 原文地址:https://www.cnblogs.com/godbell/p/7492542.html
Copyright © 2011-2022 走看看