学习ASP.NET MVC3(5)----- Controller

 

其实按照正常的顺序来说,是应该先讲模型(Model) ,再讲控制器和视图的

但是由于模型完全可以专门用一层来做(比如多层架构的实体层)

因为实际上控制器Action的代码应该越少越好而将复杂的业务逻辑和数据访问留给"模型"去做,如果控制器包含过多的代码

则有可能将它变成另一种Page_Load的形式而不利于维护,但是如果在UI层上独立出一个模型文件夹来做这些,似乎和WPF的MVVM模式相差不多

而且复杂繁杂的代码完全可以用多层(BLL,Dao,Entitties等等)解决 ,所以在ASP.NET MVC中的模型意义并不大

 

对于我来说甚至可以忽略跳过 所以就跳过吧````

注意 上面所说的"模型"并不是具指实体层

 

ASP.NET MVC请求过程

 

一个用户 通过浏览器(Browser)发出一个请求,提交给Server端

途中经过iisapi.dll这个程序集的处理和ASP.NET基本框架的处理

然后通过路由(Routing)动态的调用Controller来处理响应的请求

请求调用时实际上就是调用Controller里的某个Action

Action通过种种处理(人工代码处理)执行一些业务逻辑,然后把Model和ViewData(要给客户展示的数据)传输给视图(View)

然后视图通过一系列框架上的东西渲染好HTML返回给客户端

 

 

Controller

控制器在ASP.NET MVC中扮演着处理客户端请求的角色

     必须实现System.Web.Mvc.IController接口,通常直接继承System.Web.Mvc.Controller类

     必须要以Controller结尾

     通过不同的Action来处理具体的客户端请求

 

Action

是指在继承了System.Web.Mvc.Controller类中所以定的返回值的类型可以兼容ActionResult的方法

 

 

ASP.NET MVC 3的ActionResult

 

 

接下来看一个普通的控制器,和以前一样所有的解释都在注释里 这样比较直观

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

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        //这个Index就相当于WebForm里的Default.aspx页面
        //并不是说MVC里的"首页"就必须是这个Index方法/Action
        public ActionResult Index()
        {
            //下面的代码等同于ViewData["Message"] = "Welcome to ASP.NET MVC!";  但是ViewData这种写法相对啰嗦 而且是纯字符串的不好控制
            //其实ViewBag并没有Message这个属性, 但是它会在运行时发现,所以当这个Action传到相应的View的时候  可以在View里点出Message这个属性
            ViewBag.Message = "Welcome to ASP.NET MVC!";
            ViewBag.张三的名字 = "张三";
            
            //View()这个方法返回一个ViewResult类型,也就是返回一个页面
            //大家可能会觉得奇怪,View()方法并没有指定返回哪个页面,实际上View()有很多重载,你可以return View("ViewName")这样子来指定一个具体的视图
            //如果没有指定的话,他会在和此控制器相同的视图文件夹里找到与此Action相对应的视图,比如现在这个是Home控制器的IndexAction、
            //那它就会找Views文件夹下的Home文件夹下的Index.cshtml文件作为默认返回视图
            return View();
        }

        public ActionResult About()
        {
            //返回Views文件夹下的Home文件夹下的About.cshtml
            return View();
        }
    }
}

对应的Index的view:

@{
    ViewBag.Title = "Home Page";
}

<!--这里的Message就是开始在控制器已经赋好值的Message,值为Welcome to ASP.NET MVC!直接点出来使用-->
<h2>@ViewBag.Message</h2>
<p>
    To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
</p>

 

如果要返回一个404的页面呢:

        public ActionResult Page404()
        {
            return HttpNotFound();
        }

效果如下:

如果将Action的名字改一下为Page405  但是访问的URL不变的话是什么样呢:

public ActionResult Page405() 
        {
            return HttpNotFound();
        }

效果如下:

 虽然都是404,但是不同之处我想大家应该能够了解了吧

 

接下来在看个例子,自己创建一个继承Controller的类

上面忘记说了,如果要建立自己的控制器,就在添加里选择Controller就好了(当然也可以手动添加一个类,然后手动继承Controller类)

ControllerBase.cs:

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

namespace MvcApplication1.Controllers
{
    public class ControllerBase : Controller
    {
        public ActionResult Test()
        {
       //返回一个空白页
return new EmptyResult(); } } }

然后修改HomeController继承自上面的ControllerBase:

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

namespace MvcApplication1.Controllers
{
    public class HomeController : ControllerBase
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";
            ViewBag.张三的名字 = "张三";
            
            return View();
        }

        public ActionResult Page405() 
        {
            return HttpNotFound();
        }

        public ActionResult About()
        {
            return View();
        }
    }
}

运行看效果(把URL改为Home的Test):

可以看到就是个普通的空白页

HomeController里虽然没有Test这个Action,但是由于继承了ControllerBase,所以就也有了

创建自定义的ControllerBase,可以将很多通用的方法放在里面,以后每个控制器直接使用 方便很多

 

 

用于控制动作定义的特性

1.NonAction

2.ActionName

3.AcceptVerbs 

 

NonAction:

使用该特性标记的公有方法不会被视为动作。

        [NonAction]
        public void ThisIsNotAnAction()
        { 
            //do something
        }

 

ActionName:

通过使用ActionName改变动作的名称

 

AcceptVerbs:

该特性设置动作能够对其做出响应的HTTP动词。例如,创建一个用于编辑产品细节的表单,需要两个方法:一个用于使用其数值编写表单,另一个用于将表单数值存储到数据库中

你可以编写两个独立的动作,一个名为WriteForm,另一个为ProcessForm,这不是一个好方法,因为为同一功能提供两个名称

或者使用AcceptVerbs特性,编写两个具有相同动作名称并且影响不同动词的方法,最常用的HTTP动词是GET和POST

当单击一个链接时使用第一个动词,而提交表单的时候使用第二个动词  如下列代码所示:

 

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult 更新信息()
        { 
            //do something 显示表单
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult 更新信息(FormCollection form)
        {
            //do something 更新信息到数据库
            return View();
        }

 

其实AcceptVerbs是以前的写法,MVC 3可以直接使用[HttpGet]和[HttpPost]

 

 

注意事项

能够通过URL访问的Action必须是Public的

如果标记了[NonAction]属性,则不能通过URL访问

默认,Action的方法名就是Action名(通过URL访问的名称),如有特殊需求也可以通过ActionName标记出特定的Action名

我们可以通过[HttpGet]和[HttpPost]来区分处理不同请求动作的同名Action

 

从请求检索数据

1.向动作传递简单类型

从请求检索数据的第一种方法是将数据作为方法参数传递给动作。或提供来自只包含几个参数的Post操作的参数。这种情况下,只能向动作传递简单类型数据,如整型或字符串等

从URL检索值(路由会在后面讲到,这里随便了解)

假如一个路由的规则为{controller}/{action}/{id},并且请求的URL是:http://localhost/Home/Edit/12,则Home对应{controller}、Edit对应{action}、12对应{id}

框架使用前两个标记确定控制器和动作(确定是哪个控制器的哪个Action),之后的所有标记将作为参数传递给动作

 

现在假定有一个动作并且接收几个参数 如下所示:

public ActionResult dongzuo(int year,int month,int day,string title,int commentId)

具有如下路由规则:

{controller}/{action}/{year}/{month}/{day}/{title}

请求的URL为:http://localhost/Home/dongzuo/2013/04/01/My-Birthday?commentId=4577

请求到达后,dongzuo这个动作的参数的值如下:

year:2013

month:04

day:01

title:My-Birthday

commentId:4577

前4个参数是从URL检索到的,并且映射到在路由规则中定义的标记,而最后一个commentId是从同名的查询字符串变量检索到的

所以,当请求到达后,你就可以使用动作那些参数进行操作了

 

2.从Post数据检索到值

除了URL和查询字符串检索参数值,还可以从使用POST提交的HTML表单获取值。具体只需要将HTML输入控件命名为参数名即可

接下来看个例子:

(1)首先创建一个新的ASP.NET MVC WEB站点

(2)创建一个控制器类,命名为BlogController,并为其添加两个方法:Create和Save

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
    public class BlogController : Controller
    {

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Create()
        {
            return View();
        }

        public ActionResult Save(string postTitle,string postText)
        {
            ViewBag.Message = string.Format("Title:{0}<br/>Text:{1}", postTitle, postText);
            return View();
        }
    }
}

 

(3)在Views文件夹下创建一个新文件夹,命名为Blog

(4)在该新文件夹中添加一个内容视图页面,并将其命名为Create.cshtml:

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

<form action="/Blog/Save" method="post">
    Title:<input type="text" id="postTitle" name="postTitle" /><br />
    Text:<input type="text" id="postText" name="postText" /><br />
    <input type="submit" />
</form>

(5)添加另外一个内容视图页面,并将其命名为Save.cshtml:

@{
    ViewBag.Title = "Save";
}

<h2>Save</h2>
从Create页面提交过来的值 @ViewBag.Message

(6)现在启动该Web站点,浏览到/Blog/Create 试一下,效果如下:

 

话说为啥<br/>没有换行而是直接显示出来了?百思不得其解啊

 

 

 

posted @ 2013-03-06 19:04  韬韬韬你羞得无礼  Views(351)  Comments(0Edit  收藏  举报