2009-04-16 78 views
2

我正在进行AJAX调用(使用jQuery)来检索PartialView。除了HTML之外,我还想返回视图显示的对象的JSON表示。我一直使用的蹩脚方式是将属性作为隐藏输入嵌入到HTML中,这些输入很快变得笨拙并且紧密结合太多东西。用HTML和JavaScript返回部分视图

我可以在HTML之后发送<script>标签中的JavaScript,但我真的很关心把这些东西分开。这将是这样的:

<%@ Control Language="C#" AutoEventWireup="true" Inherits="System.Web.Mvc.ViewUserControl<Person>" %> 
<div class="person"> 
    First Name: <%= Html.TextBox("FirstName", Model.FirstName) %> 
    Last Name: <%= Html.TextBox("LastName", Model.LastName) %> 
</div> 
<script type="text/javascript"> 
    // JsonSerialized object goes here 
</script> 

我考虑的另一个选择是使第二AJAX调用返回JsonResult动作,但也感觉不好的设计。

+0

你到底用了什么?我现在有同样的问题。 – Jon 2009-05-26 10:27:21

+0

@swilliams,你可以发布检索部分视图的jQuery代码。我有兴趣了解它是如何完成的。谢谢 – Picflight 2009-08-27 16:16:40

回答

2

我想我找到了一个不错的办法做到这一点,只是包装的JSON了在HtmlHelper扩展。下面是类:

using System.Web.Script.Serialization; 

public static class JsonExtensions { 
    public static string Json(this HtmlHelper html, string variableName) { 
     return Json(html, variableName, html.ViewData.Model); 
    } 

    public static string Json(this HtmlHelper html, string variableName, object model) { 
     TagBuilder tag = new TagBuilder("script"); 
     tag.Attributes.Add("type", "text/javascript"); 
     JavaScriptSerializer jsonSerializer = new JavaScriptSerializer(); 
     tag.InnerHtml = "var " + variableName + " = " + jsonSerializer.Serialize(model) + ";"; 
     return tag.ToString(); 
    } 
} 

你通过调用它:

<%= Html.Json("foo") %> 
<%= Html.Json("bar", Model.Something) %> 

的一个陷阱,我能想到的是,它并不是一个完全完美分离;您仍然在技术上将JavaScript放入HTML中。 但是,它不会额外调用服务器,并且IDE中的标记仍然非常干净。

1

也许不是最优雅的答案,你会得到,但只是在那里扔了这一点:

您可以返回从你的行动方法纯粹是JSON,

的东西,应该是这样的:

{ 
    Html: "<div class=\"person\"> etc...", 
    Json: { // your object here 
      } 
} 
在您的控制器

你需要像这样来呈现你的看法:

var existingContext = HttpContext.Current; 
var writer = new StringWriter(); 
var response = new HttpResponse(writer); 
var httpContext = new HttpContext(existingContext.Request, response); 

var viewResult = myAction(bla); 

HttpContext.Current = httpContext; 

viewResult.ExecuteResult(this.ControllerContext) 

HttpContext.Current = existingContext; 
var viewAsHtml = writer.ToString(); 
1

与Andrew相同的解决方案,但也许多一点MVC'ish ...

创建一个继承自ViewPage的新类。重写它的Render方法来渲染页面本身,然后将其填充到Andrew的输出中。因此,所有黑客行为都在Render方法中发生。

现在每个查看您创建您更改行:

<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<MyModel>" %> 

<%@ Page Title="" Language="C#" Inherits="CustomViewPage<MyModel>" %> 

我没有检查自己,但你猜它应该工作。如果你想我可以尝试并建立它。

0
public static string RenderPartialToString(string controlName, object viewData, object model, System.Web.Routing.RequestContext viewContext) 
      { 

       ViewDataDictionary vd = new ViewDataDictionary(viewData); 
       ViewPage vp = new ViewPage { ViewData = vd }; 

       vp.ViewData = vd; 
       vp.ViewData.Model = model; 
       vp.ViewContext = new ViewContext(); 
       vp.Url = new UrlHelper(viewContext); 

       Control control = vp.LoadControl(controlName); 

       vp.Controls.Add(control); 

       StringBuilder sb = new StringBuilder(); 

       using (StringWriter sw = new StringWriter(sb)) 
       { 

        using (HtmlTextWriter tw = new HtmlTextWriter(sw)) 
        { 

         vp.RenderControl(tw); 

        } 

       } 

       return sb.ToString(); 

      }