zoukankan      html  css  js  c++  java
  • ASP.NET MVC5 网站开发实践(二) Member区域

    上次做了显示文章列表,再实现修改和删除文章这部分内容就结束了,这次内容比较简单,由于做过了添加文章,修改文章非常类似,就是多了一个TryUpdateModel部分更新模型数据。

     

    目录:

    ASP.NET MVC5 网站开发实践 - 概述

    ASP.NET MVC5 网站开发实践(一) - 项目框架

    ASP.NET MVC5 网站开发实践(一) - 框架(续) 模型、数据存储、业务逻辑

    ASP.NET MVC5 网站开发实践(二) - 用户部分(1)用户注册

    ASP.NET MVC5 网站开发实践(二) - 用户部分(2)用户登录、注销

    ASP.NET MVC5 网站开发实践(二) - 用户部分(3)修改资料、修改密码

    ASP.NET MVC5 网站开发实践(二) Member区域 - 文章管理架构

    ASP.NET MVC5 网站开发实践(二) Member区域 - 添加文章

    ASP.NET MVC5 网站开发实践(二) Member区域 - 全部文章列表

     

    一、删除文章

    由于公共模型跟,文章,附件有关联,所以这里的删除次序很重要,如果先删除模型,那么文章ModelID和附件的ModelID多会变成null,所以要先先删除文章和附件再删除公共模型。

    由于公共模型和附件是一对多的关系,我们把删除公共模型和删除附件写在一起。

    在BLL的BaseRepository类中有默认的Delete方法,但这个方法中仅删除模型,不会删除外键,所以在CommonModelRepository在new一个出来封印掉默认的方法。

    public new bool Delete(Models.CommonModel commonModel, bool isSave = true)
            {
                if (commonModel.Attachment != null) nContext.Attachments.RemoveRange(commonModel.Attachment);
                nContext.CommonModels.Remove(commonModel);
                return isSave ? nContext.SaveChanges() > 0 : true;
            }

    这个的意思是封印掉继承的Delete方法,在新的方法中如果存在附加那么先删除附件,再删除公共模型。那么如果我们还想调用基类的Delete方法怎么办?可以用base.Delete。

    好了,现在可以开始删除了。

    在ArticleController中添加Delete方法

    /// <summary>
            /// 删除
            /// </summary>
            /// <param name="id">文章id</param>
            /// <returns></returns>
            public JsonResult Delete(int id)
            {
                //删除附件
                var _article  = articleService.Find(id);
                if(_article == null) return Json(false);
                //附件列表
                var _attachmentList = _article.CommonModel.Attachment;
                var _commonModel = _article.CommonModel;
                //删除文章
                if (articleService.Delete(_article))
                {
                    //删除附件文件
                    foreach (var _attachment in _attachmentList)
                    {
                        System.IO.File.Delete(Server.MapPath(_attachment.FileParth));
                    }
                    //删除公共模型
                    commonModelService.Delete(_commonModel);
                    return Json(true);
                }
                else return Json(false);
            }

     

    二、修改文章

    这个部分跟添加文章非常类似

    首先在ArticleController中添加显示编辑视图的Edit

    /// <summary>
            /// 修改
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public ActionResult Edit(int id)
            {
                return View(articleService.Find(id));
            }

    右键添加视图,这个跟添加类似,没什么好说的直接上代码

    @section scripts{
        <script type="text/javascript" src="~/Scripts/KindEditor/kindeditor-min.js"></script>
        <script type="text/javascript">
            //编辑框
            KindEditor.ready(function (K) {
                window.editor = K.create('#Content', {
                    height: '500px',
                    uploadJson: '@Url.Action("Upload", "Attachment")',
                    fileManagerJson: '@Url.Action("FileManagerJson", "Attachment", new { id = @Model.CommonModel.ModelID })',
                    allowFileManager: true,
                    formatUploadUrl: false
                });
            //首页图片
                var editor2 = K.editor({
                    fileManagerJson: '@Url.Action("FileManagerJson", "Attachment", new {id=@Model.CommonModel.ModelID })'
                });
                K('#btn_picselect').click(function () {
                    editor2.loadPlugin('filemanager', function () {
                        editor2.plugin.filemanagerDialog({
                            viewType: 'VIEW',
                            dirName: 'image',
                            clickFn: function (url, title) {
                                var url;
                                $.ajax({
                                    type: "post",
                                    url: "@Url.Action("CreateThumbnail", "Attachment")",
                                    data: { originalPicture: url },
                                    async: false,
                                    success: function (data) {
                                        if (data == null) alert("生成缩略图失败!");
                                        else {
                                            K('#CommonModel_DefaultPicUrl').val(data);
                                            K('#imgpreview').attr("src", data);
                                        }
                                        editor2.hideDialog();
                                    }
                                });
                            }
                        });
                    });
                });
            });
        </script>
    }
    
    @model Ninesky.Models.Article
    @using (Html.BeginForm())
    { @Html.AntiForgeryToken()
        <div class="form-horizontal" role="form">
            <h4>添加文章</h4>
            <hr />
            @Html.ValidationSummary(true)
            <div class="form-group">
                <label class="control-label col-sm-2" for="CommonModel_CategoryID">栏目</label>
                <div class="col-sm-10">
                    <input id="CommonModel_CategoryID" name="CommonModel.CategoryID" data-options="url:'@Url.Action("JsonTree", "Category", new { model="Article" })'" class="easyui-combotree" style="height: 34px;  280px;" value="@Model.CommonModel.CategoryID" />
                           @Html.ValidationMessageFor(model => model.CommonModel.CategoryID)</div>
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.CommonModel.Title, new { @class = "control-label col-sm-2" })
                <div class="col-sm-10">
                           @Html.TextBoxFor(model => model.CommonModel.Title, new { @class = "form-control" })
                           @Html.ValidationMessageFor(model => model.CommonModel.Title)</div>
            </div>
    
    
            <div class="form-group">
                @Html.LabelFor(model => model.Author, new { @class = "control-label col-sm-2" })
                <div class="col-sm-10">
                    @Html.TextBoxFor(model => model.Author, new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.Author)
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Source, new { @class = "control-label col-sm-2" })
                <div class="col-sm-10">
                    @Html.TextBoxFor(model => model.Source, new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.Source)
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Intro, new { @class = "control-label col-sm-2" })
                <div class="col-sm-10">
                    @Html.TextAreaFor(model => model.Intro, new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.Intro)
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Content, new { @class = "control-label col-sm-2" })
                <div class="col-sm-10">
                    @Html.EditorFor(model => model.Content)
                    @Html.ValidationMessageFor(model => model.Content)
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.CommonModel.DefaultPicUrl, new { @class = "control-label col-sm-2" })
                <div class="col-sm-10">
                    <img id="imgpreview" class="thumbnail" src="@Model.CommonModel.DefaultPicUrl" />
                    @Html.HiddenFor(model => model.CommonModel.DefaultPicUrl)
                    <a id="btn_picselect" class="easyui-linkbutton">选择…</a>
                    @Html.ValidationMessageFor(model => model.CommonModel.DefaultPicUrl)
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                    <input type="submit" value="保存" class="btn btn-default" />
                </div>
            </div>
        </div>
    }

    开始做后台接受代码,在ArticleController中添加如下代码。

    [HttpPost]
            [ValidateInput(false)]
            [ValidateAntiForgeryToken]
            public ActionResult Edit()
            {
                int _id = int.Parse(ControllerContext.RouteData.GetRequiredString("id"));
                var article = articleService.Find(_id);
                TryUpdateModel(article, new string[] { "Author", "Source", "Intro", "Content" });
                TryUpdateModel(article.CommonModel, "CommonModel", new string[] { "CategoryID", "Title", "DefaultPicUrl" });
                if(ModelState.IsValid)
                {
                    if (articleService.Update(article))
                    {
                        //附件处理
                        InterfaceAttachmentService _attachmentService = new AttachmentService();
                        var _attachments = _attachmentService.FindList(article.CommonModel.ModelID, User.Identity.Name, string.Empty,true).ToList();
                        foreach (var _att in _attachments)
                        {
                            var _filePath = Url.Content(_att.FileParth);
                            if ((article.CommonModel.DefaultPicUrl != null && article.CommonModel.DefaultPicUrl.IndexOf(_filePath) >= 0) || article.Content.IndexOf(_filePath) > 0)
                            {
                                _att.ModelID = article.ModelID;
                                _attachmentService.Update(_att);
                            }
                            else
                            {
                                System.IO.File.Delete(Server.MapPath(_att.FileParth));
                                _attachmentService.Delete(_att);
                            }
                        }
                        return View("EditSucess", article);
                    }
                }
                return View(article);
            }

    详细讲解一下吧:

    1、[ValidateInput(false)] 表示不验证输入内容。因为文章内容包含html代码,防止提交失败。

    2、[ValidateAntiForgeryToken]是为了防止伪造跨站请求的,也就说只有本真的请求才能通过。

    image

    见图中的红线部分,在试图中构造验证字符串,然后再后台验证。

    3、public ActionResult Edit()。看这个方法没有接收任何数据,我们再方法中使用TryUpdateModel更新模型。因为不能完全相信用户,比如如果用户构造一个CateggoryID过来,就会把文章发布到其他栏目去。

    image

    这个是在路由中获取id参数

    image

    再看这两行,略有不同

    第一行直接更新article模型。第一个参数是要更新的模型,第二个参数是更新的字段。

    第二行略有不同,增加了一个前缀参数,我们看视图生成的代码 @Html.TextBoxFor(model => model.CommonModel.Title 是带有前缀CommonModel的。所以这里必须使用前缀来更新视图。

    三、修改文章列表

    写完文章后,就要更改文章列表代码用来删除和修改文章。

    打开List视图,修改部分由2处。

    1、js脚本部分

    <script type="text/javascript">
        $("#article_list").datagrid({
            loadMsg: '加载中……',
            pagination:true,
            url: '@Url.Action("JsonList","Article")',
            columns: [[
                { field: 'ModelID', title: 'ID', checkbox: true },
                { field: 'CategoryName', title: '栏目'},
                { field: 'Title', title: '标题'},
                { field: 'Inputer', title: '录入', align: 'right' },
                { field: 'Hits', title: '点击', align: 'right' },
                { field: 'ReleaseDate', title: '发布日期', align: 'right', formatter: function (value, row, index) { return jsonDateFormat(value); } },
                { field: 'StatusString', title: '状态',  100, align: 'right' }
            ]],
            toolbar: '#toolbar',
            idField: 'ModelID',
            onDblClickRow: function (rowIndex, rowData) { window.parent.addTab("修改文章", "@Url.Action("Edit","Article")/" + rowData.ModelID, "icon-page"); }
        });
        //查找
        $("#btn_search").click(function () {
            $("#article_list").datagrid('load', {
                title: $("#textbox_title").val(),
                input: $("#textbox_inputer").val(),
                category: $("#combo_category").combotree('getValue'),
                fromDate: $("#datebox_fromdate").datebox('getValue'),
                toDate: $("#datebox_todate").datebox('getValue')
            });
        });
    
        //修改事件
        function eidt() {
            var rows = $("#article_list").datagrid("getSelections");
            if (!rows || rows.length < 1) {
                $.messager.alert("提示", "请选择要修改的行!");
                return;
            }
            else if (rows.length != 1) {
                $.messager.alert("提示", "仅能选择一行!");
                return;
            }
            else {
                window.parent.addTab("修改文章", "@Url.Action("Edit","Article")/" + rows[0].ModelID, "icon-page");
            }
        }
        //删除
        function del()
        {
            var rows = $("#article_list").datagrid("getSelections");
            if (!rows || rows.length < 1) {
                $.messager.alert("提示", "未选择任何行!");
                return;
            }
            else if (rows.length > 0) {
                $.messager.confirm("确认", "您确定要删除所选行吗?", function (r) {
                    if (r) {
                        $.messager.progress();
                        $.each(rows, function (index, value) {
                            $.ajax({
                                type: "post",
                                url: "@Url.Action("Delete", "Article")",
                                data: { id: value.ModelID },
                                async: false,
                                success: function (data) {
                                }
                            });
                        });
                        $.messager.progress('close');
                        //清除选择行
                        rows.length = 0;
                        $("#article_list").datagrid('reload');
                    }
                });
                return;
            }
        }
    </script>

    增加了修改方法、删除方法,在datagrid里添加行双击进入修改视图的方法

    onDblClickRow: function (rowIndex, rowData) { window.parent.addTab("修改文章", "@Url.Action("Edit","Article")/" + rowData.ModelID, "icon-page"); }

    2、

    image

    四、我的文章列表

    我的文章列表与全部文章类似,并简化掉了部分内容那个,更加简单,直接上代码了

    Article控制器中添加

    /// <summary>
            /// 文章列表Json【注意权限问题,普通人员是否可以访问?】
            /// </summary>
            /// <param name="title">标题</param>
            /// <param name="input">录入</param>
            /// <param name="category">栏目</param>
            /// <param name="fromDate">日期起</param>
            /// <param name="toDate">日期止</param>
            /// <param name="pageIndex">页码</param>
            /// <param name="pageSize">每页记录</param>
            /// <returns></returns>
            public ActionResult JsonList(string title, string input, Nullable<int> category, Nullable<DateTime> fromDate, Nullable<DateTime> toDate, int pageIndex = 1, int pageSize = 20)
            {
                if (category == null) category = 0;
                int _total;
                var _rows = commonModelService.FindPageList(out _total, pageIndex, pageSize, "Article", title, (int)category, input, fromDate, toDate, 0).Select(
                    cm => new Ninesky.Web.Models.CommonModelViewModel() 
                    { 
                        CategoryID = cm.CategoryID,
                        CategoryName = cm.Category.Name,
                        DefaultPicUrl = cm.DefaultPicUrl,
                        Hits = cm.Hits,
                        Inputer = cm.Inputer,
                        Model = cm.Model,
                        ModelID = cm.ModelID,
                        ReleaseDate = cm.ReleaseDate,
                        Status = cm.Status,
                        Title = cm.Title 
                    });
                return Json(new { total = _total, rows = _rows.ToList() });
            }
    
            public ActionResult MyList()
            {
                return View();
            }
    
            /// <summary>
            /// 我的文章列表
            /// </summary>
            /// <param name="title"></param>
            /// <param name="fromDate"></param>
            /// <param name="toDate"></param>
            /// <param name="pageIndex"></param>
            /// <param name="pageSize"></param>
            /// <returns></returns>
            public ActionResult MyJsonList(string title, Nullable<DateTime> fromDate, Nullable<DateTime> toDate, int pageIndex = 1, int pageSize = 20)
            {
                int _total;
                var _rows = commonModelService.FindPageList(out _total, pageIndex, pageSize, "Article", title, 0, string.Empty, fromDate, toDate, 0).Select(
                    cm => new Ninesky.Web.Models.CommonModelViewModel()
                    {
                        CategoryID = cm.CategoryID,
                        CategoryName = cm.Category.Name,
                        DefaultPicUrl = cm.DefaultPicUrl,
                        Hits = cm.Hits,
                        Inputer = cm.Inputer,
                        Model = cm.Model,
                        ModelID = cm.ModelID,
                        ReleaseDate = cm.ReleaseDate,
                        Status = cm.Status,
                        Title = cm.Title
                    });
                return Json(new { total = _total, rows = _rows.ToList() }, JsonRequestBehavior.AllowGet);
            }

    为MyList右键添加视图

    <div id="toolbar">
        <div>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-edit',plain:true" onclick="eidt()">修改</a>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-remove',plain:true" onclick="del()">删除</a>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-reload',plain:true" onclick="$('#article_list').datagrid('reload');">刷新</a>
        </div>
        <div class="form-inline">
            <label>标题</label> <input id="textbox_title" class="input-easyui" style="280px" />
            <label>添加日期</label>
            <input id="datebox_fromdate" type="datetime" class="easyui-datebox" style="120px" /> -
            <input id="datebox_todate" type="datetime" class="easyui-datebox" style="120px; " />
            <a href="#" id="btn_search" data-options="iconCls:'icon-search'" class="easyui-linkbutton">查询</a>
        </div>
    
    </div>
    <table id="article_list"></table>
    <script src="~/Scripts/Common.js"></script>
    <script type="text/javascript">
        $("#article_list").datagrid({
            loadMsg: '加载中……',
            pagination:true,
            url: '@Url.Action("MyJsonList", "Article")',
            columns: [[
                { field: 'ModelID', title: 'ID', checkbox: true },
                { field: 'CategoryName', title: '栏目'},
                { field: 'Title', title: '标题'},
                { field: 'Inputer', title: '录入', align: 'right' },
                { field: 'Hits', title: '点击', align: 'right' },
                { field: 'ReleaseDate', title: '发布日期', align: 'right', formatter: function (value, row, index) { return jsonDateFormat(value); } },
                { field: 'StatusString', title: '状态',  100, align: 'right' }
            ]],
            toolbar: '#toolbar',
            idField: 'ModelID',
            onDblClickRow: function (rowIndex, rowData) { window.parent.addTab("修改文章", "@Url.Action("Edit","Article")/" + rowData.ModelID, "icon-page"); }
        });
        //查找
        $("#btn_search").click(function () {
            $("#article_list").datagrid('load', {
                title: $("#textbox_title").val(),
                fromDate: $("#datebox_fromdate").datebox('getValue'),
                toDate: $("#datebox_todate").datebox('getValue')
            });
        });
    
        //修改事件
        function eidt() {
            var rows = $("#article_list").datagrid("getSelections");
            if (!rows || rows.length < 1) {
                $.messager.alert("提示", "请选择要修改的行!");
                return;
            }
            else if (rows.length != 1) {
                $.messager.alert("提示", "仅能选择一行!");
                return;
            }
            else {
                window.parent.addTab("修改文章", "@Url.Action("Edit","Article")/" + rows[0].ModelID, "icon-page");
            }
        }
        //删除
        function del()
        {
            var rows = $("#article_list").datagrid("getSelections");
            if (!rows || rows.length < 1) {
                $.messager.alert("提示", "未选择任何行!");
                return;
            }
            else if (rows.length > 0) {
                $.messager.confirm("确认", "您确定要删除所选行吗?", function (r) {
                    if (r) {
                        $.messager.progress();
                        $.each(rows, function (index, value) {
                            $.ajax({
                                type: "post",
                                url: "@Url.Action("Delete", "Article")",
                                data: { id: value.ModelID },
                                async: false,
                                success: function (data) {
                                }
                            });
                        });
                        $.messager.progress('close');
                        //清除选择行
                        rows.length = 0;
                        $("#article_list").datagrid('reload');
                    }
                });
                return;
            }
        }
    </script>

     

    五、总结

    要注意的是删除文章时删除的次序,修改文章时TryUpdateModel的使用。

    到此Member部分文章这块结束。

    补上代码 http://pan.baidu.com/s/1c05UNYS

    登录地址:/Member/User/Login

    账号mzwhj密码123456

  • 相关阅读:
    Java 设计模式之单例
    CentOS 下安装配置Hadoop
    Linux 修改IP地址和DNS
    Hibernate 主配置文件详解
    HTTP 协议细节
    Java 设计模式之工厂
    mysqldump备份与还原
    [小技巧]windows时间同步
    关于反射
    XHTML、DTD和Web Services
  • 原文地址:https://www.cnblogs.com/mzwhj/p/3597457.html
Copyright © 2011-2022 走看看