zoukankan      html  css  js  c++  java
  • ASP.NET MVC 4 (二)控制器

    MVC中控制器负责处理请求,由它操作数据模型,最后返回视图给用户。

    IController接口

    所有的控制器类以Controller结尾,必须实现System.Web.Mvc.IController接口,一个最简单的控制器类可以是:

    public class BasicController : IController {
    
            public void Execute(RequestContext requestContext) {
    
                string controller = (string)requestContext.RouteData.Values["controller"];
                string action = (string)requestContext.RouteData.Values["action"];
    
                if (action.ToLower() == "redirect") {
                    requestContext.HttpContext.Response.Redirect("/Derived/Index");
                } else {
                    requestContext.HttpContext.Response.Write(
                        string.Format("Controller: {0}, Action: {1}", 
                        controller, action));
                }
            }
        }

    BasicController类实现了IController的唯一方法Execute(),在上面的例子中直接返回数据到请求响应,我们可以根据自己的需求来灵活的处理客户请求。

    Controller类

    更多的时候我们直接继承MVC已经定义的控制类System.Web.Mvc.Controller:

     public class DerivedController : Controller
        {
    
            public ActionResult Index()
            {
                ViewBag.Message = "Hello from the DerivedController Index method";
                return View("MyView");
            }
    
        }

    Controller类封装的IController.Execute()方法会调用我们定义的Action方法,比如这里的Index()。Controller同时为我们提供了众多的属性来方便获取相关数据:

    • Request:比如Request.QueryString、Request.Url、Request.Form、Request.HttpMethod等。
    • Response:可以直接向Response返回数据到用户。
    • RouteData:和路径映射相关的数据,比如RouteData.Route、RouteData.Values。
    • HttpContext:比如HttpContext.HttpSessionStateBAse、HttpContext.Items。
    • User:当前已会话已认证的用户信息。
    • TempData:存储当前用户的一些临时信息,可以传递给View。

    一些获取Controller数据的例子:

    string userName = User.Identity.Name; 
    string serverName = Server.MachineName; 
    string clientIP = Request.UserHostAddress; 
    DateTime dateStamp = HttpContext.Timestamp; 
    AuditRequest(userName, serverName, clientIP, dateStamp, "Renaming product"); 
    // Retrieve posted data from Request.Form 
    string oldProductName = Request.Form["OldName"]; 
    string newProductName = Request.Form["NewName"]; 
    bool result = AttemptProductRename(oldProductName, newProductName); 
    ViewData["RenameResult"] = result; 
    return View("ProductRenamed"); 

    Action方法参数 

    控制器Action方法可以带一系列的参数,比如:

    ... 
    public ActionResult ShowWeatherForecast(string city, DateTime forDate) { 
    // ... implement weather forecast here ... 
    return View(); 
    } 
    ... 

    这些参数是由MVC的Value providers和model binders所提供的,MVC自动从请求数据等中自动按名称为我们解析参数值并做类型转换,比如上面例子中的city和forDate可能来自于:

    string city = (string)RouteData.Values["city"]; 
    DateTime forDate = DateTime.Parse(Request.Form["forDate"]); 

    响应输出

    我们可以从Icontroller的Excecute()方法中直接输出响应,也可以在Controller中使用Response直接输出响应:

    public void ProduceOutput()
            {
                if (Server.MachineName == "TINY")
                {
                    Response.Redirect("/Basic/Index");
                }
                else
                {
                    Response.Write("Controller: Derived, Action: ProduceOutput");
                }
            }  

    这里的Action方法ProduceOutput没有返回值,更多的时候,我们返回一个ActionResult对象,比如View("MyView")返回一个ViewResult,ViewResult继承自ActionResult。甚至我们可以创建自定义的ActionResult类来使用: 

    public class CustomRedirectResult : ActionResult { 
      public string Url { get; set; } 
      public override void ExecuteResult(ControllerContext context) { 
      string fullUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext); 
      context.HttpContext.Response.Redirect(fullUrl); 
      } 
    } 

    在控制器Action方法中返回自定义的ActionResult对象:

    public ActionResultProduceOutput() { 
      if (Server.MachineName == "TINY") { 
          return new CustomRedirectResult { Url = "/Basic/Index" }; 
        } else { 
          Response.Write("Controller: Derived, Action: ProduceOutput"); 
          return null; 
        } 
    } 

    这里创建了一个实现重定向的ActionResult对象,实际上MVC已经为我们提供了RedirectResult来实现这个功能:

    ... 
    public ActionResult ProduceOutput() { 
    return new RedirectResult("/Basic/Index"); 
    } 
    ... 

    或者更方便的调用Controller的Redirect()方法:

    ... 
    public ActionResult ProduceOutput() { 
    return Redirect("/Basic/Index"); 
    } 
    ... 

    除了RedirectResult,MVC还提供这些ActionResult:

    • ViewResult:渲染一个视图,等同于控制器中调用View()
    • PartialViewResult:渲染部分视图,等同于控制器中调用PartialView()
    • RedirectToRouteResult:根据指定的路由信息发出一个HTTP 301或者302重定向命令,等同于控制器调用RedirectToAction 、RedirectToActionPermanent 、RedirectToRoute 、RedirectToRoutePermanent。
    • HttpUnauthorizedResult:设置HTTP状态码401表示未授权。
    • HttpNotFoundResult:返回HTTP 404-NOT FOUD错误,等同于控制器调用HttpNotFound()。
    • HttpStatusCodeResult:返回自定义的HTTP状态码
    • EmptyResult:不返回任何信息。

    返回视图

    用得最多的就是在控制器Action方法中返回一个视图,由它渲染HTML返回给用户。我们可以不带任何参数调用View(),MVC会查找和Action方法同名(不带Controller)的View,也可以直接在参数中指定视图的名称:

    public ViewResult Index() { 
      return View("Homepage"); 
    } 

    MVC在应用目录下搜索视图,如果启用了区域Area,搜索路径为:

    •  /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.aspx 
    •  /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.ascx 
    •  /Areas/<AreaName>/Views/Shared/<ViewName>.aspx 
    •  /Areas/<AreaName>/Views/Shared/<ViewName>.ascx 
    •  /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.cshtml 
    •  /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.vbhtml 
    •  /Areas/<AreaName>/Views/Shared/<ViewName>.cshtml 
    •  /Areas/<AreaName>/Views/Shared/<ViewName>.vbhtml 

    如果没有使用Area,搜索路径为:

    •  /Views/<ControllerName>/<ViewName>.aspx 
    •  /Views/<ControllerName>/<ViewName>.ascx 
    •  /Views/Shared/<ViewName>.aspx 
    •  /Views/Shared/<ViewName>.ascx 
    •  /Views/<ControllerName>/<ViewName>.cshtml 
    •  /Views/<ControllerName>/<ViewName>.vbhtml 
    •  /Views/Shared/<ViewName>.cshtml 
    •  /Views/Shared/<ViewName>.vbhtml 

    MVC如果按照上述顺序搜索视图,如果找到一个文件就停止搜索,如果没有可用的视图文件会返回资源未找到错误。注意MVC会搜索ASPX视图引擎的老式文件.aspx和.ascx。

    View方法还有其他一些重载调用方式:

    return View("Index", "_AlternateLayoutPage"); //指定要使用的布局模板
    return View("~/Views/Other/Index.cshtml"); //直接指定要使用的视图模板,必须以/或者~/开头。

    从控制器向视图传递数据

    我们可以在调用View()直接指定要传递给视图的数据:

    ... 
    public ViewResult Index() { 
    DateTime date = DateTime.Now; 
    return View(date); 
    } 
    ... 

    在视图中使用传入的数据:

    @{ 
    ViewBag.Title = "Index"; 
    } 
    <h2>Index</h2> 
    The day is: @(((DateTime)Model).DayOfWeek) 

    对于强类型的视图,使用起来更方便:

    @model DateTime 
    @{ 
    ViewBag.Title = "Index"; 
    } 
    <h2>Index</h2> 
    The day is: @Model.DayOfWeek

    也可以使用ViewBag来传递,它是一个动态的键值对集合:

    public ViewResult Index() { 
    ViewBag.Message = "Hello"; 
    ViewBag.Date = DateTime.Now; 
    return View(); 
    } 

    在视图中使用:

    @{ 
    ViewBag.Title = "Index"; 
    } 
    <h2>Index</h2> 
    The day is: @ViewBag.Date.DayOfWeek 
    <p /> 
    The message is: @ViewBag.Message 

    Viewbag比视图模型好在可以传递多个值,但是VS不会给出IntelliSense提示,只会在渲染视图时给出错误信息。

    重定向

    在上面我们已经看到可以使用Redirect重定向请求:

    public RedirectResult Redirect() { 
    return Redirect("/Example/Index"); 
    } 

    也可以使用RedirectPermanent永久重定向:

    return RedirectPermanent("/Example/Index");

    和Redirect临时重定向发出302 HTTP代码不同,RedirectPermanent发回301 HTTP代码,前者指示浏览器重新GET新的URL,而后者指示浏览器缓存重定向信息,以后针对老URL的请求自动转向新URL。

    除了重定向到URL,我们可以重定向到路径映射方法:

    public RedirectToRouteResult Redirect() { 
      return RedirectToRoute(new { controller = "Example", action = "Index", ID = "MyID" }); 
    } 

    或者一个Action方法:

    public RedirectToRouteResult RedirectToRoute() { 
        return RedirectToAction("Index"); 
    } 

    可以指定是某个控制器的某个Action方法:

    public RedirectToRouteResult Redirect() { 
        return RedirectToAction("Index", "Basic"); 
    }  

    如果在重定向另一个控制器的Action时我们想要传递数据该怎么办呢?我们可以使用TempData:

    public RedirectToRouteResult RedirectToRoute() { 
    TempData["Message"] = "Hello"; 
    TempData["Date"] = DateTime.Now; 
    return RedirectToAction("Index"); 
    } 

    在新的视图中读取TempData:

    @{ 
    ViewBag.Title = "Index"; 
    } 
    <h2>Index</h2> 
    The day is: @(((DateTime)TempData["Date"]).DayOfWeek) 
    <p /> 
    The message is: @TempData["Message"]

    和ViewBag只用于控制器和同名视图不同,TempData类似于会话Session数据,可以在不同控制器/视图中共享,但是和Session跨请求不同的是一旦读取了TempData的数据TempData就会被删除。TempData.Peek读取数据但是不删除数据:

    DateTime time = (DateTime)TempData.Peek("Date"); 

    TempData.Keep可以标记数据不被删除,但是如果再被读取又会再次标记删除,类似于引用计数器:

    TempData.Keep("Date"); 

    返回HTTP状态码

    我们可以返回一个HTTP状态码比如404错误:

    public HttpStatusCodeResult StatusCode() { 
    return new HttpStatusCodeResult(404, "URL cannot be serviced"); 
    } 

    或者直接调用:

    return HttpNotFound(); 

    401未授权错误:

    return new HttpUnauthorizedResult();

     以上为对《Apress Pro ASP.NET MVC 4》第四版相关内容的总结,不详之处参见原版 http://www.apress.com/9781430242369

  • 相关阅读:
    MFC加载图片
    动态数组类
    MFC程序打包方法
    如何在C++中使用动态三维数组
    Ansys热应力计算
    像使用数据库一样使用xml
    过年回家的一点感想
    前后端框架和设计模式
    国外支付PayPal
    可重用的管理后台代码
  • 原文地址:https://www.cnblogs.com/GoogleGetZ/p/5835754.html
Copyright © 2011-2022 走看看