美文网首页点耐特经典收藏mvc
ASP.NET MVC开发:带后台的CMS开发

ASP.NET MVC开发:带后台的CMS开发

作者: 凉风有兴 | 来源:发表于2016-11-20 21:25 被阅读1540次

    本来这一篇写的是一个音乐商城的程序的创建,但我啰啰嗦嗦写了三大篇,结果很多业务都没交代清楚,干脆就删了,重写一篇。这一篇重点的地方都有提及,包括会员管理员、文章发布、权限管理,实在是入门最佳教材,遥想入门当年,怎么遇不到这种文章呢?呵呵。由于MVC开发性能卓越,基本上可以在一天之内完成这个开发任务。学了这个,开发个小型商业网站大概也就两三天的功夫。

    基本的思路先画一个思维导图厘清一下思路:

    本例子使用了IDentity进行用户验证,同时也使用了角色,角色设为Admin可以管理用户,也可以管理文章。普通用户除了发表评论外就没有其他功能了。

    控制器方面,我用了AxCMSAdmin控制器,作为管理文章用。

    数据库设计如下图,这里并不包括IDentity生成的数据库,只包括CMS简单业务。

    假设你已经有了一个完整的包含整个IDentity业务的项目,项目名称为Blog,那么我们就从新建模型开始,右击解决方案资源管理器的Models文件夹,在弹出来的菜单上选择新建类:Contents.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace AxCMS.Models
    {
        public class Contents
        {
            public int ContentsId { get; set; }
            public string User { get; set; }
            public string Title { get; set; }
            public int CategoryId { get; set; }
            public DateTime PublicationDate { get; set; }
            public string Content { get; set; }
            public UserCommments UserCommments { get; set; }
            public Category Category { get; set; }
        }
    }
    

    接着,再次新建类:Category.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace AxCMS.Models
    {
        public class Category
        {
            public int CategoryId { get; set; }
            public string Name { get; set; }
            public List<Contents> Contentss { get; set; }
        }
    }
    

    最后再一次新建类:UserCommments.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace AxCMS.Models
    {
        public class UserCommments
        {
            public int UserCommmentsId { get; set; }
            public int ContentsId { get; set; }
            public string user { get; set; }
            public string Comments { get; set; }
        }
    }
    

    全部保存之后,点击生成菜单里面的生成解决方案。

    好了,现在我们来完成一个新的控制器,右击解决方案资源管理器的Controllers文件夹,添加新的控制器,选择 "包含视图的MVC 5控制器(使用 Entity Framework)",设置如下图:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data.Entity;
    
    namespace CMS.Models
    {
        public class testseed:DropCreateDatabaseAlways<CMSDB>
        {
            protected override void Seed(CMSDB context)
            {
                context.BlogClases.Add(new BlogClass { ClassName = "经营" });
                context.BlogDetaileds.Add(
                    new BlogDetailed
                    {
                        User = "null",
                        BlogDate = DateTime.Now,
                        BlogContent="这是一次测试!",
                        BlogClass=new BlogClass { ClassName="管理"}
                });
                base.Seed(context);
            }
        }
    }
    

    打开Global.asax.cs,在protected void Application_Start() 下面输入代码:

     protected void Application_Start()
            {
                System.Data.Entity.Database.SetInitializer(new MvcMusicStore.Models.MusicStoreDbInitializer());
                AreaRegistration.RegisterAllAreas();
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
            }
    

    运行程序,我们可以发现数据库已经完成了并且有了一两笔播种数据。

    一般我们一个程序都在一个数据库里面,在还没有使用注册的情况下,IDentity并不会给你一个默认的数据库,打开web.config文件,将<add name="DefaultConnection" 下面的数据库文件名改为<add name="AxCMSDBContext" 里面的文件名。

    现在,我们在启用IDentity的用户管理同时,也启用角色:

    第一步:打开IdentityConfig.cs,往里面增加代码

    //配置此应用程序中使用的应用程序角色管理器。RoleManager 在 ASP.NET Identity 中定义,并由此应用程序使用。
    public class ApplicationRoleManager : RoleManager<IdentityRole>
        {
            public ApplicationRoleManager(IRoleStore<IdentityRole,string> roleStore)
                : base(roleStore)
            {
            }
    
            public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
            {
                return new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
            }
        }
    

    第二步: 修改Startup.Auth.cs,在 public void ConfigureAuth(IAppBuilder app)中加入代码:

     app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);   //添加的角色管理器
    

    第三步:创建种子数据,新建ApplicationDbInitializer.cs类,将数据加入

    using Microsoft.AspNet.Identity;
    using Microsoft.AspNet.Identity.Owin;
    using System.Data.Entity;
    using Microsoft.AspNet.Identity.EntityFramework;
    using System.Web;
    
    namespace AxCMS.Models
    {
        public class ApplicationDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>
        {
            protected override void Seed(ApplicationDbContext context)
            {
                InitializeIdentityForEF(context);
                base.Seed(context);
            }
    
    
            public static void InitializeIdentityForEF(ApplicationDbContext db)
            {
                var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
                var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();
                const string name = "Admin@alexzeng.net";//用户名
                const string password = "Admin123@alexzeng";//密码
                const string roleName = "Admin";//用户要添加到的角色组
    
                //如果没有Admin用户组则创建该组
                var role = roleManager.FindByName(roleName);
                if (role == null)
                {
                    role = new IdentityRole(roleName);
                    var roleresult = roleManager.Create(role);
                }
    
                //如果没有Admin@alexzeng.net用户则创建该用户
                var user = userManager.FindByName(name);
                if (user == null)
                {
                    user = new ApplicationUser { UserName = name, Email = name };
                    var result = userManager.Create(user, password);
                    result = userManager.SetLockoutEnabled(user.Id, false);
                }
    
                // 把用户Admin@alexzeng.net添加到用户组Admin中
                var rolesForUser = userManager.GetRoles(user.Id);
                if (!rolesForUser.Contains(role.Name))
                {
                    var result = userManager.AddToRole(user.Id, role.Name);
                }
            }
        }
    }
    

    最后一步:在IdentityModels.cs文件中修改:

     public ApplicationDbContext()
               
            {
                Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
            }
    

    运行后用Admin@alexzeng.net 进行登录即可。

    有了Admin角色,我们可以设置为整个‘CMSAdminController’控制器都需要使用Admin权限才能进入。其实非常简单,打开控制器,在命名空间的下面加入 [Authorize(Roles = "Admin")]就可以啦。

    namespace AxCMS.Controllers
    {
        [Authorize(Roles = "Admin")]
      ......
    

    由于文章输入依赖于用户的输入,我们需要对用户输入进行一些限制,如果一些无效数据流入到数据库里面,有可能会给我们的网站带来一些麻烦。再回到模型,打开Contents.cs文件。

    注:需要加入命名空间using System.ComponentModel.DataAnnotations;

     public class Contents
        {
            public int ContentsId { get; set; }
            public string User { get; set; }
            [Required]
            [StringLength(160,MinimumLength =4)]
            [Display(Name ="标题")]
            public string Title { get; set; }
            [Display(Name = "类别")]
            public int CategoryId { get; set; }
            public DateTime PublicationDate { get; set; }
            [Required]
            [Display(Name = "内容")]
            public string Content { get; set; }
            public UserCommments UserCommments { get; set; }
            [Display(Name = "类别")]
            public Category Category { get; set; }
        }
    

    运行程序,坏了,报错了。不要着急,这是EF发现数据库数据发生变化,重新更新一下就可以了。

    打开“程序包管理控制台”,依次输入以下三个命令就可以了。

     Enable-Migrations -ContextTypeName AxCMS.Models.AxCMSDBContext
     add-migration Initial
     update-database
    

    下面对Create视图做一些修改,打开Contents表,有ContentsId,User,Title,CategoryId,PublicationDate,Content等字段,User是获取作者的用户名,这个可以不用用户输入,删除。PublicationDate为当前时间,也不用用户输入。

    打开Create.cshtml,修改如下:

    @model AxCMS.Models.Contents
    
    @{
        ViewBag.Title = "Create";
    }
    
    <h2>Create</h2>
    
    
    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()
        
        <div class="form-horizontal">
            <h4>Contents</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
           
    
            <div class="form-group">
                @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.CategoryId, "标题", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.DropDownList("CategoryId", null, htmlAttributes: new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.CategoryId, "", new { @class = "text-danger" })
                </div>
            </div>
    
            
    
            <div class="form-group">
                @Html.LabelFor(model => model.Content, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.TextAreaFor(model => model.Content, htmlAttributes: new {  @class = "form-control", @rows = 10  })
                    @Html.ValidationMessageFor(model => model.Content, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default" />
                </div>
            </div>
        </div>
    }
    
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
    
    

    打开控制器,对HttpPost的Create进行如下修改。

     [HttpPost]
            [ValidateAntiForgeryToken]
            public ActionResult Create(FormCollection collection)
            {
                var contents = new Contents();
                if (TryUpdateModel(contents))
                {
                    contents.PublicationDate = DateTime.Now;
                    contents.User = User.Identity.Name;
                    db.Contents.Add(contents);
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
    
                ViewBag.CategoryId = new SelectList(db.Categories, "CategoryId", "Name", contents.CategoryId);
                return View(contents);
            }
    

    Edit也类似,不过对用户名和发布时间,我们可以将其设为只读而不用删除,详细代码如下:

    @model AxCMS.Models.Contents
    
    @{
        ViewBag.Title = "Create";
    }
    
    <h2>Create</h2>
    
    
    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()
        
        <div class="form-horizontal">
            <h4>Contents</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
           
    
            <div class="form-group">
                @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.CategoryId, "类别", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.DropDownList("CategoryId", null, htmlAttributes: new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.CategoryId, "", new { @class = "text-danger" })
                </div>
            </div>
    
            
    
            <div class="form-group">
                @Html.LabelFor(model => model.Content, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.TextAreaFor(model => model.Content, htmlAttributes: new {  @class = "form-control", @rows = 10  })
                    @Html.ValidationMessageFor(model => model.Content, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default" />
                </div>
            </div>
        </div>
    }
    
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
    
    

    Edit在控制器中的代码修改如下:

    [HttpPost]
            [ValidateAntiForgeryToken]
            public ActionResult Edit(FormCollection collection)
            {
                var contents = new Contents();
                if (TryUpdateModel(contents))
                {
                    db.Entry(contents).State = EntityState.Modified;
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
                ViewBag.CategoryId = new SelectList(db.Categories, "CategoryId", "Name", contents.CategoryId);
                return View(contents);
            }
    

    好了,文章这里修改得差不多了,那么文章类别管理你会做了吧?

    下面我们来看看如何将文章管理的链接接到全站的导航链接上面去。

    全站默认模板在视图文件夹里面,打开..\Views\Shared_Layout.cshtml,修改里面的

      <ul class="nav navbar-nav">
                        <li>@Html.ActionLink("主页", "Index", "Home")</li>
                        <li>@Html.ActionLink("关于", "About", "Home")</li>
                        <li>@Html.ActionLink("联系方式", "Contact", "Home")</li>
                    </ul>
    

    后面那两个对我们没有用,我们可以添加权限,让拥有权限的用户可以管理文章,管理用户。

     <ul class="nav navbar-nav">
                        <li>@Html.ActionLink("主页", "Index", "Home")</li>
        @if (Request.IsAuthenticated && User.IsInRole("Admin")) {
                            <li>@Html.ActionLink("管理文章", "Index", "CMSAdmin")</li>
                            <li>@Html.ActionLink("管理用户", "Index", "UsersAdmin")</li>
                            <li>@Html.ActionLink("管理角色", "Index", "RolesAdmin")</li>
     }
                    </ul>
    

    这一节最后我们来完成一下首页,将文章数据移到首页来,然后再加一个Details ,参考CMSAdminController的Index和Details,这个真心不难,这里不做讨论。

    下一节,我们将完成用户管理控制器:CMSUser,最后再完成用户评论,用户评论将在Details 页面中显示出来,并且对登录用户显示文本框可以输入评论,难度略有提高。

    谢谢大家。转帖的时候请把凉风有兴或者AlexZeng.net进行署名。本文版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证

    相关文章

      网友评论

      • little慕白:学习到了
      • iimT:很期待你的教程更新,另外希望对教程有个统一命名😁

      本文标题:ASP.NET MVC开发:带后台的CMS开发

      本文链接:https://www.haomeiwen.com/subject/hjmypttx.html