当前位置: 首页 > news >正文

Asp.Net MVC系列--进阶篇之controller(1)

通过实现接口IController完成一个controller

对于默认的路由:

routes.MapRoute(
                name: "Default",
                url:"{controller}/{action}/{id}",
                defaults: new { controller ="Home", action = "Index", id = UrlParameter.Optional }
           );


 

添加controller:

public void Execute(RequestContextrequestContext)
       {
           var controller = (string)requestContext.RouteData.Values["controller"];
           var action =(string)requestContext.RouteData.Values["action"];
           requestContext.HttpContext.Response.Write(
           string.Format("Controller: {0}, Action: {1}", controller,action));
 
       }


访问controller查看结果:


这是最简单的controller创建方式,但是通常不这样做,因为:

我们拿到的是RequestContext对象,需要手动去生成html写到Response里面返回客户端,代码将很难维护。

 

集成Controller类完成一个controller

一般的,每当我们新建一个controller,都是自动继承controller类,这个类主要帮我们完成两件事情:

1.      会从路由拿到requestContext对象,解析出action以及参数,并调用

2.      提供不同的resultcommand模式),返回给客户端

另外,我们还可以使用filter,完成不同的crosscutting的concern,后面章节会详细介绍。

由于引入了action和result的概念,使得我们的代码更容易单元测试,起码比我们自己继承IController接口,直接操作RequestContext对象容易很多。

 

controller示例:

 

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


View代码:

@{
ViewBag.Title ="MyView";
}
<h2>MyView</h2>
Message: @ViewBag.Message


 

代码很简单,就是用Viewbag传值到View显示出来,Controller返回了最常用的result,ViewResult。

 

从controller获取客户端传值的方式

1.      从context object 直接提取

2.      通过参数传进来(由基类controller完成解析)

3.      通过model binding

 

context object常用的对象

Request.QueryString

从Get 请求的url中取

Request.Form

从Post请求的表单取

Request.Cookies

把值放在请求的cookie里带过来

RouteData.Route

从路由表里取注册的路由名

RouteData.Values

从路由表获取路由配置的匿名对象

HttpContext.Cache

应用程序缓存

HttpContext.Items

存储一些值,只在同一请求中使用(可以在httppipeline过程的不同module,handler,以及页面传递值)

HttpContext.Session

当前用户的session

TempData

存一些临时值,取出后会被自动删除

 

另外,不建议直接从RouteData.Values直接取传来的参数值:

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

return View(forDate);
}


 

建议改写为传参:

public ActionResult ShowWeatherForecast(string city, DateTime forDate) {

return View(forDate);
}


关于传参,注意:

1.      对于引用类型,如果RouteData没有拿到参数,那么就给null了,如果要避免接收null,可以使用默认参数

2.      对于值类型,如果没有拿到参数,就会抛出异常,因此,建议值类型总提供默认参数,或者使用Nullable类型

例如:

public ActionResult Search(stringquery= "all", int page = 1) {
// ...process request...
return View();
}


使用Execute Result


Controller的职责:

1.      操作domain model

2.      返回一个合适的result

 

操作完domainmodel之后,就要给客户端返回result了,不推荐手动去实现IController接口进行Redirect或者直接Response.Write数据给客户端。前面说过了:

1.      直接输出html,或者直接跳转url,降低了可读性和可维护性

2.      很难单元测试

3.      交接很难上手

 

使用ActionResult

MVC Framework 的controller已经给我们了足够的result类型来返回给客户端完成交互。为了了解ActionResult,先customize一个:

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


要customize一个result,需要继承ActionResult,主要实现ExecuteResult方法,MVCFramework给我们了一个controllerContext对象,里面有足够我们需要的信息,以上创建的actionResult功能:指定一个url,拿到controllerContext对象生成一个fullurl,完成跳转。

使用这个result:

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


常用的result:

ViewResult

返回一个view,可以指定不同的controller

ParcialViewResult

返回部分view

RedirectToActionResult

转到另一个action

RedirectResult

返回301或者302(permanent)

JsonResult

返回js最喜欢的json,常用,尤其当前段打算采用纯js template,或者single page application

FileResult

文件result

ContentResult

字符串

HttpUnauthorizedResult

401,通常,会自动跳转到登陆页面

HttpNotFoundResult

404

 

返回viewResult时,查找顺序:

1.      /Views/<ControllerName>/<ViewName>.aspx

2.      /Views/<ControllerName>/<ViewName>.ascx

3.      /Views/Shared/<ViewName>.aspx

4.      /Views/Shared/<ViewName>.ascx

5.      /Views/<ControllerName>/<ViewName>.cshtml

6.      /Views/<ControllerName>/<ViewName>.vbhtml

7.      /Views/Shared/<ViewName>.cshtml

8.      /Views/Shared/<ViewName>.vbhtml

可以看到,mvcframework会先从熟悉的aspx和ascx找起

 

直接传递路径,返回指定view

public ViewResult Index() {
return View("~/Views/Other/Index.cshtml");
}


如果出现类似以上的代码,请思考两个问题:

想要跳转到另一个action?可以考虑使用RedirectToAction

View是否放错了位置?

 

Action传值到View

Model Object

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


 

View中:

@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();
}


View中:

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


ViewBag优点:

可以不需要定义类型直接传递,并且可以传递任意个对象

缺点:

错误总是运行时,由于是DynamicObject(实际是DynamicViewDataDictionary继承自DynamicObject,因此是像其他functionlanguage语言一样可以动态扩展的)

 

跳重定向到指定url

HttpStatusCode : 302(临时重定向)

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


HttpStatusCode:301 (永久重定向,使用小心,不常用)

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


跳转回route

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


大多数情况,遇到处理不掉的请求,我们起码是可以确定跳转到哪个controller和action的:

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


可以指定controller:

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


Redirection过程中传值

在MVCframework中,理想选择应该是使用TempData:

赋值:

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


取值:

public ViewResult Index() {
ViewBag.Message =TempData["Message"];
ViewBag.Date =TempData["Date"];
return View();
}


这个对象的好处是,取完就被标记为removable了,请求完毕会自动清掉。如果想取多次,那么可以使用peek方法(但是还是建议最后一次取了清掉(用索引取)):

TempData.Peek("Date");

另外,笔者还推荐HttpRequest.Items,也是在httppipeline内传值的一个不错的选择。

 

 

返回httpstatus code

 

404 (url 找不到):

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


 

401(访问权限受限):

public HttpStatusCodeResult StatusCode() {
return new HttpUnauthorizedResult();
}


 

相关文章:

  • Windows 7下可以使用的虚拟光驱软件
  • Asp.Net MVC 系列--进阶篇之Filter
  • 10个非常有用的Windows 7优化调整技巧
  • Asp.Net MVC4 系列--进阶篇之Controller(2)
  • Windows 7快捷键及鼠标动作大全
  • C# 将多个Image 合成为一个,格式可选择
  • IE8 正式版(RTM) 的版本号: 8.0.6001.18702
  • Iori的工具箱 之 C# 实现多个图片合为一个Tiff
  • Asp.Net MVC4 系列--进阶篇之View
  • Xp+Windows 7硬盘安装 体验心得
  • Javascript 实现的StopWatch
  • Asp.Net MVC4系列--进阶篇之Helper(1)
  • 玻璃效果
  • Asp.Net MVC4 系列--进阶篇之Helper(2)
  • 主流杀毒软件多已支持windows7
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • css布局,左右固定中间自适应实现
  • ES6 ...操作符
  • Fastjson的基本使用方法大全
  • javascript数组去重/查找/插入/删除
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • Mybatis初体验
  • MySQL-事务管理(基础)
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • session共享问题解决方案
  • SQL 难点解决:记录的引用
  • Zsh 开发指南(第十四篇 文件读写)
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 给新手的新浪微博 SDK 集成教程【一】
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 前端临床手札——文件上传
  • 深度学习中的信息论知识详解
  • 手机端车牌号码键盘的vue组件
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 原生JS动态加载JS、CSS文件及代码脚本
  • Linux权限管理(week1_day5)--技术流ken
  • ​linux启动进程的方式
  • # 数论-逆元
  • #宝哥教你#查看jquery绑定的事件函数
  • (10)ATF MMU转换表
  • (python)数据结构---字典
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (办公)springboot配置aop处理请求.
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (一)基于IDEA的JAVA基础12
  • (译) 函数式 JS #1:简介
  • (转)h264中avc和flv数据的解析
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .bat批处理出现中文乱码的情况
  • .htaccess 强制https 单独排除某个目录
  • .Net 8.0 新的变化
  • .NET Framework 4.6.2改进了WPF和安全性
  • .net 简单实现MD5