[英]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;
}
通过创建一个扩展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.