繁体   English   中英

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

[英]How Asp Mvc choose appropriate ActionResult when action return arbitrary type

有关ActionResult的文档指出,可以从actionmethod返回任何对象,并且框架选择ActionResult的右降序来执行它。

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

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

问题是,一切皆有可能,选择规则的规则是什么。

不仅如此,为什么以下代码不会导致编译错误。

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

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

也许有人更幸运,可以解释幕后发生的事情。

问题是,一切皆有可能,选择规则的规则是什么。

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

不仅如此,为什么以下代码不会导致编译错误。

以下代码将永远不会编译。

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

例外:

无法将类型“ HelloWorldMvcApp.MyClass”隐式转换为“ 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,因此您可以从Controller返回该类型。

它清楚地说

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

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

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

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

链接

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM