.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文件,通过页面渲染,最终达到呈现视图的效果

猜你喜欢

转载自www.cnblogs.com/HTLucky/p/12742907.html