当动作返回任意类型时,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的转换,但我失败了。
也许有人更幸运,可以解释下面发生了什么。
问题是为什么这一切都是可能的,以及选择一个的规则是什么。
它不是,你可能应该按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();
}
}