• 学习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/>没有换行而是直接显示出来了?百思不得其解啊

  • 相关阅读:
    dart 函数迭代器
    dart 编译
    dart 扩展方法
    dart 包
    默认2345导航
    (24)WPF 数据绑定
    (22)WPF 控件模板
    JSP慕课网之Session
    HTML <td> 标签的 colspan 属性
    HTML Input属性
  • 原文地址:https://www.cnblogs.com/Scissors/p/2946717.html
Copyright © 2020-2023  润新知