Asp.net MVC网站的基本结构:
Controller->IBLL(定义业务接口)->BLL->DA(调用Utility)->数据库 ,其中A->B表示A调用B
1.Web网站,主要包括Controller类(内含一系列Action方法),视图即cshtml页面,各个视图公用的js脚本,图片文件,css样式文件。
Controller只负责接收页面通过URL或者Post方法发送的请求,然后返回视图,不做逻辑判断,逻辑判断统统放在BLL层来做。
视图即cshtml页面通过<script>标签引用公用的js脚本(或者在每个页面单独写js或jquery)向Controller的某个Actiona发送jax请求,Action方法再将请求的参数传到BLL获取数据。Action获取到数据之后就会返回结果,结果(必须是ActionResult的子类,ActionResult的之类可以是视图或者数据比如JsonResult)可以是包含获取到数据的某个新视图(通过ViewBag将数据传给该视图),也可以仅仅是数据,如果是数据,那么原来发送ajax请求的视图将获取到该数据,并通过原来的ajax请求的callback回调方法接收并处理该数据,如显示在当前页面的某个div或table里。
Controller为了使用BLL的方法,是直接使用对应的BLL还是通过IBLL?
答案是使用IBLL,作为接口,IBLL能够调用实现了其接口方法的BLL,具体做法是,在Controller中定义几个IBLL的变量,然后在构造方法中通过IOC将IBLL变量进行实例化。然后Action方法中,就用这些IBLL变量调用BLL层的方法。
2.IBLL层,这一层只定义业务接口方法,不做实现,这一层感觉有点鸡肋,只是为了让BLL层的方法符合IBLL的规范。
3.BLL层,实现IBLL的接口方法,主要实现方式是通过调用DAL的方法来访问数据库获取数据(或将数据通过DAL的方法存入数据库),或保存数据到数据库。
并且BLL负责对获取到的数据进行加工,如逻辑判断,将获取到的数据进行重新组装,封装成视图能直接用的ModelView,用户输入的后台验证,数据库报错信息的异常处理等。
4.DAL层,定义具体的操作数据库的方法。主要方法的参数为SearchModel(用于从数据库查询)或对应数据库表的Model(用于保存到数据库),但也有个别方法可能为了配合BLL的某些具体需要,DAL方法不需要参数或者参数为基本类型,如int等。
在DAL层直接写SQL语句(或者调用存储过程)来获取数据或者保存数据。
5.Entity层,一系列用于封装数据的实体类,是通信载体,是对数据的封装。Entity主要包括Model和ModelView两种实体类。根据需要Entity层还可以包括一些自定义的枚举等。
一个Model类直接对应数据库的一个表,字段与表中一样,例如可以对实体类添加Attribute(属性)修饰符,例如对StudentModel类添加[Table(Name = "table_student")],可以使得StudentModel类对应数据库的table_student表(当然需要用代码来识别这种对应关系)。
但是有了Model还不够,应为前台的视图展示的数据可能与数据库表中字段有些差异,这就需要被称为ModelView的实体类。
顾名思义,ModelView就是为了给View即视图使用的,它是对Model的再封装。具体做法是各个ModelView从相对应的Model继承,这样Model有的字段ModelView都有,并且可以添加Model中不存在,但视图又需要的字段。这样DAL和BLL的方法返回一个ModelView类型的数据,视图就能不经过处理直接使用了。
另外,一个实用技巧是,在信息管理系统这样的网站中,经常会有用户会在前台页面输入几个查询条件,查询一些东西以求得到一些列表或报表这样的场景,这时我们可以把用户的查询条件封装成一个Model实体类,叫SearchModel,比如查询学生的StudentSearchModel,查询商品的ProductSearchModel,
这样前台页面发送ajax请求时,就发送一个SearchModel到Controller的Action方法,然后Controller与BLL,BLL与DAL之间通信的载体都使用SearchModel(即BLL,DAL方法的参数为SearchModel,而不是SearchModel具体的几个字段),这样假如前台需要增加一个查询条件时,只需要给SearchModel增加一个字段即可,再把前台ajax请求修改一下(多发送一个字段),而不需要修改BLL,DAL方法的定义,非常方便。
6.Utility,主要是一些工具方法,例如操作数据库的基本方法,比如执行查询,创建连接,执行事务等,还有一些工具方法,比如字符串处理,正则表达式验证等,DAL及BLL可能会用到这些方法.
7.数据库,包括基本表,和一大堆视图,对于复杂的操作还需要存储过程。
视图主要是为了查询方便,DAL获取到的数据主要通过从视图进行查询,比较少直接从基本表查询,因为很多情况下,查询是为给前台页面提供数据,
而前台页面需要的数据通常比较人性化,不会像基本数据表那么规范,而且基本表一般比较详细,字段很多,而前台用到的数据往往需要来自好几个表,但对每个表都只需要其中一两个字段。
因此需要视图预先写好select语句,将需要的数据封装好再用。
8.视图页面(cshtml)
asp.net mvc对比asp.net webform比较大的不同是web form的页面aspx还有后台代码一说,两者是一起的,而mvc把视图和控制器进行了分割,控制器的代码就可以脱离视图,很方便地对action的结果进行测试。另外控制器的每个action方法都可以返回一个视图。
web form模式下,通过服务器控件,后台代码可以直接操作页面,读取控件的值,将数据绑定到控件上等等操作。而mvc没有了web form的服务器控件,如何操作页面呢,答案是controller或者说action再也不能操作页面,包括为控件赋值,完成数据绑定等操作,action方法只能生成页面或者返回数据。
这就需要我们页面上自己写js方法来向action发送请求,获取到action返回的数据之后,再用js代码实现数据的绑定和展示。因此用mvc模式做网站需要程序员对js很熟悉,基本的用jquery发送ajax请求,然后自己写好回调函数处理response,实现数据的动态加载,url跳转等都要会。
视图向action传递数据,主要是发送ajax请求,在请求内包含数据参数,以这样的形式。而控制器的action向视图传递数据除了直接返回数据,例如json之外,还可以用ViewBag和ViewData,例如,ViewBag.stuList=myStuList;视图再通过js代码用 "@" 符号,用var stuList= @ViewBag.stuList;获取数据,然后用js读取stuList变量,遍历时动态生成<tr><td>标签等,将数据展示出来。
注意:html代码和js代码中可以嵌入c#代码,只需要在每一句代码或者每一个代码块(用花括号包围)前加上"@"符号即可,如果需要换行,则在下一行的c#代码前也需要加上"@"符号。
例如:
<table> @foreach(var item in mylist) { <tr> <td>@item.id</td> <td>@item.name</td> @if(item.age<18) { <td>未成年</td>
}
@else
{
<td>@item.age 岁</td>
}
</tr>
}
</table>
还有这样一种常用的编程模式:
StudentController有一个Action即默认的Index()方法,当用户在浏览器跳转到http://localhost:8080/Student时,Index方法返回一个空的视图页面(即Index视图),
然后在视图内添加js代码,这段js代码是向StudentController发送ajax请求,请求的Action是GetStudentInfo()方法(url是http://localhost:8080/Student/GetStudentInfo),该方法通过BLL获取到数据之后进行返回,
向Index视图返回一个Json格式的List<Student>。Index视图再通过ajax请求中事先定义好的回调方法读取返回的数据,并加载到Index视图中。
还有另外一种做法,就是在用户请求http://localhost:8080/Student时,在Index方法内先通过BLL获取数据,然后在生成Index视图时直接把数据通过ViewBag传给视图,于是生成的视图已经包含了数据,无需再请求其他Action方法。
对比这两种做法,前者在响应速度上更快,因为它先生成了一个页面并返回给客户端,虽然是空页面。另外,它把读取数据的过程放在另外一个Action里,这样就使得该读取数据的Action更简单。而第二种做法的主要问题是读取数据的过程比较耗时,响应速度比较慢。
其他MVC基本知识:asp.net mvc 入门资料