首页 新闻 会员 周边

mvc里面 返回 ActionResult 与 返回 JsonResult 的一点问题

1
[待解决问题]

这样返回Json到页面后,为什么不需要序列化为json对象,可以直接使用

data.属性  之类的就可以使用了

 

而像这种 返回json到页面 需要序列化为对象,然后使用?

~雨落忧伤~的主页 ~雨落忧伤~ | 菜鸟二级 | 园豆:336
提问于:2018-01-24 20:21
< >
分享
所有回答(4)
0

都可以直接使用,不需要序列化为对象,Json() 会自动进行序列化

dudu | 园豆:30994 (高人七级) | 2018-01-24 20:56

嗯嗯,为什么有的时候在页面上需要序列化呢? 

比如

var ajaxResult = eval("(" + data + ")");

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-24 20:59

@~雨落忧伤~: 那是其他问题引起的,不是 ActionResult 与 JsonResult 的问题

支持(0) 反对(0) dudu | 园豆:30994 (高人七级) | 2018-01-24 21:03

@~雨落忧伤~: 建议在出问题时看一下响应头中content-type是否正确

content-type:application/json; charset=utf-8
支持(0) 反对(0) dudu | 园豆:30994 (高人七级) | 2018-01-24 21:07

@dudu: content-type:application/json; 这就代表是json对象吗? 还是json字符串

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-24 21:08
0

你不是传了对象给JsonResult吗 —— 说明它做了这个过程三。

常见的各种Result都是 ActionResult 派生的,都去各自实现 自己的  成员 及 核心过程: ExecuteResult

比如以下是JsonResult的部分源代码,我们可以看到它在核心 函数 ExecuteResult 做了头部处理,做了Http Body 内容处理——

 1 public override void ExecuteResult(ControllerContext context)
 2     {
 3       if (context == null)
 4         throw new ArgumentNullException("context");
 5       if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
 6         throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed);
 7       HttpResponseBase response = context.HttpContext.Response;
 8       response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;
 9       if (this.ContentEncoding != null)
10         response.ContentEncoding = this.ContentEncoding;
11       if (this.Data == null)
12         return;
13       JavaScriptSerializer scriptSerializer = new JavaScriptSerializer();
14       if (this.MaxJsonLength.HasValue)
15         scriptSerializer.MaxJsonLength = this.MaxJsonLength.Value;
16       if (this.RecursionLimit.HasValue)
17         scriptSerializer.RecursionLimit = this.RecursionLimit.Value;
18       response.Write(scriptSerializer.Serialize(this.Data));
19     }

 

所以以此类推,如果你想做其他result,只需要根据result最终的样子  —— 核心通过派生ActionResult,并重写ExecuteResult 即可实现。

花飘水流兮 | 园豆:13560 (专家六级) | 2018-01-24 22:17

response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;

这么说

这个方法 应该还可以返回其他类型的数据吧?

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-26 13:08

@~雨落忧伤~:肯定可以三。

 

eg.

 

 1     public class ImageResult : ActionResult
 2     {
 3         public ImageResult() { }
 4         public Image Image { get; set; }
 5         public ImageFormat ImageFormat { get; set; }
 6         public override void ExecuteResult(ControllerContext context)
 7         {
 8             // verify properties 
 9             if (Image == null)
10             {
11                 throw new ArgumentNullException("Image");
12             }
13             if (ImageFormat == null)
14             {
15                 throw new ArgumentNullException("ImageFormat");
16             }
17             // output 
18             context.HttpContext.Response.Clear();
19             if (ImageFormat.Equals(ImageFormat.Bmp)) context.HttpContext.Response.ContentType = "image/bmp";
20             if (ImageFormat.Equals(ImageFormat.Gif)) context.HttpContext.Response.ContentType = "image/gif";
21             if (ImageFormat.Equals(ImageFormat.Icon)) context.HttpContext.Response.ContentType = "image/vnd.microsoft.icon";
22             if (ImageFormat.Equals(ImageFormat.Jpeg)) context.HttpContext.Response.ContentType = "image/jpeg";
23             if (ImageFormat.Equals(ImageFormat.Png)) context.HttpContext.Response.ContentType = "image/png";
24             if (ImageFormat.Equals(ImageFormat.Tiff)) context.HttpContext.Response.ContentType = "image/tiff";
25             if (ImageFormat.Equals(ImageFormat.Wmf)) context.HttpContext.Response.ContentType = "image/wmf";
26             Image.Save(context.HttpContext.Response.OutputStream, ImageFormat);
27         }
28     }
class ViewResultBase //ViewResult 又是从这个派生的
{
public override void ExecuteResult(ControllerContext context)
    {
      if (context == null)
        throw new ArgumentNullException(nameof (context));
      if (string.IsNullOrEmpty(this.ViewName))
        this.ViewName = context.RouteData.GetRequiredString("action");
      ViewEngineResult viewEngineResult = (ViewEngineResult) null;
      if (this.View == null)
      {
        viewEngineResult = this.FindView(context);
        this.View = viewEngineResult.View;
      }
      TextWriter output = context.HttpContext.Response.Output;
      this.View.Render(new ViewContext(context, this.View, this.ViewData, this.TempData, output), output);
      if (viewEngineResult == null)
        return;
      viewEngineResult.ViewEngine.ReleaseView(context, this.View);
    }
}

好好理解吧。

 

支持(0) 反对(0) 花飘水流兮 | 园豆:13560 (专家六级) | 2018-01-26 13:27

@花飘水流兮: 第一个勉强还看得懂,第二个就看不懂了

里面的

看的有点蒙,里面好多东西没用过

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-26 14:10

@~雨落忧伤~: 最重要的是你理解的截图,你就大大滴进步了。我也很多没用过,你心头好过些了吧。实际有的东西你用了只是你没觉得而已,比如ViewReuslt,你Return View()的时候就用了,上下文多多注意,多思考(假如是我,要怎么写才能这样提供接口),有条件和时间也可以看看人家源码是不是这么实现的。

支持(0) 反对(0) 花飘水流兮 | 园豆:13560 (专家六级) | 2018-01-26 14:42

@花飘水流兮: 嗯嗯,醍醐灌顶,说的很对,

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-26 19:03

@花飘水流兮: 大哥,请受小弟一拜, 你的方法我看了好久 还是不太明白 ViewResult 与 ViewEngineResult  这两者的区别...

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-26 19:06

@~雨落忧伤~: 你看命名空间就知道——那个是MVC本身的源码。这个你不用管太多,就是执行Razor解析的东西,执行为最终的html 文档的东西。你自己都可以加aspx或者Razor渲染器就可以完成到CustomerViewResult,然后可以不用系统自己的ViewResult。【当然这是多余的工作】

只有ImageResult和LJsonResult是个人补充的,前者因为没得,后者因为需要说明如何序列化。

支持(0) 反对(0) 花飘水流兮 | 园豆:13560 (专家六级) | 2018-01-26 19:34

@~雨落忧伤~: 站在通讯上来讲,本身http是个很简单的协议,通讯方式也很简单。你如果自己从tcp写一个mvc就很清楚了,没事的时候你可以试试。

支持(0) 反对(0) 花飘水流兮 | 园豆:13560 (专家六级) | 2018-01-26 19:36

@花飘水流兮: 从tcp写一个mvc  tcp协议吗  mvc也可以不走http协议吗?

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-29 15:32

@~雨落忧伤~:

tcp=>http server=>request 通过文件规则map 各种 XxHandler

将会有一种叫做MvcHandler(还有普通的FileHandler,比如静态的css,js,html等等),该Handler又将实现Request 和 Response的各种类的封装,

其中Response过程 你又将封装各种ActionResult,其中有一种是 ViewResult,ViewResult又有各种Render引擎,比如Razor、aspx甚至jsp等等。

每个环节你都将会发现很多很多问题,比如http协议中get 判断是否修改,内容大小,连接时间...这些都足以搞死服务器,你会明白为什么file 是stream的请求,你会明白 原来 razor就是这么“简单”,自定义razor也是这么简单,然后你会发现razor原来还可以干点其他什么事...你也会发现http传输协议本身很简单,但结构意义却挺复杂,很多很多为什么...

 

空了慢慢玩吧。

支持(0) 反对(0) 花飘水流兮 | 园豆:13560 (专家六级) | 2018-01-29 15:58

@花飘水流兮:  但不知道怎么使用,代码怎么写?

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-29 20:21

@花飘水流兮: 也不理解原理~~

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-29 20:21
0

主要是$.ajax() 中的dataType参数决定(预期服务器返回的数据类型)。

其次是服务器端响应头的:

Content-Type: application/json; charset=utf-8
 
也就是说,如果$.ajax()中不定义dataType参数,那么它会根据服务器端给出的内容来解析。
如果定义了dataType,那么就会按照定义的类型解析。
 
例:
// 服务器响应头为:Content-Type:application/json; charset=utf-8
// 服务器返回的内容为:{"Success":true,"Message":null}

$.ajax({
    url: "/xxx/yyy",
    data: datas,
    type: "POST",
    success: function (data) {
        //这里的data为对象。
        console.log(data);
    },
});  

$.ajax({
    url: "/xxx/yyy",
    data: datas,
    type: "POST",
    dataType: "text",
    success: function (data) {
        //这里的data为字符串。
        console.log(data);
    },
});

$.ajax({
    url: "/xxx/yyy",
    data: datas,
    type: "POST",
    dataType: "json",
    success: function (data) {
        //这里的data为对象。
        console.log(data);
    },
});

 

参照:http://www.w3school.com.cn/jquery/ajax_ajax.asp

junio.cn | 园豆:445 (菜鸟二级) | 2018-01-25 10:32

也就是说 如果服务器本身返回是json字符串 

也可以通过dataType: "json"  设置为json  修改成 对象 

这样就不用再这样

var ajaxResult = eval("(" + data + ")");

序列化为对象了

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-25 10:52

@~雨落忧伤~: 是的,主要以$.ajax的dataType参数为准,前提是要能保证服务器端返回的数据格式是预期的

例:

服务器端

[HttpPost]
public ActionResult Test()
{
    return Content("{\"Test\":\"A\", \"C\":100}", "html/text");
}

客户端

$.ajax({
    url: "@Url.Action("Test")",
    type: "POST",
    dataType: "json",
    success: function (data) {
        //这里的data为对象
        console.log(data);
    },
});

 

注:因为这里已经知道服务器返回的文本是json格式,所以客户端可以直接当作json来解析。

支持(0) 反对(0) junio.cn | 园豆:445 (菜鸟二级) | 2018-01-25 11:18

@listen.core:服务器端返回的数据格式是预期的。

预期的 指的是,返回的数据要 是能被 dataType 转换的字符串吗?

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-25 16:11

@~雨落忧伤~: 预期的是指返回的数据格式正式客户端处理的那种,否则就没法正确识别啦。(●ˇ∀ˇ●)

支持(0) 反对(0) junio.cn | 园豆:445 (菜鸟二级) | 2018-01-26 09:59

@listen.core: 嗯嗯 返回格式 正是 浏览器处理的那种

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-29 15:29
0

  兄台,学习下什么是 Content-Type。如果返回json格式的数据,js就能以对象的方式访问。否则只是一个字符串。

Eysa | 园豆:62 (初学一级) | 2018-01-25 18:03

F12 后 提交的ajax 里面有个Response Headers  和 Request Headers  

两个里面都有  Content-Type  Content-Length 还有一些其他相同的, 一些不同的

问下,这两个里面的有什么区别吗?

支持(0) 反对(0) ~雨落忧伤~ | 园豆:336 (菜鸟二级) | 2018-01-25 18:44
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册