从 ASP.NET MVC 操作返回部分视图和 JSON [英] Return Partial View and JSON from ASP.NET MVC Action

查看:20
本文介绍了从 ASP.NET MVC 操作返回部分视图和 JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 KnockoutJS 引入现有应用.我的计划是修改/利用我们已经创建的现有部分视图,并将它们绑定到具有 Knockout 声明性属性的 JS 视图模型.当我对某个操作进行 AJAX 调用时,理想情况下我希望该操作同时返回部分视图的 HTML 和 JSON 对象.然后我可以用 HTML 填充一个 div,将 JSON 转换为 Knockout 对象并将其绑定到 HTML.但我不知道如何从动作中返回两者.

I'm introducing KnockoutJS into an existing app. My plan is to modify/utilize the existing partial views that we've already created and bind them to the JS view models with Knockout's declarative attributes. When I make an AJAX call to an action, ideally I'd like the action to return both the HTML of the partial view and JSON object. Then I can fill a div with the HTML, convert the JSON to a Knockout object and bind it to the HTML. But I can't figure out how to return both from the action.

我需要完整的视图模型,因为我将对其进行更新并最终将其发送回服务器.

I need the full view model because I'll be updating it and eventually sending it back to the server.

我想过让操作返回局部视图(已经绑定到模型),并在局部视图中包含 javascript 以将 .Net 模型转换为 Knockout 对象.但我觉得像这样散布 JS 是混乱和不可维护的.我宁愿让一切都接近原始 ajax 调用.

I thought about having the action return the partial view (already bound to the model), and within the partial view, include javascript to convert the .Net model into a Knockout object. But I feel that scattering the JS around like that is messy and unmaintainable. I'd rather have everything close to the original ajax call.

我想另一种选择是发出两个动作调用.一个用于 JSON,另一个用于局部视图.但必须有更巧妙的方法.

I guess another alternative is to make two action calls. One for the JSON, and another for the partial view. But there has to be a slicker way.

关于如何最好地做到这一点的任何想法?

Any ideas on how best to do this?

推荐答案

我确信有多种方法可以做到这一点.我从控制器手动渲染视图,然后将渲染的视图作为 JSON 响应的一部分传回.

I'm sure there are a variety of ways to do this. I manually render the view from the controller, and then pass the rendered view back as part of my JSON response.

这保留了每个实体的责任.视图仍然使用视图引擎定位,它们可以被重用.除了名称和模型类型之外,控制器对视图知之甚少或一无所知.

This preserves the responsibilities of each entity. Views are still located using the view engine and they can be reused. The controller knows little or nothing about the view beyond its name and model type.

public static class RenderHelper
{
    public static string PartialView( Controller controller, string viewName, object model )
    {
        controller.ViewData.Model = model;

        using( var sw = new StringWriter() )
        {
            var viewResult = ViewEngines.Engines.FindPartialView( controller.ControllerContext, viewName );
            var viewContext = new ViewContext( controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw );

            viewResult.View.Render( viewContext, sw );
            viewResult.ViewEngine.ReleaseView( controller.ControllerContext, viewResult.View );

            return sw.ToString();
        }
    }
}

在您的操作方法中:

object model = null; // whatever you want
var obj = new { 
    someOtherProperty = "hello", 
    view = RenderHelper.PartialView( this, "_PartialName", model ) 
};

return Json( obj );

请注意,我返回的是匿名类型.您可以返回任何您想要的(可序列化的)类型,只要它具有呈现视图的字符串属性即可.

Note that I'm returning an anonymous type. You can return any (serializable) type you want, as long as it has a string property for the rendered view.

测试使用手动渲染的操作需要稍作修改.这是因为渲染视图比在 MVC 管道中渲染的时间要早​​一些.

Testing an action that uses manual rendering requires a slight modification. This is due to rendering the view a bit earlier than it would be rendered in the MVC pipeline.

手动渲染

  1. 输入操作方法
  2. 显式渲染视图 <-- 这将使测试调用操作变得困难
  3. 退出操作方法

自动渲染

  1. 输入操作方法
  2. 创建查看结果
  3. 退出操作方法
  4. 处理视图结果(从而呈现视图)

换句话说,我们的手动渲染过程会启动各种其他操作,从而使测试变得困难(例如与构建管理器交互以编译视图).

In other words, our manual rendering process kicks off a variety of other operations that make it difficult to test (such as interacting with the build manager to compile the view).

假设您希望测试操作方法而不是视图的实际内容,您可以检查代码是否在托管环境中执行.

Assuming you wish to test the action method and not the actual contents of the view, you can check whether or not the code is executing in a hosted environment.

    public static string PartialView( Controller controller, string viewName, object model )
    {
        // returns false from a VS 2013 unit test, true from IIS
        if( !HostingEnvironment.IsHosted )
        {
            // return whatever you want here
            return string.Empty;
        }

        // continue as usual
     }

检查 HostingEnvironment.IsHosted 成本很低(实际上,它只是一个空检查).

Checking HostingEnvironment.IsHosted is inexpensive (under the hood, it is simply a null check).

这篇关于从 ASP.NET MVC 操作返回部分视图和 JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆