繁体   English   中英

同时返回带有HTML和JavaScript的PartialView

[英]Returning a PartialView with both HTML and JavaScript

我正在进行AJAX调用(使用jQuery)以检索PartialView 与HTML一起,我想发回View显示的对象的JSON表示。 我一直使用的糟糕方法是将属性作为隐藏的输入嵌入HTML中,这很快变得笨拙并且紧密地耦合了太多的东西。

我可以将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>

我考虑过的另一种选择是对返回JsonResult的动作进行第二次AJAX调用,但这也感觉设计不好。

我想我找到了一个很好的方法,只需将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中的标记仍然非常干净。

可能不是您会得到的最优雅的答案,而只是把它扔在那里:

您可以从操作方法中返回纯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();

与安德鲁相同的解决方案,但可能更像是MVC ...

创建一个新类,该类继承自ViewPage。 重写其Render方法以呈现页面本身,然后将其填充到Andrew建议的输出中。 这样,所有骇客都会在应发生的Render方法中发生。

现在,您创建的每个视图都会更改该行:

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

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

我自己没有检查它,但是猜测它应该可以工作。 如果您愿意,我可以尝试构建它。

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();

            }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM