• APS.NET MVC + EF (05)---控制器


    Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务端的交互,并且负责协调Model与View之间数据传递,是ASP.NET MVC框架核心。Controller为ASP.NET MVC框架的核心组成部分,其主要负责处理浏览器请求,并决定响应什么内容给浏览器,但并不负责决定内容应如何显示(View的职责)。

    5.1 动作方法

    Controller本身就是一个类(Class),该类别有许多方法(Method),这些方法中只要是公开方法(public method)就会被视为是一个动作(Action)或动作方法(Action Method),并可以通过该动作方法接收客户端传来的请求和决定响应的视图(View)。

    Controller应具备如下几个基本条件。

    (1)Controller必须为公开类别;

    (2)Controller名称必须以Controller结尾;

    (3)必须继承自ASP.NET MVC内建的Controller类别,或实现IController自定义类别;

    (4)动作方法必须为公开方法,任何非公开的方法如声明为private或protected的方法都不会被视为一个动作方法;

    5.1.1 同名方法问题

    在一般的类中,方法是可以重载的,但是动作方法是不可以重载的。如示例1中代码在编译的时候不会有任何问题,但在运行时就会出现如图5-1所示的错误。

    示例1

    public class AccountController : Controller

    {

    public ActionResult Register()

    {

    //省略代码

    }

    public ActionResult Register(User user)

    {

    //省略代码

    }

    }

       

    图5-1 动作方法不明确

    上面的错误说明ASP.NET MVC 路由系统不能凭借方法参数去定位动作方法。

    5.1.2 动作方法上的特性

    解决同名方法的问题一般有3种方法,3种方法都是要在动作方法上应用特性。

    1. 谓词筛选特性

      在ASP.NET MVC中,提供了区分不同请求的请求谓词筛选特性,如HttpGet、

      HttpPost、HttpDelete和HttpPut,分别对应Get、Post、Delete和Put几种请求。对于示例1的代码,可以按照示例2的方式应用特性。

      示例2

    public class AccountController : Controller

    {

    [HttpGet]

    public ActionResult Register()

    {

    //省略代码

    }

    [HttpPost]

    public ActionResult Register(User user)

    {

    //省略代码

    }

    }

    示例2的代码表示,Register( ) 方法只能对应到Get方式的请求,Register(User user)方法只能对应到Post方式请求。

    1. NonAction特性

      若控制器某个方法特性为NonAction,即使该Action方法是"公开方法",也不会被被看作Action来运行。

      主要用途:

    • 保护Controller中的特定公开方法不要发布到Web上;
    • 功能尚未开发完成就要进行部署,暂时不想将此方法删除。

    示例3

    public class HomeController : Controller

    {

    public ActionResult Index()

    {

    return View();

    }

    [NonAction]

    public ActionResult Index(int id)

    {

    return View();

    }

    }

       

    1. ActionName特性

      在ASP.NET MVC中,路由中定义的Action的名称和控制器中定义的动作方法的名称命名通常是一致的,但这只是一般的方法,也可以让Action和动作方法的名称不一致,用法如示例4所示。

      示例4

    public class HomeController : Controller

    {

    public ActionResult Register()

    {

    //省略代码

    }

    [ActionName("RegisterUser")]

    public ActionResult Register(User user)

    {

    //省略代码

    }

    }

    示例5中,将Register(User user)方法的Action名声明为RegisterUser,解决了同名冲突问题。使用这种方法,需要注意在视图中提交表单的Action属性也要做相应的修改,如下面的代码。

    <form action="/Account/RegisterUser" method="post">

    </form>

       

    5.1.3 动作方法的结果类型

    在前面的内容中,我们习惯使用ActionResult作为动作方法的返回类型,通过View()方法返回对象。其实View()方法的返回类型是ViewResult,ViewResult和ActionResult的关系图5-2所示。

     

    图5-2 ActionResult类关系图

    在动作方法定义中,很显然使用了多态,ActionResult是一个抽象类,返回的对象为子类类型。在实际的开发中,有时候不需要 向客户端输出HTML,而是文件、文本等其它一些输出,这时候子类就派上用场了,常用的输出类型如表5-1所示。

    表5-1 常用输出类型

    输出类型

    说 明

    EmptyResult

    输出空内容

    ContentResult

    将指定内容作为文本输出

    JsonResult

    输出JSON字符串

    JavaScriptResult

    输出JavaScript文件

    RedirectResult

    指定的 URI 来执行重定向

    RedirectToRouteResult

    指定路由值来执行重定向

    FilePathResult

    指定文件路径来输出文件

    FileContentResult

    指定字节数组来输出文件

    FileStreamResult

    指定流来输出文件

    ViewResult

    调用视图文件输出视图

    在实际使用这些类型时,不需要在动作方法中实例化这些类的实例再返回,再Controller类中,已经定义了返回这些类型实例的方法,直接调用即可。如View()方法。常用的方法如表5-2所示。

    表5-2 常用控制器输出方法

    类型

    方 法

    EmptyResult

    ContentResult

    Content(string content)

    JsonResult

    Json(object data)

    JavaScriptResult

    JavaScript(string script)

    RedirectResult

    Redirect(string url)

    RedirectToRouteResult

    RedirectToAction(string actionName)

    FilePathResult

    File(string fileName, string contentType)

    FileContentResult

    File(byte[] fileContents, string contentType)

    FileStreamResult

    File(Stream fileStream, string contentType)

    ViewResult

    View(string viewName)

    各种方法的用法如示例5所示。

    示例5

    public class HomeController : Controller

    {

    public ActionResult Index()

    {

    return View();

    }

    //页面跳转

    public ActionResult RedirectTest()

    {

    return Redirect("/Home/Detail");

    }

    //页面跳转

    public ActionResult RedirectToRouteTest()

    {

    return RedirectToRoute(new { controller = "Home",

    action = "Detail", id = 1, cate = "test" });

    }

    //页面跳转

    public ActionResult RedirectToActionTest()

    {

    return RedirectToAction("Detail", new { id = 1,

    cate = "test" });

    }

    //输出JSON文件

    public ActionResult JsonTest()

    {

    var book = new

    {

    bookid = 1,

    bookName = "精通ASP.NET MVC",

    author = "Fangyc",

    publishData = DateTime.Now

    };

    return Json(book, JsonRequestBehavior.AllowGet);

    }

    //输出JavaScript文件

    public ActionResult JavaScriptTest()

    {

    string js = "alert('Welecome to ASP.NET MVC!')";

    return JavaScript(js);

    }

    //按文件路径输出文件

    public ActionResult FilePathTest()

    {

    return File("~/Content/rain.mp3", "audio/mp3");

    }

    //对字符串编码并输出文件

    public ActionResult FileContentTest()

    {

    string content = "Welcome to ASP.NET MVC!";

    byte[] contents = System.Text.Encoding.UTF8.GetBytes(content);

    return File(contents, "text/plain");

    }

    //用文件流输出文件

    public ActionResult FileStreamTest()

    {

    string content = "Welcome to ASP.NET MVC!";

    byte[] contents = System.Text.Encoding.UTF8.GetBytes(content);

    FileStream fs = new FileStream(

    Server.MapPath("~/Content/ASP.NET MVC.pdf"),

    FileMode.Open);

    return File(fs, "application/pdf");

    }

    //输出简单文本

    public ActionResult ContentTest()

    {

    string content = "<h1>Welcome to ASP.NET MVC!</h1>";

    return Content(content);

    }

    }

       

    在ASP.NET MVC中,动作方法的返回类型并不一定是ActionResult类型,也可以是其它任何类型,甚至是void类型,如下面的代码。

    public int Sum(int num1,int num2)

    {

    int sum=num1+num2;

    return sum;

    }

    public void log()

    {

    File.WriteAllText(@"D:log.test", "保存文件");

    }

    上述这种返回类型的动作方法称为隐式动作方法,ASP.NET MVC 自动做了一些处理,将void类型对应到EmptyResult类型,将其它非ActionResult类型对应到ContentResult类型。

    5.2 动作方法参数

    我们以前在动作方法中获取 URL 和表单数据的方法,可能会采用如下方式:

    string name=Request.Forms["name"];

    string id=RouteData.Values["id"];

    除了上面的方法外,ASP.NET MVC 还提供了更加便利的方法。

    5.2.1 简单类型映射

    在ASP.NET MVC中,可以把路由数据、URL数据、表单数据自动映射到动作方法参数中,这些参数可以直接定义为基本数据类型或string类型。

    示例6

    public ActionResult Detail()

    {

    int id = Request.QueryString["id"] != null?

    Convert.ToInt32(RouteData.Values["id"]):0;

    // 省略代码

    return View();

    }

       

    public ActionResult Detail(int id=0)

    {

    // 省略代码

    }

    示例6中,第二个方法参数使用了数据映射的功能,RouteData.Values["id"]的值可以自动映射到参数id中。

    示例7

    public ActionResult List()

    {

    int pageCount = 0;//总页数

    int categoryId = Request.QueryString["categoryId"] != null

    ? Convert.ToInt32(Request.QueryString["categoryId"]) : 1;

    //页序号

    int pageIndex = Request.QueryString["pageIndex"] != null

    ? Convert.ToInt32(Request.QueryString["pageIndex"]) : 1;

    //排序字段

    string order = Request.QueryString["order"] != null

    ? Convert.ToString(Request.QueryString["order"]) : "PublishDate";

    BookManager manager = new BookManager();

    List<Book> list = manager.GetBooks(

    categoryId, this.PageSize, pageIndex, ref pageCount, order);

    }

       

    public ActionResult List(int categoryId = 1, int pageIndex = 1,

    string order = "PublishDate")

    {

    int pageCount = 0;//总页数

    BookManager manager = new BookManager();

    List<Book> list = manager.GetBooks(categoryId, this.PageSize, pageIndex, ref pageCount, order);

    }

      

    示例7中,第二个方法参数使用了数据映射的功能,该方法定义了多个参数,各个参数的值都由Request.QueryString映射而来。

    示例8

    public ActionResult LogIn()

    {

    string userName=Request.Form["userName"];

    string password=Request.Form["password"];

    string returnUrl=Request.Form["returnUrl"];

    // 省略代码

    }

    public ActionResult LogIn(string userName, string password, string returnUrl)

    {

    // 省略代码

    }

       

    从上述三个示例可以看出,使用动作方法参数自动映射,简化了大量代码。

    获取数据的优先级依次是表单数据--->路由数据--->URL数据。在定义动作方法参数时,需要保证以下两点。

    • 参数名要和目标数据参数名一致(不区分大小写)。
    • 参数数据类型要和来源数据的目标数据类型一致。

    对于值类型参数的数据,如果从来源数据获取不到相应的值,就会出现参数映射的运行时错误,一般把这种参数直接声明为可空类型或可选参数。

       

    5.2.2 映射模型

    动作方法参数的映射不仅仅是简单类型,还可以是复杂类型。如示例 8所示。

    示例8

    <form action="/Account/RegisterUser1" class="member_form" id="Form1"

    method="post">

    <p>

    <label><span>*</span>用户名</label>

    <input class="opt_input" name="LoginId" type="text"/>

    5-12个字符或数字组成,可用中文名

    </p>

    <p>

    <label><span>*</span>真实姓名</label>

    <input class="opt_input" name="Name" type="text"/>

    </p>

    <p>

    <label><span>*</span>&#160;&#160;&#160;&#160;</label>

    <input class="opt_input" name="LoginPwd" type="password"/>

    </p>

    <p>

    <label><span>*</span>确认密码</label>

    <input class="opt_input" name="PasswordConfirm" type="password" />

    </p>

    <p>

    <label><span>*</span>电子邮件</label>

    <input class="opt_input" name="Mail" type="text" />

    </p>

    <!-- 省略其它代码 -->

    </form>

       

    // 控制器代码

    public ActionResult RegisterUser(User user)

    {

    UserManager manager = new UserManager();

    if (!manager.Register(user))

    {

    //省略代码

    }

    return View("Register", user);

    }

      

    示例8的方法中,并没有创建User对象,也没有给其属性赋值。其实这些工作是ASP.NET MVC通过分析User对象的属性和表单中元素按名称进行匹配并进行赋值。通过这种方式,自动完成对象创建和初始化赋值工作。这也被称为ASP.NET MVC的模型自动绑定功能。

       

    5.3 案例:用户注册(或信息添加)

       

       

       

       

  • 相关阅读:
    message sent to deallocated instance
    将本地项目提交github
    WKWebView 初窥-JS交互探究
    抓包工具Charles的使用
    iOS hook delegate (一)
    Return
    控制方法只有相应权限才可执行
    如何模拟登陆添加了CSRF保护的网站
    HTTP客户端都应该支持的五个特性
    如何利用WebClient模拟登陆CSRF控制的网站
  • 原文地址:https://www.cnblogs.com/mrfang/p/10776034.html
Copyright © 2020-2023  润新知