从Action方法返回原始对象,并在渲染之前将它们转换为JsonResult

时间:2013-04-22 09:28:36

标签: ajax asp.net-mvc json asp.net-mvc-4 asp.net-ajax

我正在处理的网站严重依赖于ajax / json和knockout.js。 我想让很多我的控制器返回视图定制的'json对象',而不是在返回方法时将它们包装在JsonResult中。

这意味着我可以轻松地将多个调用合并到一个父对象中,但仍然可以单独调用Actions。

简化示例:

public object Main(int groupId)
{
    var viewModel = new
    {
        Persons    = Employees(groupId),
        Messages   = AllMessages()
    };

    return viewModel;
}

public object Employees(int groupId)
{
    return DatabaseContext.Employees.Where(e => e.GroupId == groupId).ToList();
}

public object AllMessages()
{
    return DatabaseContext.Messages.ToList();
}

我希望我可以在OnActionExecuted中捕获返回的对象,然后将整个结果包装在最终的JsonResult中。

结果已经转换为字符串并在ContentResult中捕获。

有什么想法吗? :)谢谢,

2 个答案:

答案 0 :(得分:1)

这方面的一个好方法是为实体调用创建辅助方法。或者如果你已经将这些方法放在某处,它们实际上可以作为辅助方法。通过这种方式,您可以返回强类型MessagesEmployees的列表,并返回您想要的父对象。然后,您可以使用返回json对象的各个控制器方法。此外,您可以扩展父视图模型以返回其他字段。

父ViewModel

public class ParentModel {
    public Employee Persons {get;set;}
    public Message Messages {get;set;}
}

助手方法

使用类似于此处定义的辅助方法的好处在于,您可以为查询应用更多逻辑,以及更多,并且您不必更改控制器方法中的任何内容。

public ParentModel GetMain(int groupId)
{
    var viewModel = new ParentModel 
    {
        Persons    = Employees(groupId),
        Messages   = AllMessages()
    };

    return viewModel;
}

public IEnumerable<Employee> Employees(int groupId)
{
    return DatabaseContext.Employees.Where(e => e.GroupId == groupId).ToList();
}

public IEnumerable<Message> AllMessages()
{
    return DatabaseContext.Messages.ToList();
}

控制器方法

public ActionResult GetParent(int groupId){
    return Json(helperinstance.GetMain()); 
}
public ActionResult GetEmployees(int groupId){
    return Json(helperinstance.Employees()); 
}
public ActionResult GetMessages(int groupId){
    return Json(helperinstance.AllMessages()); 
}

答案 1 :(得分:0)

感谢您的回答。我不打算解决von v。因为我喜欢尽量减少样板。

最后我尝试了以下方法。它现在似乎工作得很好,但我仍然需要在实际生产中测试它。

如果有人对此有一些(安全)问题,我很高兴在评论中听到它们。

// BaseController
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var returnType = ((ReflectedActionDescriptor)filterContext.ActionDescriptor).MethodInfo.ReturnType;

    // is the returnType not deriving from ActionResult? Automatically wrap it in a JsonResult
    if ( !typeof(ActionResult).IsAssignableFrom(returnType) )
    {
        var result = filterContext.ActionDescriptor.Execute(filterContext, filterContext.ActionParameters);

        filterContext.Result = Json( result );
    }
}