当动作返回任意类型时,Asp Mvc如何选择合适的ActionResult

本文关键字:选择 何选择 ActionResult Mvc 返回 任意 类型 Asp | 更新日期: 2023-09-27 17:50:29

关于ActionResult的文档告诉我们可以从actionmethod和框架中返回任何对象,并选择ActionResult的右后代来执行它。

https://msdn.microsoft.com/en-us/library/system.web.mvc.actionresult (v = vs.118) . aspx

您可以创建返回任何类型对象的操作方法,例如字符串、整数或布尔值。这些返回类型在呈现给响应流之前被包装在一个适当的ActionResult类型中。

问题是为什么这一切都是可能的,以及选择一个的规则是什么。

多于,为什么下面的代码不会导致编译错误。

public ActionResult MyAction()
{
    return new MyClass(); //not inherited from ActionResult
}

我试图在Asp Mvc源代码中找到答案,希望找到隐式转换操作符声明从对象到ActionResult的转换,但我失败了。

也许有人更幸运,可以解释下面发生了什么。

当动作返回任意类型时,Asp Mvc如何选择合适的ActionResult

问题是为什么这一切都是可能的,以及选择一个的规则是什么。

它不是,你可能应该按F5/F6(编译/重建)。

多于,为什么下面的代码不会导致编译错误。

下面的代码永远不会编译…

public ActionResult MyAction()
{
  return new MyClass(); //not inherited from ActionResult
}
异常:

不能隐式转换类型"HelloWorldMvcApp"。MyClass' to 'System.Web.Mvc.ActionResult'

你需要再读一遍:

可以创建操作方法,使返回任意类型的对象,如字符串、整数或布尔值。这些返回类型在呈现给响应流之前被包装在一个适当的ActionResult类型中。

这并不是说MVC框架会自动为你包装它,它是说你可以返回任何对象在一个包装ActionResult这是什么所有的ActionResult返回类型做。这绝对是糟糕的措辞,MVC并没有做任何神奇的关于允许方法返回一个不匹配它的签名的类型(目前)。

您可以创建自己的操作结果,例如XmlResult。

您可以返回JSON对象而不是ActionResult。

你错过了下一个陈述的要点。在呈现给响应流之前,这些返回类型被包装在适当的ActionResult类型中。

public JsonResult GetProductDataJson()
        {
            IEnumerable<Product> data = GetData();
            return Json(data, JsonRequestBehavior.AllowGet);
        }

JsonResult是ActionResult类型,所以你可以从控制器返回该类型。

很明显

这些返回类型被包装在一个适当的ActionResult类型中在它们被呈现到响应流之前

所以你不能直接返回一个对象到视图中。它应该被包装在View()、Json()或任何其他Helper方法中。

见链接:https://msdn.microsoft.com/en-us/library/dd410269(v=vs.100).aspx

如果你想创建你自己的 ActionResult,创建一个从ActionResult类继承的类。

链接
  • http://www.codeproject.com/Articles/533932/Custom-ASP-NET-MVC-ActionResults
  • http://www.c-sharpcorner.com/UploadFile/dbd951/how-to-create-custom-actionresult-method-in-Asp-Net-mvc4/

正如文档所说,您可以从操作方法返回任何类型。您需要适当地声明该方法,以便编译:

public MyClass MyAction()
{
    return new MyClass();
}

你可以声明你的方法返回object,它仍然是一个有效的动作方法,MVC框架将高兴地调用。

当您返回不能转换为ActionResult的东西时,它将转换为String(如果不是null)并设置为ContentResult上的Content;返回值的String表示形式直接发送给客户端。ControllerActionInvoker类的CreateActionResult方法处理这个:

protected virtual ActionResult CreateActionResult(ControllerContext controllerContext, ActionDescriptor actionDescriptor, object actionReturnValue)
{
    if (actionReturnValue == null)
    {
        return new EmptyResult();
    }
    ActionResult actionResult = (actionReturnValue as ActionResult) ??
                                new ContentResult { Content = Convert.ToString(actionReturnValue, CultureInfo.InvariantCulture) };
    return actionResult;
}

http://aspnetwebstack.codeplex.com/SourceControl/latest src/System.Web.Mvc ControllerActionInvoker.cs

有可能通过创建一个扩展ControllerActionInvoker并实现所需行为的类来覆盖此行为(这是我遇到这个问题时试图找出如何做的)。然后重写控制器中的CreateActionInvoker方法或分配ActionInvoker属性:

public class MyActionInvoker: ControllerActionInvoker
{
    protected override ActionResult CreateActionResult(ControllerContext controllerContext, ActionDescriptor actionDescriptor, object actionReturnValue)
    {
        // Your behaviour
    }
}
public class MyController: Controller
{
    protected override void Initialize(RequestContext requestContext)
    {
        ActionInvoker = new MyActionInvoker();
    }
    protected override IActionInvoker CreateActionInvoker()
    {
        return new MyActionInvoker();
    }
}