在上一章中,我们讲述了ActionResult的三个子类,分别是EmptyResult,RediretResult和ContentResult。那么本章我们在讲几个ActionResult的子类。
JsonResult | 表示可以运用到AJAX程序中JSON结果 |
JavaScriptResult | 表示一个JavaScript对象 |
FileContentResult | 表示一个可以下载的、二进制内容的文件 |
FilePathResult | 表示一个可以下载的、指定路径的文件 |
首先就是JsonResult,从名字看,我们可以猜出,这个结果和Json是相关的,返回的类型是以Json格式的,所以一般这个用于Ajax请求,当然在Ajax请求的时候要设置服务器端返回的类型是json。下面我们通过一个案例来研究这个JsonResult。在这个案例中,我们使用了Jquery。首先我们新建一个项目“Com.ArHat.Web”。并添加一个HomeController控制器,同时在Models文件夹中添加一个类M_User.cs。代码如下:
M_User:
HomeController:
public ActionResult Index() { return View(); } public ActionResult AjaxUserInfo() { Models.M_User user = new Models.M_User()
{
Name="济公活佛",Age=90
}; return Json(user,JsonRequestBehavior.AllowGet); }
同时我们添加Index的视图文件Index.cshtml,内容如下:
@{ ViewBag.Title = "JsonResult"; } <script type="text/javascript"> function AjaxSearch()
{ $.get("/Home/AjaxUserInfo", null, function (data) { var html = "姓名:" + data.Name + ",年龄:" + data.Age; $("#result").html(html); }, "json"); } </script> <h2>这是JsonResult实例</h2> 请输入用户的名字:<input type="button" value="查询" οnclick="AjaxSearch()" /> <div id="result" style="margin:10px"> </div>
我们在浏览器中预览一下,当点击查询按钮的时候,发现数据已经显示到div中了。我们来分一下上面的代码。
首先我们再视图文件中使用了$.get来发送一个异步的get请求,请求的Action是HomeController下的AjaxUserInfo。这一点没什么难度。主要在AjaxUserInfo这函数中,我们创建了一个对象M_User,最关键的一点事Controller提供的Json函数。这个函数返回的类型就是JsonResult。下面我们来看一下Json函数的定义:
protected internal JsonResult Json(object data); protected internal JsonResult Json(object data, JsonRequestBehavior behavior); protected internal JsonResult Json(object data, string contentType);
这个函数中,都必须提供参数”object data”。这个就是要把对象转换为json数据。比如M_User对象,有属性Name,Age.那么JsonResult就会把这个对象转为Json对象{Name:”xxx”,Age:YY}。
其中的第二个重载函数,提供了另外一个参数JsonRequestBehavior这个参数是说明请求Json的方式,默认情况下,如果是get请求,则是不允许的,如果要使异步的get请求起作用,则必须设置JsonRequestBehavior.AllowGet。可以猜测出,JsonRequestBehavior是个枚举类型了,还有一个枚举值是DenyGet(阻止Get,这个是默认值)。
所以我们在AjaxUserInfo中,使用了的第二个重载。那么我们来分析一下最后的结果。我们使用firefox浏览器,通过firebug来看看结果。
从上面的结果,我们可以看出和我们猜测的是一样的,JsonResult把对象自动转换为了json数据了。
下面我们来看看JavaScriptResult。现在我挺佩服微软的命名规则的,特别见名之意啊。从名字上看,返回的就是一个JavaScript对象。别看返回的事JavaScript对象,但是这个对象确是“纯文本”的哦!
现在我们改写一下Index函数,内容如下:
发了什么问题呢?原来alert函数并没有执行,而是当做纯文本来输出了,这是怎么回事呢?原因是JavascriptResult要和Ajax一起使用,而这个Ajax和我们传统的Ajax有些不同,需要使用在Razor页面中使用@Ajax生成的链接或者是表单来调用,从一定程度上可以看成是“回发”,但这种回发是纯粹的Ajax。而且页面中调用的Ajax函数必须在本Controller中定义才可以。下面我们改写一下HomeController:
public class HomeController : Controller { public ActionResult Index()
{ return View(); } public ActionResult AjaxUserInfo() { Models.M_User user = new Models.M_User() { Name="济公活佛",Age=90}; return Json(user,JsonRequestBehavior.AllowGet); } public ActionResult JSResult() { string js = "alert('sss')"; return JavaScript(js); } }
同时我们需要改写_Layout.cshtml,在_Layout.cshtml中加上
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
只有加上了这个js,@Ajax才会起作用。下面我们改写一下Index.cshtml
@{ ViewBag.Title = "JsonResult"; } <script type="text/javascript"> function AjaxSearch()
{ $.get("/Home/AjaxUserInfo", null, function (data)
{ var html = "姓名:" + data.Name + ",年龄:" + data.Age; $("#result").html(html+","); }, "json"); } </script> <h2>这是JsonResult实例</h2> 请输入用户的名字:<input type="button" value="查询" οnclick="AjaxSearch()" /> <div id="result" style="margin:10px"> </div> <br /> <a href="/Home/JSResult">这是JavaScriptResult——普通调用</a> <br /> @Ajax.ActionLink("这是JavaScriptResult——Ajax调用", "JSResult", new AjaxOptions())
在Index.cshtml中,我们加入了两个超链接,一个是普通的,一个是@Ajax生成的超链接。我们在浏览器中预览一下,分别点击这两个超链会发现,第一个是以另外一个页面显示内容,第二个是在本页面直接执行了javascript代码。同时我们查看一下源代码:
发现通过@Ajax生成的标签中多了几个data-*的属性,而且功能正常执行,我们会感觉比较奇怪,因为这是一种JavaScript的编写风格(和html5相关),这种风格称之为”Unobtrusive Javascript”。其实这种应用在Jquery EasyUI中经常用的到。需要注意的是,如果要使用@Ajax,那么在页面中必须导入
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
而且在页面中所调用的方法必须是在页面所对应的Controller中。
@Ajax.ActionLink("这是JavaScriptResult——Ajax调用", "JSResult", new AjaxOptions())。
大家会发现,上面的代码是在HomeController的Index方法所对应的视图中,那么“JSResult”这个方法必须在HomeController中。如果,我们现在再创建一个Controller为TestController,内容如下:
同时我们改一下Home/Index方法对应的视图文件Index.cshtml
@Ajax.ActionLink("这是JavaScriptResult——Ajax调用", "/Test/Index", new AjaxOptions())
我们预览一下,发现请求失败哦。为什么呢?我们观察一下生成的源代码:
发现地址这么会是/Home/Test/Index呢?这一点就说明了这种Ajax方法必须是在视图对应的Controller中声明。所以这也就是我为什么称它为另一种的“回发”。只不过这种“回发”是Ajax形式的。比如,我们post提交一个记录后,需要返回一个说明,但是这个说明是cs生成的,那么就可以利用这种方法。
下面,我们来分析一下@Ajax辅助方法ActionLink(text,action, AjaxOptions)。
如果说,我们必须要调用TestController中的Index方法,怎么办呢?我们可以使用@Ajax.ActionLink的第二个重载函数:ActionLink(text,action, new object,AjaxOptions)。
就按上面的说法,我们要调用TestController中的Index方法,则我们可以这样写:
@Ajax.ActionLink("这是JavaScriptResult——Ajax调用", "Index",new {controller="Test"}, new AjaxOptions())
这个方法提提供了几个参数,第一个参数text:是要显示的文本,action是要调用的Ajax方法,第三个参数是action执行后把执行后的内容填入到AjaxOptions中。至于AjaxOptions的作用,我们会在后面讲解Ajax的时候专门进行讲解。
那么本章就到这里吧,下一章我们打算写其他的ActionResult的,但是由于这一章中出现了@Ajax的用法,那么我在下一章中老魏讲解一下@Ajax辅助方法吧!