当action返回任意类型

时间:2015-05-23 21:16:29

标签: c# asp.net asp.net-mvc

有关ActionResult的文档告诉我们可以从action方法返回任何对象,并选择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但是我失败了。

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

4 个答案:

答案 0 :(得分:2)

  

问题是如何做到这一切以及选择一个的规则。

不是,你应该点击F5 / F6(编译/重建)。

  

以下代码不会导致编译错误。

The following code will never compile.

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

例外:

  

无法将类型'HelloWorldMvcApp.MyClass'隐式转换为'System.Web.Mvc.ActionResult'

您需要再次阅读:

  

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

它没有声明MVC框架会自动为你包装它,它说明你可以在一个包装的ActionResult中返回任何对象,这是所有ActionResult返回类型所做的。这绝对是措辞不好,MVC没有做任何关于允许方法返回与其签名(当前)不匹配的类型的魔法

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

答案 1 :(得分:0)

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

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

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

JsonResult属于ActionResult类型,因此您可以从Controller返回该类型。

答案 2 :(得分:0)

它清楚地说明了

  

这些返回类型包装在适当的ActionResult类型中   在它们呈现给响应流之前。

因此您无法直接将对象返回到视图中。它应该包含在View(),Json()或任何其他Helper方法中。

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

如果要创建您自己的 ActionResult,请创建一个继承自ActionResult类的类。

链接

答案 3 :(得分:0)

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

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

您可以将方法声明为返回object,它仍然是MVC框架乐意调用的有效操作方法。

当您返回无法转换为ActionResult的内容时,会将其转换为String(如果不为空)并在Content上设置为ContentResult;您的返回值的String表示将直接发送给客户端。 CreateActionResult类的ControllerActionInvoker方法处理此问题:

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();
    }
}