控制器-各种ActionResult【2】

本文详细介绍了ASP.NET MVC中各种ActionResult的使用方法及其应用场景,包括PartialViewResult、ContentResult、JsonResult、JavaScriptResult、RedirectResult、FileResult等,并提供了丰富的示例代码。

控制器-各种ActionResult   

ASP.NET MVC几种ActionResult的本质

我们所看到的Action都是return View();我们可以看作这个返回值用于解析一个aspx文件。而它的返回类型是ActionResult如

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

除了View()之外那我们这里还能用于返回什么值呢?


<1>ascx页面  分部视图  PartialViewResult

场景:要返回代码片断,比如Ajax返回一个子页

让我们先建立一个TestController.cs控制器;我们先新建一个Action

public PartialViewResult Ascx()
{
    return PartialView();
}

然后给这个Action添加一个视图Ascx.cshtml

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Ascx</title>
</head>
<body>
    <div>
       <table border="1">
        <tr><th>中国</th><th>美国</th><th>英国</th></tr>
        <tr><th>湖南</th><th>纽约</th><th>巴黎</th></tr>
       </table> 
    </div>
</body>
</html>
在浏览器中运行 http://localhost:8439/Test/Ascx   得到的结果是一个ascx页面



<2>ContentResult  返回文本 

在Test控制器下添加一个Action方法

public ContentResult Text()
{
    return Content("这是一段文本"); //往前台输出一个字符串
	
	//它相当于以下两句代码:
	//Response.write("这是一段文本");
	//Response.End(); //End 方法使 Web 服务器停止处理脚本并返回当前结果。文件中剩余的内容将不被处理。如果 Response.Buffer 已设置为 TRUE,则调用 Response.End 将缓冲输出
}

这个连视图都不用添加

直接在浏览器中运行 http://localhost:8439/Test/Text   结果是在网页上输出“这是一段文本”这么一行字


<3.1>JsonResult  返回Json

有时我们在调用Ajax时还会要求返回对象为Json序列化的结果,如:

public JsonResult ShowJson()
{

    var userinfo = new { Name = "奥巴马", Age = 56 };
    return Json(userinfo, JsonRequestBehavior.AllowGet);

    //var tempObj = new { Controller = "DemoController", Action = "JsonResultDemo" };
    //return Json(tempObj,JsonRequestBehavior.AllowGet);  

    //JsonRequestBehavior.AllowGet表示:允许来自客户端的 HTTP GET 请求
    //return Json(User, JsonRequestBehavior.AllowGet); 
}

在浏览器中运行 http://localhost:8439/Test/ShowJson  然后就弹出一个窗体让你保存ShowJson.json文件。


保存图片后,用记事本打开文件,文件的内容是 :{"Name":"奥巴马","Age":56}

源代码:

//在Controller控制器中有一个Json方法,这个Json方法
protected internal JsonResult Json(object data)
{
	return this.Json(data, null, null, JsonRequestBehavior.DenyGet);
}
//在JsonResult类中执行了ExecuteResult方法
public override void ExecuteResult(ControllerContext context)
{
	//.....省略代码
	HttpResponseBase response = context.HttpContext.Response;
	if (!string.IsNullOrEmpty(this.ContentType))
	{
		response.ContentType = this.ContentType;
	}
	else
	{
		response.ContentType = "application/json"; //设定响应类型为json
	}
	if (this.ContentEncoding != null)
	{
		response.ContentEncoding = this.ContentEncoding;
	}
	if (this.Data != null)
	{
		JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();//创建了一个序列化对象
		if (this.MaxJsonLength.HasValue)
		{
			javaScriptSerializer.MaxJsonLength = this.MaxJsonLength.Value;
		}
		if (this.RecursionLimit.HasValue)
		{
			javaScriptSerializer.RecursionLimit = this.RecursionLimit.Value;
		}
		response.Write(javaScriptSerializer.Serialize(this.Data)); //将Data序列化成json字符串后写入到响应报文中
	}
}

<3.2>返回Json

/// <summary>
/// 返回一个JSON数据
/// </summary>
/// <param name="pageIndex">当前页码</param>
/// <returns>JSON数据</returns>
public JsonResult Paging(int pageIndex)
{
    //从数据库查询数据
    var query = ((from a in db.T_User
                  where a.Id > pageIndex * 5
                  select a).Take(5)).ToList();

    JsonResult json = new JsonResult();
    json.JsonRequestBehavior = JsonRequestBehavior.AllowGet;  //允许来自客户端的HTTP GET请求
    json.Data = new
    {
        result = query, //将从数据库中查询出来的数据赋值给jsond对象。
    };
    return json;
}

 

<4>JavaScriptResult  输出JS文件

大多时候js文件都是静态的,但有时js文件可能也要动态生成这时我们可以这样输出:

public JavaScriptResult Js()
{
    return JavaScript("var x=0;");
}
在浏览器中运行:http://localhost:8439/Test/Js  弹出一个窗体:如下

保存后,用记事本打开Js.js文件 内容是: var x=0;

源代码:

//在Controller控制器中有一个JavaScript方法,这个Json方法
protected internal virtual JavaScriptResult JavaScript(string script)
{
	return new JavaScriptResult
	{
		Script = script
	};
}
//在JavaScriptResult类中执行了ExecuteResult方法
public override void ExecuteResult(ControllerContext context)
{
    //....省略代码
	HttpResponseBase response = context.HttpContext.Response;
	response.ContentType = "application/x-javascript"; //设定响应类型为javascript
	if (this.Script != null)
	{
		response.Write(this.Script);//将内容写入响应报文中
			
		/*
		注:这个this.Script其实就是我们在控制器JavaScript方法中写的参数
		public JavaScriptResult Index()
        {
            return JavaScript("int a=1; alert(a)"); //就是这个"int a=1; alert(a)"
        }
		*/
	}
}


<5>RedirectResult 页面跳转

1.跳转到Action

public RedirectResult rdaction()
{
    return RedirectToAction("Text", "Test");//跳转到Test控制下的Text方法
}
在浏览器中运行:http://localhost:8439/Test/rdaction  于是立刻就跳转到 http://localhost:8439/Test/Text页面了,于是输出

2.跳转到URL

public RedirectResult rdurl()
{
    return Redirect("http://www.baidu.com");
}
在浏览器中运行:http://localhost:8439/Test/rdurl  于是立刻就跳转到百度的首页了。

3.跳转到Routing规则

public RedirectResult rdrouting() //跳转到Routing规则
{
    return RedirectToRoute("Default",//Route名
      new
      {
          Controller = "Test",
          Action = "Ascx"
      });
}
在浏览器中运行:http://localhost:8439/Test/rdrouting  于是立刻就跳转到 Test控制器下的Ascx方法了,即跳转到http://localhost:8439/Test/Ascx 页面了
于是就输出 http://localhost:8439/Test/Ascx页面的内容


<6>FileResult  输出文件

注:表示一个用于将二进制文件内容发送到响应的基类

其实FileStreamResult继承了FileResult 而FileResult又继承了ActionResult  其实FileResult与FileStreamResult是一个东西

public FileResult fn()
{
    return File("d:/123.jpg","jpg/png/JPEG");               
}
在浏览器中运行:http://localhost:8439/Test/fn    弹出一个对话框:如下

点击保存后,选择用图片查看器打开。显示出了 D盘下的123.jpg图片





<7>FileStreamResult  输出文件流

注:使用 System.IO.Stream 实例将二进制内容发送到响应

FileStreamResult继承了FileResult 而FileResult又继承了ActionResult。  其实FileResult与FileStreamResult是一个东西

public FileStreamResult FileStreamResultDemo()//将d盘下的haha.jpg文件转化成一个文件流,返回到前台
{
    FileStream fs = new FileStream("d:/haha.jpg", FileMode.Open, FileAccess.Read);
    return File(fs, @"jpg/image/gif");//记得这个File()方法有6个重载哦。到时候可以使用以下哦。
} 
运行浏览器:http://localhost:8439/Test/FileStreamResultDemo  弹出一个对话框

选择保存。保存后,选择用图片查看器打开,就显示了一幅D盘下的 haha.jpg文件

源码:

//在Controller中有个File方法,它有一个重载的返回值是FileStreamResult类型,而这个FileStreamResult是继承自FileResult
protected internal FileStreamResult File(Stream fileStream, string contentType)
{
	return this.File(fileStream, contentType, null);
}
//在这个FileResult类中执行了ExecuteResult方法
public override void ExecuteResult(ControllerContext context)
{
	if (context == null)
	{
		throw new ArgumentNullException("context");
	}
	HttpResponseBase response = context.HttpContext.Response;
	response.ContentType = this.ContentType;
	if (!string.IsNullOrEmpty(this.FileDownloadName))
	{
		string headerValue = FileResult.ContentDispositionUtil.GetHeaderValue(this.FileDownloadName);
		context.HttpContext.Response.AddHeader("Content-Disposition", headerValue);
	}
	this.WriteFile(response); //在这里调用(执行)了子类的WriteFile方法
}
//这个是子类FileStreamResult中的WriteFile方法,它重新了父类FIleResult的WriteFile抽象方法
protected override void WriteFile(HttpResponseBase response) 
{
	Stream outputStream = response.OutputStream;
	using (this.FileStream)
	{
		byte[] buffer = new byte[4096];
		while (true)
		{
			int num = this.FileStream.Read(buffer, 0, 4096);
			if (num == 0)
			{
				break;
			}
			outputStream.Write(buffer, 0, num);//输出一个流
		}
	}
}

<8>返回一个空的页面

public EmptyResult EmptyResultDemo()
{
    //仅仅用来占位,没有任何的逻辑。与return null是一样的
    return new EmptyResult(); //空方法  
} 
在浏览器中运行 : http://localhost:8439/Test/EmptyResultDemo   得到的是一个空空如也的空白页


<9> 返回一个响应状态码

//HttpStatusCodeResult()这要是用来防盗链的。 例如:当博客园里有个哥们在博客园里发布了一个帖子,帖子里放了一个<img src="http://www.jd.con/img/1.jpg">的图片。 当用户访问博客园,浏览这个帖子的时候,浏览器解析到有这么个<img src="http://www.jd.con/img/1.jpg">的图片,于是就向京东的这个网站请求这幅图片。此时京东的服务器就做了一个判断,判断你这个请求的上一次请求URL地址是谁? 于是发现这个请求的上一个地址是http://wwww.cnblogs.com/abc.html。这个地址是博客园的地址,所以此时京东的服务就返回一个404的状态码。表示这幅图片不存在(其实是京东不想给你看,如果上一次的请求是从京东本网过来的话,图片就给你看了。)
public ActionResult HttpStatusCodeResultDemo()
{
    //动态修改响应状态码。给请求返回一个404的响应

    //404:资源找不到 500:服务器错误 304:缓存  302:重定向
    return new HttpStatusCodeResult(404);
} 
当控制器返回404的状态码的时候,执行这个视图的时候,浏览器的反应是



<think>首先,用户的问题是关于ASP.NET MVC中控制器的使用和功能。用户明确说:“我想了解或学习ASP.NET MVC中控制器的使用和功能 请问ASP.NET MVC 控制器的作用和使用方法”。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 参考站内引用: - 引用[1]:关于ASP.NET MVC的约定优于配置思想,控制器的位置、命名规则。 - 引用[2]:关于过滤器的使用,但用户的问题是关于控制器的,所以可能不直接相关。我应该专注于控制器的部分。 用户的问题集中在控制器的使用和功能上,所以我需要构建一个清晰的回答结构。 回答结构: 1. **介绍控制器的作用**:解释什么是控制器,它在MVC模式中的作用。 2. **控制器的使用方法**:包括如何创建控制器、基本结构、常用功能。 3. **示例代码**:提供简单的代码示例来演示控制器的使用。 4. **相关约定**:基于引用[1],讨论控制器的命名、位置等约定。 5. **生成相关问题**:在回答结束时,生成几个相关问题。 确保使用中文回答。 步骤: - **介绍控制器的作用**: - 控制器是MVC模式中的核心组件,负责处理用户请求、协调模型和视图。 - 它接收输入(如HTTP请求),调用模型处理业务逻辑,然后选择视图显示结果。 - **控制器的使用方法**: - **创建控制器**:在Controllers目录下创建类,类名以"Controller"结尾。 - **基本结构**:控制器类包含Action方法,每个方法对应一个用户操作。 - **常用功能**:如返回视图、重定向、处理表单数据等。 - **示例代码**:提供一个简单的控制器示例。 - **相关约定**:强调命名规则和位置约定。 - **生成相关问题**:在最后,添加相关问题部分。 对于引用: - 在回答中自然地添加引用标识。例如,当提到约定时,引用[^1]。 数学表达式:用户的问题是关于编程的,可能没有数学表达式,但如果需要,确保正确使用LaTeX。例如,如果有变量,用$...$包裹。 相关问题生成: - 系统指令要求生成相关问题。 - 基于用户问题,生成2-3个相关问题,如控制器的其他功能、常见问题、优化等。 最终回答结构: 1. 控制器的作用 2. 控制器的使用方法 3. 代码示例 4. 控制器的约定 5. 相关问题</think>### ASP.NET MVC 控制器的作用和使用方法 在 ASP.NET MVC 框架中,控制器(Controller)是 MVC 设计模式的核心组件之一,负责处理用户请求、协调模型(Model)和视图(View)。它充当应用程序的“交通警察”,接收输入(如 HTTP 请求),执行业务逻辑,并决定如何响应(例如返回视图或数据)。下面我将逐步解释控制器的作用和使用方法,确保内容清晰可靠。 #### 1. **控制器的作用** - **请求处理**:控制器接收来自浏览器的 HTTP 请求(如 URL 路由),解析用户操作(例如点击按钮或提交表单),并调用相应的 Action 方法来处理请求。 - **业务逻辑协调**:它调用模型(Model)来获取或处理数据(如数据库查询),但不直接包含业务逻辑细节,而是委托给模型层。 - **视图选择**:控制器根据处理结果决定返回哪个视图(View),或重定向到其他页面。例如,处理登录请求后,可能返回主页视图或错误页面。 - **状态管理**:控制器可以维护会话状态(如用户认证信息),通过 `Session` 或 `TempData` 对象实现请求间的数据传递。 - 整体上,控制器确保应用程序的松耦合,分离用户界面与业务逻辑,提高可维护性和可测试性[^1]。 #### 2. **控制器的使用方法** 控制器的使用遵循 ASP.NET MVC 的约定,简化开发流程。以下是关键步骤和功能: - **创建控制器**: - 在项目的 `Controllers` 目录下创建新的 C# 类。 - 类名必须以 `Controller` 结尾,例如 `HomeController` 或 `ProductController`。 - 继承自 `System.Web.Mvc.Controller` 基类,以获取内置功能(如视图返回方法)。 - 示例创建步骤: 1. 在 Visual Studio 中,右键点击 `Controllers` 文件夹。 2. 选择“添加” > “控制器”,使用模板生成基本代码。 - **定义 Action 方法**: - Action 方法是控制器中的公共方法,每个方法对应一个用户操作(如显示页面或提交表单)。 - 方法名通常描述操作,例如 `Index()` 用于默认页面,`Create()` 用于创建新记录。 - Action 方法可以返回多种结果: - `View()`:返回关联的视图(Razor 页面)。 - `RedirectToAction()`:重定向到另一个 Action。 - `Json()`:返回 JSON 数据(用于 API)。 - 参数处理:通过模型绑定,自动将表单数据或 URL 参数映射到方法参数。 - 示例方法定义: ```csharp public class HomeController : Controller { // 默认 Action,返回主页视图 public ActionResult Index() { return View(); // 自动查找 Views/Home/Index.cshtml } // 处理表单提交,参数绑定 [HttpPost] // 指定 HTTP POST 请求 public ActionResult Create(string productName, int quantity) { // 调用模型处理业务逻辑 if (ModelState.IsValid) // 验证输入 { // 保存数据等操作 return RedirectToAction("Index"); // 重定向到主页 } return View("Error"); // 返回错误视图 } } ``` - **使用约定**: - 控制器类必须位于 `Controllers` 目录下,且名称以 `Controller` 结尾[^1]。 - 视图关联:Action 方法返回的视图文件必须位于 `Views/{ControllerName}/{ActionName}.cshtml`。例如,`HomeController.Index()` 会自动查找 `Views/Home/Index.cshtml`。 - 路由映射:默认路由配置(在 `RouteConfig.cs` 中)将 URL 映射到控制器和 Action,例如 URL `/Home/Index` 调用 `HomeController.Index()`。 - **常见功能扩展**: - **过滤器(Filters)**:通过特性(如 `[Authorize]`)添加额外逻辑,例如权限验证或日志记录。过滤器在 Action 执行前后运行,增强控制器的灵活性[^2]。 - **依赖注入**:在构造函数中注入服务(如数据库上下文),提高可测试性。 - **异步处理**:使用 `async` 和 `await` 处理耗时操作,避免阻塞请求。 #### 3. **代码示例:简单控制器实现** 以下是一个完整的控制器示例,演示用户管理功能: ```csharp using System.Web.Mvc; public class UserController : Controller { // Action 1: 显示用户列表 public ActionResult List() { // 模拟获取数据(实际中调用模型) var users = new List<string> { "Alice", "Bob", "Charlie" }; return View(users); // 传递数据到视图 } // Action 2: 处理用户创建表单 [HttpGet] // 指定 HTTP GET 请求(显示表单) public ActionResult Create() { return View(); // 返回创建视图 } [HttpPost] // 指定 HTTP POST 请求(提交表单) public ActionResult Create(UserModel model) { if (ModelState.IsValid) { // 保存用户数据(调用模型) return RedirectToAction("List"); // 成功重定向 } return View(model); // 验证失败,返回表单 } } ``` - **说明**:此示例中,`UserController` 处理用户列表显示和创建操作。`List` Action 返回视图并传递数据;`Create` Action 使用 `[HttpGet]` 和 `[HttpPost]` 区分请求类型,实现 RESTful 风格。 #### 4. **最佳实践和注意事项** - **保持精简**:控制器应只处理请求协调,避免复杂业务逻辑(委托给模型或服务层)。 - **测试友好**:通过依赖注入和接口抽象,便于单元测试。 - **安全性**:使用 `[ValidateAntiForgeryToken]` 防止 CSRF 攻击,或在敏感操作上添加 `[Authorize]` 过滤器[^2]。 - 遵循约定:违反命名或位置规则(如控制器类名不以 `Controller` 结尾)会导致路由失败[^1]。 通过以上步骤,您可以高效使用 ASP.NET MVC 控制器构建动态 Web 应用。如果您有具体场景(如 API 开发),可以进一步探讨。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值