Возврат PartialView с использованием HTML и JavaScript - PullRequest
2 голосов
/ 16 апреля 2009

Я делаю AJAX-вызов (с jQuery), чтобы получить PartialView. Наряду с HTML я хотел бы отправить обратно JSON-представление объекта, который отображает View. Хитрый способ, которым я пользуюсь, это встраивание свойств в виде скрытых входных данных в HTML, который быстро становится громоздким и тесно связывает слишком много вещей.

Я мог бы просто послать JavaScript в теге <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>

Другой вариант, который я рассмотрел, - это сделать второй AJAX-вызов для действия, которое возвращает JsonResult, но это также похоже на плохой дизайн.

Ответы [ 4 ]

2 голосов
/ 03 июня 2009

Я думаю, что нашел довольно хороший способ сделать это, просто заверните 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 голос
/ 19 апреля 2009

То же решение, что и у Эндрю, но, возможно, немного больше MVC'ish ...

Создайте новый класс, который наследуется от ViewPage. Переопределите его метод Render, чтобы отобразить саму страницу, а затем добавьте его в вывод, предложенный Эндрю. Чтобы все взломы происходили в методе Render, где это должно происходить.

Теперь каждое создаваемое вами представление меняет строку:

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

с

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

Я сам не проверял, но думаю, это должно сработать. Если хочешь, я могу попробовать и построить его.

1 голос
/ 16 апреля 2009

Наверное, не самый элегантный ответ, который вы получите, но просто добавьте его:

Вы можете вернуть чисто 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();
0 голосов
/ 26 мая 2009
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();

            }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...