代码之家  ›  专栏  ›  技术社区  ›  swilliams

使用HTML和JavaScript返回partialView

  •  2
  • swilliams  · 技术社区  · 16 年前

    我正在进行Ajax调用(使用jquery)以检索 PartialView . 除了HTML,我还想返回视图显示的对象的JSON表示。我一直使用的糟糕方法是将属性作为隐藏的输入嵌入到HTML中,这很快就会变得笨拙,并且将太多的东西紧密地结合在一起。

    我可以用一个 <script> 标记在HTML之后,但我真的很想把这些东西分开。就像这样:

    <%@ 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>
    

    我考虑的另一个选项是对返回 JsonResult 但这也让人觉得设计不好。

    4 回复  |  直到 15 年前
        1
  •  2
  •   swilliams    15 年前

    我想我找到了一个很好的方法,把 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) %>
    

    我能想到的一点是,它不是一个完整的 很完美 分离;从技术上讲,您还在HTML中放入JavaScript。 但是 ,它不会额外调用服务器,而且IDE中的标记仍然很干净。

        2
  •  1
  •   Andrew Bullock    16 年前

    也许这不是你能得到的最优雅的答案,但把它扔出去就行了:

    您可以从操作方法返回纯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();
    
        3
  •  1
  •   Gideon    16 年前

    和安德鲁的解决方案一样,但也许更像MVC…

    创建从ViewPage继承的新类。重写其呈现方法以呈现页面本身,然后将其放入安德鲁建议的输出中。所以所有的黑客攻击都发生在渲染方法中,它应该发生在那里。

    现在,您创建的每个视图都将更改线条:

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

    具有

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

    我没亲自检查过,但我想应该可以。如果你愿意,我可以试着建造它。

        4
  •  0
  •   Jon    15 年前
    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();
    
                }