• .NET MVC中各种Result的本质原理


    在使用.net mvc时发现在Controller中返回一个View()便能达到页面的渲染,返回一个Json()便能返回json格式的数据,返回一个Content()便能返回一个string格式的数据。那我们又没有想过mvc框架是怎么实现的呢,今天我们就带着疑惑,去探寻mvc框架中result的奥妙

    一.Content()

    protected internal virtual ContentResult Content(string content, string contentType, Encoding contentEncoding)
    {
        ContentResult contentResult = new ContentResult();
        contentResult.Content = content;
        contentResult.ContentType = contentType;
        contentResult.ContentEncoding = contentEncoding;
        return contentResult;      //在这里返回了一个ContentResult对象
    }
    public class ContentResult : ActionResult
    {
    
        public string Content
        {
            get;
            set;
        }
    
        public Encoding ContentEncoding
        {
            get;
            set;
        }
        public string ContentType
        {
            get;
            set;
        }
    
        public override void ExecuteResult(ControllerContext context)    //重写父类的方法,本质都是返回一个ActionResult
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            HttpResponseBase response = context.HttpContext.Response;   //重点在这里,返回了一个HttpResponseBase 
            if (!string.IsNullOrEmpty(ContentType))  //若是ContentType不为空了就赋值,为空了就是默认返回string
            {
                response.ContentType = ContentType;
            }
            if (ContentEncoding != null)
            {
                response.ContentEncoding = ContentEncoding;
            }
            if (Content != null)
            {
                response.Write(Content);      //写入输出流,完成http请求的返回
            }
        }
    }

    通过源码分析,得到所有的Content()方法本质都是返回 Content(string content, string contentType, Encoding contentEncoding)这个重载的版本。在这个方法里面返回一个ContentResult对象,通过对ContentResult的源码解析,重写父类的ExecuteResult的方法,用Response.Write(Content)写入输出流,完成http请求的返回

    二.JavaScript()

    protected internal virtual JavaScriptResult JavaScript(string script)
    {
        JavaScriptResult javaScriptResult = new JavaScriptResult();
        javaScriptResult.Script = script;
        return javaScriptResult;    //返回一个JavaScriptResult 对象
    }
    
    public class JavaScriptResult : ActionResult    //都是继承了ActionResult
    {
        public string Script
        {
            get;
            set;
        }
        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            HttpResponseBase response = context.HttpContext.Response;
            response.ContentType = "application/x-javascript";     //奥秘在这里,通过修改Response.ContentType来控制返回的类型,别的部分大致都相同
            if (Script != null)
            {
                response.Write(Script);
            }
        }
    }

    通过JavaScript()方法可以直接返回一个javascript,这就是我们常见的有的请求没有后缀名,但依然能执行javascript的奥秘。其本质就是将Response.ContentType的值修改为application/x-javascript并通过response.Write()方法输出,完成相应的实现

    三.Json()

    protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        JsonResult jsonResult = new JsonResult();
        jsonResult.Data = data;
        jsonResult.ContentType = contentType;
        jsonResult.ContentEncoding = contentEncoding;
        jsonResult.JsonRequestBehavior = behavior;
        return jsonResult;     //返回一个JsonResult对象
    }
    public class JsonResult : ActionResult
    {
        public Encoding ContentEncoding
        {
            get;
            set;
        }
        public string ContentType
        {
            get;
            set;
        }
        public object Data
        {
            get;
            set;
        }
        public JsonRequestBehavior JsonRequestBehavior
        {
            get;
            set;
        }
        public int? MaxJsonLength
        {
            get;
            set;
        }
        public int? RecursionLimit
        {
            get;
            set;
        }
        public JsonResult()
        {
            JsonRequestBehavior = JsonRequestBehavior.DenyGet;
        }
    
        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) //默认是不支持Get请求,我们可以使用JsonRequestBehavior.AllowGet来允许Get返回
            {
                throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed);
            }
            HttpResponseBase response = context.HttpContext.Response;
            if (!string.IsNullOrEmpty(ContentType))
            {
                response.ContentType = ContentType;
            }
            else
            {
                response.ContentType = "application/json"; //定义返回格式为application/json
            }
            if (ContentEncoding != null)
            {
                response.ContentEncoding = ContentEncoding;
            }
            if (Data != null)
            {
                JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();   //加载JavaScriptSerializer 这个序列化对象,我们也可以用Newtonsoft来进行对象的序列化
                if (MaxJsonLength.HasValue)
                {
                    javaScriptSerializer.MaxJsonLength = MaxJsonLength.Value;
                }
                if (RecursionLimit.HasValue)
                {
                    javaScriptSerializer.RecursionLimit = RecursionLimit.Value;
                }
                response.Write(javaScriptSerializer.Serialize(Data)); //序列化对象并返回
            }
        }
    }

    mvc中的Json()跟Content()类似,都是有多个重载的版本,但本质上都是调用的Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)这个版本,返回一个JsonResult对象,通过对源码的分析,我们发现JsonResult中通过判断,默认Get请求是不会让我们返回的。所以我们要通过JsonRequestBehavior.AllowGet来完成Get请求的返回。最后还是老套路,通过response.Write(javaScriptSerializer.Serialize(Data))序列化对象,并执行返回

     总结

    通过对源码的解析,我们不难发现各种Result的本质区别就是修改ContentType的值来控制返回的数据类型。各种Result都继承了ActionResult,通过重写父类的ExecuteResult的方法,来完成相应的返回操作,当然viewresult()是个例外,它是将cshtml转换为一个cs文件,通过页面渲染,最终达到呈现视图的效果

  • 相关阅读:
    Python实现TCP服务端的并发
    python程序中的线程操作
    jmeter命令行执行脚本_动态参数设置
    App客户端性能测试点总结
    App功能测试点总结
    jmeter中生成UUID作为唯一标识符
    Python Unittest进行接口测试的简单示例
    jmeter接口测试中的用例数据分离
    博客园看板娘的简单添加
    (转)后端服务性能压测实践
  • 原文地址:https://www.cnblogs.com/HTLucky/p/12742907.html
Copyright © 2020-2023  润新知