浅谈MVC/WebForm框架设计

为什么要设计框架?

在开发的过程中为了方便管理资源,统一一定的规范,所以采用使用框架,为了以后项目的延伸和拓展,比如我们的代码其实都可以在一个方法内进行,而且也不需要相互调用也许会更快吧?但是要是发生错误呢 ?好不容易执行的最后一行结果突然发生错误了,很难受不是  题外话,但是也可以感受到一个好的设计会给我们带来很大的方便

题外话继续 :开发过程中,我们前后台之间相互关联,有一个项目的改动就需要一起协调,这还是一个小功能,要是同时进行一次开发,那就难免深受其累了,怎么样才能方便管理、前后台分离呢?  按照模块化儿文件夹来区分是个不错的想法,这里给大家带来一点儿自己开发的心得,当然是有很多前辈的心血  题外话结束

使用Areas、区域、模块化分离项目

首先建立一个项目Forame,添加3个类库项目Forame.BLL、Forame.Controllers、Forame.Models,一个MVC项目Forame.Web,目录如下:

在Web项目中添加MVC区域Area 右键项目  添加  区域(列表第一个)输入创建的区域名称 ,由于可以有多个区域所以统一存放在了Areas文件夹下所以大家不要感觉到奇怪,为什么多个文件夹出来  , 我们在这里创建两个区域 ,管理员Admin、用户User,

正如你所见,区域生成的目录和原本的目录结构一致,这也意味着我们初步实现了分离按照模块化分离,毕竟多数的项目版本管理工具都是在文件内管理--比如我在操作这个文件夹的时候锁住,使用完成再释放,但是这还远远不够、达不到我们预期的目标,那么我们继续,有些朋友一定记得我们创建了三个类库,可都还没有使用呢 呵呵! 下面我们就把这个联系起来

在类库Forame.Controllers中引用System.Web.Mvc程序集 创建类HomeController、,在这个我们使Forame.Controllers类库作为我们的控制器,当然控制器的规约我们还是要遵守的,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace Forame.Controllers
{
    public class FirstController:Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
}
FirstController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace Forame.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
}
HomeController

其次我们再继续回到Web项目中,在Areas区域内的Admin、User区域中添加相应的视图  操作如:在Vires下创建和控制器对应的文件下  --  添加视图  --  视图页面上输出一些可以用来标识的文本,也许眼急的朋友已经看到了  哎,这个文件夹下怎么还有一个类,恭喜你,中奖了,由于我们设置了区域,相当于修了一些墙,那么怎么样才能把合适的用户带入合适的房间,AreaRegistration.cs这个类为我们提供了支持:这个类的作用就是设置路由,同时将URL指向控制器,这里我们一般不需要进行改动但是需要加一个属性

using System.Web.Mvc;

namespace Forame.Web.Areas.Admin
{
    public class AdminAreaRegistration : AreaRegistration 
    {
        public override string AreaName 
        {
            get 
            {
                return "Admin";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context) 
        {
            context.MapRoute(
                "Admin_default",//路由的名称
                "Admin/{controller}/{action}/{id}",  //路由格式
                new { action = "Index", id = UrlParameter.Optional }//路由参数定义
            );
        }
    }
}
路由设置类的样子
using System.Web.Mvc;

namespace Forame.Web.Areas.Admin
{
    public class AdminAreaRegistration : AreaRegistration 
    {
        public override string AreaName 
        {
            get 
            {
                return "Admin";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context) 
        {
            context.MapRoute(
                "Admin_default",//路由的名称
                "Admin/{controller}/{action}/{id}",  //路由格式
                new { action = "Index", id = UrlParameter.Optional },//路由参数定义
                new string[] { "Forame.Controllers" }//指向控制器所在位置
            );
        }
    }
}
修改后的样子

同时我们需要在总的路由App_Start文件夹下的RouteConfig 同样添加控制器的位置属性

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace Forame.Web
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                namespaces: new string[] { "Forame.Controllers" }//指向控制器所在位置
            );
        }
    }
}
总的路由也需要设置

好了,至此我们的分离就算完成了  等 !等等!! 同学们先别急着下课,我们是不是忘记了什么  记得Web要添加Forame.Controllers类库的引用哟,大家可以继续看看4个页面的URL的不同之处

 总结:想必大家看到这里心里也有一些想法了,是的我们使用的MVC区域的知识点,主要是将控制器分离到了一个独立的类库中接触了和前端的耦合关联,当然我们可以 在类库中按照文件夹来区分各个控制器,总而言之BLL用来做业务逻辑、Model用来存放实体类、 Controllers用来和前台交互返回数据、Web用来做前端页面展示,

道歉:由于本人文笔有限,可能描述的不太清楚欢迎各位评论、留言、交流,批评、指正。

加注 : 有很多朋友在使用webForm开发程序,那么WebForm是否可以达到同样的效果呢,答案是肯定的,首先同样我们可以创建一个文件夹来集中存放我们的前端页面(在WebForm中是没有区域这个概念的),一般使用Modules作为文件夹的名字,其次删除WebForm窗体下的相关联的类,在有的VS版本中创建页面时好像可以选择单独的页面是没有.cs类的,如果有那就需要我们自己删除了,随即回到我们的Web窗体 这个时候已经开始出现错误了,CodeBehind属性出现一条绿色的波浪线,删除就好了,其次开始设置 Inherits 属性 需要全类名 程序集+类名,这也就是说和MVC一样我们可以将后台单独写成一个类库,然后将Inherits属性指向这个类库下相对应的类,那么问题来了,我们都知道WebForm是基于控件和事件开发的,那么我们应该怎么样去绑定呢?

1.0  后台类库引用using System.Webusing System.Web.UI.WebControls; 两个程序集

2.0  在前端中出现的控件使用属性的方式声明

3.0  在我们页面后台的类中都需要继承 System.Web.UI.Page这个类,我们在  Page_Init 这个事件中去绑定控件的相关事件

下面给出一系列图片帮助大家理解 也会加入相关的一些注释,希望帮助大家理解

/********************************************************************

   标题:        ClassManage_List.cs
   功能:        班级列表
   说明:        
   
   当前版本:   1.0
   开发信息:   Created by WangLong 2018/01/17
**************************************************************/

using SJTSoft.Core.BLL;
using SJTSoft.Core.Util;
using SJTSoft.Text.BLL;
using SJTSoft.WebControls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI.WebControls;
namespace SJTSoft.Text.ModuleWeb.Class
{
    /// <summary>
    /// 编辑班级
    /// </summary>
    public partial class ClassManage_Add : System.Web.UI.Page
    {
        //标题
        protected PageTitle pageTitle;
        //工具栏
        protected Toolbar toolbar;
        //保存
        protected Button btnSave;
        //返回
        protected Button btnBack;
        //班级名称
        protected TextBox txtClassName;
        //班级总人数
        protected TextBox txtClassMaxTotal;
        //班主任
        protected TextBox txtClassHeadmaster;
        //班级描述
        protected TextBox txtClassDescribe;
        //所在年级
        protected DropDownList ddlClassGrade;

        /// <summary>
        /// 页面初始化
        /// </summary>
        protected void Page_Init(object sender, EventArgs e)
        {
            //事件绑定
            btnSave.Click += new EventHandler(btnSave_Click);
            btnBack.Click += new EventHandler(btnBack_Click);
            toolbar.ToolbarItemClick += new MenuEventHandler(toolbar_ToolbarItemClick);
        }

        /// <summary>
        /// 页面加载
        /// </summary>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                InitTabToolbar();
            }
        }

        /// <summary>
        ///  初始化页签
        /// </summary>
        private void InitTabToolbar()
        {
            if (string.IsNullOrEmpty(Request.QueryString["ClassId"]))
            {
                pageTitle.Items.Add(new PageTitleItem("新增班级"));
            }
            else
            {
                pageTitle.Items.Add(new PageTitleItem("修改班级"));
                ClassDataBind();
            }

            MenuItem item = new MenuItem("保存", "save");
            item.ToolTip = "保存班级";
            item.SeparatorImageUrl = toolbar.SeparatorImageUrl;
            toolbar.AddMenuItem(item);

            item = new MenuItem("返回", "return", "/Images/ico/ico_Return.gif");
            item.ToolTip = "返回到班级列表";
            toolbar.AddMenuItem(item);
        }

        /// <summary>
        /// 工具栏
        /// </summary>
        void toolbar_ToolbarItemClick(object sender, MenuEventArgs e)
        {
            if (e.Item.Value == "save")
            {
                btnSave_Click(null, null);
            }
            else if (e.Item.Value == "return")
            {
                btnBack_Click(null, null);
            }
        }

        /// <summary>
        /// 绑定角色数据
        /// </summary>
        private void ClassDataBind()
        {
            //获取该编号的对象
            Model.Entitys.Class objClass = BaseBLLFactory.CreateService<ClassService>().GetClass(Request.QueryString["ClassId"]);

            //将对象赋值到页面控件中
            txtClassName.Text = objClass.ClassName;
            txtClassMaxTotal.Text = objClass.ClassMaxTotal.ToString();
            txtClassHeadmaster.Text = objClass.ClassHeadmaster;
            txtClassDescribe.Text = objClass.ClassDescribe;
            ddlClassGrade.SelectedValue = objClass.ClassGrade.ToString();

        }

        /// <summary>
        /// 返回按钮
        /// </summary>
        void btnBack_Click(object sender, EventArgs e)
        {
            Response.Redirect("/Modules/Class/ClassManage_List.aspx");
        }

        /// <summary>
        /// 保存编辑
        /// </summary
        void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                Model.Entitys.Class objClass;
                if (!string.IsNullOrEmpty(Request.QueryString["ClassId"]))
                {
                    objClass = BaseBLLFactory.CreateService<ClassService>().GetClass(Request.QueryString["ClassId"]);
                }
                else
                {
                    objClass = new Model.Entitys.Class();
                }
                //验证参数
                objClass.ClassName = VerifyUtil.VerifyStringNotNull(txtClassName.Text, "班级名称", 50);
                objClass.ClassGrade = VerifyUtil.VerifyIntegerDefaultVal(ddlClassGrade.SelectedValue, "年级", 1, 9, 1);
                objClass.ClassMaxTotal = VerifyUtil.VerifyIntegerDefaultVal(ddlClassGrade.SelectedValue, "年级", 1, 10, 10);
                objClass.ClassHeadmaster = VerifyUtil.VerifyStringNotNull(txtClassName.Text, "班主任", 50);

                if (string.IsNullOrEmpty(Request.QueryString["ClassId"]))
                {
                    BaseBLLFactory.CreateService<ClassService>().AddClass(objClass);
                }
                else
                {
                    BaseBLLFactory.CreateService<ClassService>().UpdateClass(objClass);
                }

                Response.Redirect("/Modules/Class/ClassManage_List");
            }
            catch (Exception err)
            {
                throw err;
            }
        }
    }
}
由于使用了自己的框架,所以大家看看这个思路就好
<%@ Page Language="C#" AutoEventWireup="true" Inherits="SJTSoft.Text.ModuleWeb.Class.ClassManage_List" %>
<%--去除 CodeBehind 属性  设置Inherits 指定具体的类(全类名:程序集+类名)--%>
需要在窗体的头部设置的属性

项目分离后的效果图 : 一定要记得Web层要引用后台类库的程序集哟,不然。。。

原文地址:https://www.cnblogs.com/huanjinyuan/p/8288287.html