从控制器内部获取部分视图的 HTML

发布于 2024-07-09 10:59:21 字数 239 浏览 11 评论 0原文

我为我的 mvc 网站开发了一种简单的机制,通过 jquery 提取 html,然后填充指定的 div。 一切都很好,看起来很酷。
我的问题是,我现在正在控制器内创建 html 标记(顺便说一句,这在 VB.net 中很容易做到),我不想混淆关注点的分离。

是否可以使用自定义“MVC 视图用户控件”来满足此需求? 我可以创建一个控件实例,传入模型数据并渲染为 html 吗? 然后渲染并传回调用浏览器就变得很简单了。

I have developed a simple mechanism for my mvc website to pull in html via jquery which then populates a specified div. All is well and it looks cool.
My problem is that i'm now creating html markup inside of my controller (Which is very easy to do in VB.net btw) I'd rather not mix up the sepparation of concerns.

Is it possible to use a custom 'MVC View User Control' to suit this need? Can I create an instance of a control, pass in the model data and render to html? It would then be a simple matter of rendering and passing back to the calling browser.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

初见 2024-07-16 10:59:21

这是一个适用于 ASP.Net MVC 1.0 的解决方案(许多声称适用于 beta 3 的解决方案不适用于 1.0),不会遇到“服务器在发送 HTTP 标头后无法设置内容类型”的问题并且可以从控制器(不仅仅是视图)内调用:

/// <summary>
/// Render a view into a string. It's a hack, it may fail badly.
/// </summary>
/// <param name="name">Name of the view, that is, its path.</param>
/// <param name="data">Data to pass to the view, a model or something like that.</param>
/// <returns>A string with the (HTML of) view.</returns>
public static string RenderPartialToString(string controlName, object viewData) {
    ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };
    viewPage.Url = GetBogusUrlHelper();

    viewPage.ViewData = new ViewDataDictionary(viewData);
    viewPage.Controls.Add(viewPage.LoadControl(controlName));

    StringBuilder sb = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb)) {
        using (HtmlTextWriter tw = new HtmlTextWriter(sw)) {
            viewPage.RenderControl(tw);
        }
    }

    return sb.ToString();
}

public static UrlHelper GetBogusUrlHelper() {
  var httpContext = HttpContext.Current;

  if (httpContext == null) {
    var request = new HttpRequest("/", Config.Url.ToString(), "");
    var response = new HttpResponse(new StringWriter());
    httpContext = new HttpContext(request, response);
  }

  var httpContextBase = new HttpContextWrapper(httpContext);
  var routeData = new RouteData();
  var requestContext = new RequestContext(httpContextBase, routeData);

  return new UrlHelper(requestContext);
}

这是一个静态方法,您可以将其放在您认为方便的地方。 你可以这样称呼它:

string view = RenderPartialToString("~/Views/Controller/AView.ascx", someModelObject); 

This is a solution that is working with ASP.Net MVC 1.0 (many that claim to work with beta 3 don't work with 1.0), doesn't suffer of the 'Server cannot set content type after HTTP headers have been sent' problem and can be called from within a controller (not only a view):

/// <summary>
/// Render a view into a string. It's a hack, it may fail badly.
/// </summary>
/// <param name="name">Name of the view, that is, its path.</param>
/// <param name="data">Data to pass to the view, a model or something like that.</param>
/// <returns>A string with the (HTML of) view.</returns>
public static string RenderPartialToString(string controlName, object viewData) {
    ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };
    viewPage.Url = GetBogusUrlHelper();

    viewPage.ViewData = new ViewDataDictionary(viewData);
    viewPage.Controls.Add(viewPage.LoadControl(controlName));

    StringBuilder sb = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb)) {
        using (HtmlTextWriter tw = new HtmlTextWriter(sw)) {
            viewPage.RenderControl(tw);
        }
    }

    return sb.ToString();
}

public static UrlHelper GetBogusUrlHelper() {
  var httpContext = HttpContext.Current;

  if (httpContext == null) {
    var request = new HttpRequest("/", Config.Url.ToString(), "");
    var response = new HttpResponse(new StringWriter());
    httpContext = new HttpContext(request, response);
  }

  var httpContextBase = new HttpContextWrapper(httpContext);
  var routeData = new RouteData();
  var requestContext = new RequestContext(httpContextBase, routeData);

  return new UrlHelper(requestContext);
}

It's a static method you can drop somewhere you find it convenient. You can call it this way:

string view = RenderPartialToString("~/Views/Controller/AView.ascx", someModelObject); 
罪#恶を代价 2024-07-16 10:59:21

我构建了一个粗略的框架,允许您从 MVC Beta 中的控制器方法将视图渲染为字符串。 这应该有助于暂时解决这个限制。

此外,我还为 MVC Beta 构建了一个类似 Rails 的 RJS javascript 生成框架。

请访问 http:// www.brightmix.com/blog/how-to-renderpartial-to-string-in-asp-net-mvc 并让我知道您的想法。

I put together a rough framework which allows you to render views to a string from a controller method in MVC Beta. This should help solve this limitation for now.

Additionally, I also put together a Rails-like RJS javascript generating framework for MVC Beta.

Check it out at http://www.brightmix.com/blog/how-to-renderpartial-to-string-in-asp-net-mvc and let me know what you think.

日记撕了你也走了 2024-07-16 10:59:21

您可以像这样创建您的操作:

        public PartialViewResult LoginForm()
        {
            var model = // get model data from somewhere
            return PartialView(model);
        }

该操作会将渲染的部分视图返回到您的 jquery 响应。

你的 jquery 可能看起来像这样:

$('#targetdiv').load('/MyController/LoginForm',function(){alert('complete!');});

You would create your action like this:

        public PartialViewResult LoginForm()
        {
            var model = // get model data from somewhere
            return PartialView(model);
        }

And the action would return the rendered partial view to your jquery response.

Your jquery could look something like this:

$('#targetdiv').load('/MyController/LoginForm',function(){alert('complete!');});
鹿港小镇 2024-07-16 10:59:21

您应该使用 jquery 填充您的 div(并根据需要创建新的 html 元素),并使用 ActionResult 的 Json 序列化。

另一种方法是使用 jquery 调用某些控制器/操作,但 json 使用常规视图(aspx 或 ascx、webforms 视图引擎)来渲染内容,并且使用 jquery 只需将该 html 注入到某些 div 中。 这是从 asp.net ajax 到 UpdatePanels 的一半方法...

我可能会使用第一种方法,使用 json,您几乎没有更多的工作要做,但它更加“优化”,因为您不传输整个 html通过网络,只有序列化的对象。 这就是“大佬”(gmail、g docs、hotmail 等)的做法——大量 JS 代码通过 UI 进行操作。

如果你不需要ajax,那么你基本上有两种调用部分视图的方法:

  • html.renderpartial("name of ascx")
  • html.RenderAction(x=>x.ActionName) from Microsoft.web.mvc (mvc futures) )

You should use jquery to populate your divs (and create new html elements if needed), and Json serialization for ActionResult.

Other way is to use jquery to call some controller/action, but instead json use regular View (aspx or ascx, webforms view engine) for rendering content, and with jquery just inject that html to some div. This is half way to UpdatePanels from asp.net ajax...

I would probably go with first method, with json, where you have little more job to do, but it's much more "optimized", because you don't transfer whole html over the wire, there are just serialized objects. It's the way that "big ones" (gmail, g docs, hotmail,..) do it - lot of JS code that manipulates with UI.

If you don't need ajax, then you basically have two ways of calling partial views:

  • html.renderpartial("name of ascx")
  • html.RenderAction(x=>x.ActionName) from Microsoft.web.mvc (mvc futures)
玻璃人 2024-07-16 10:59:21

经过谷歌大量挖掘后,我找到了答案。
您无法轻松访问视图输出的 html。

http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to- Different-output-source.aspx

After much digging in google i have found the answer.
You can not get easy access to the html outputted by the view.

http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to-different-output-source.aspx

难得心□动 2024-07-16 10:59:21

我已经为我正在开发的应用程序做了类似的事情。 我有返回渲染内容的部分视图可以使用其 REST 路径或使用以下方式调用:

<% Html.RenderAction("Action", "Controller"); %>

然后在我的实际显示 HTML 中,我有一个由 jQuery 填充的 DIV:

<div class="onload">/controller/action</div>

jQuery 如下所示:

<script type="text/javascript">
    $.ajaxSetup({ cache: false });

    $(document).ready(function () {
        $('div.onload').each(function () {
            var source = $(this).html();
            if (source != "") {
                $(this).load(source);
            }
        });
    });
</script>

这会扫描与“onload”匹配的所有 DIV类并从其内容中读取 REST 路径。 然后,它在该 REST 路径上执行 jQuery.load 并使用结果填充 DIV。

抱歉,我得搭车回家了。 如果您想让我详细说明,请告诉我。

I've done something similar for an app I'm working on. I have partial views returning rendered content can be called using their REST path or using:

<% Html.RenderAction("Action", "Controller"); %>

Then in my actual display HTML I have a DIV which is filled from jQuery:

<div class="onload">/controller/action</div>

The jQuery looks like this:

<script type="text/javascript">
    $.ajaxSetup({ cache: false });

    $(document).ready(function () {
        $('div.onload').each(function () {
            var source = $(this).html();
            if (source != "") {
                $(this).load(source);
            }
        });
    });
</script>

This scans for all DIV that match the "onload" class and reads the REST path from their content. It then does a jQuery.load on that REST path and populates the DIV with the result.

Sorry gotta go catch my ride home. Let me know if you want me to elaborate more.

恰似旧人归 2024-07-16 10:59:21

您有多种选择。

在视图的控制器中创建 MVC 视图用户控件和操作处理程序。 要渲染视图,请使用

<% Html.RenderPartial("MyControl") %>

在这种情况下,您的操作处理程序将需要将模型数据传递到视图

public ActionResult MyControl ()
{
    // get modelData

    render View (modelData);
}

您的另一个选择是从父页面传递模型数据。 在这种情况下,您不需要操作处理程序,并且模型类型与父级相同:

<% Html.RenderPartial("MyControl", ViewData.Model) %>

如果您的用户控件有自己的数据类型,您也可以在页面中构造它

在 MyControl.ascx.cs 中:

public class MyControlViewData
{
    public string Name { get; set; }
    public string Email { get; set; }
}

public partial class MyControl : System.Web.Mvc.ViewUserControl <MyControlViewData>
{
}

在您的页面中,您可以初始化控件的数据模型:

<% Html.RenderPartial("MyControl", new MyControlViewData ()
   {
        Name= ViewData.Model.FirstName,
        Email = ViewData.Model.Email,
   });
 %>

You have several options.

Create a MVC View User Control and action handler in your controller for the view. To render the view use

<% Html.RenderPartial("MyControl") %>

In this case your action handler will need to pass the model data to the view

public ActionResult MyControl ()
{
    // get modelData

    render View (modelData);
}

Your other option is to pass the model data from the parent page. In this case you do not need an action handler and the model type is the same as the parent:

<% Html.RenderPartial("MyControl", ViewData.Model) %>

If your user control has it's own data type you can also construct it within the page

In MyControl.ascx.cs:

public class MyControlViewData
{
    public string Name { get; set; }
    public string Email { get; set; }
}

public partial class MyControl : System.Web.Mvc.ViewUserControl <MyControlViewData>
{
}

And in your page you can initialize your control's data model:

<% Html.RenderPartial("MyControl", new MyControlViewData ()
   {
        Name= ViewData.Model.FirstName,
        Email = ViewData.Model.Email,
   });
 %>
随心而道 2024-07-16 10:59:21

在 Rails 中,这称为渲染部分视图,您可以使用 render :partial => 来完成此操作。 '你的文件名'。 我相信 ASP.NET MVC 有类似的 RenderPartial 方法,但我找不到 MVC 的官方文档来确认或否认这样的事情。

In rails this is called rendering a partial view, and you do it with render :partial => 'yourfilename'. I believe ASP.NET MVC has a similar RenderPartial method, but I can't find the official docs for MVC to confirm or deny such a thing.

走过海棠暮 2024-07-16 10:59:21

这非常简单,您只需创建一个强类型的部分视图(或用户控件),然后在您的控制器中创建如下所示的内容:

public PartialViewResult yourpartialviewresult()
{
    var yourModel
    return PartialView("yourPartialView", yourModel);
}

然后您可以在需要时使用 JQuery 执行请求:

$.ajax({
    type: 'GET',
    url: '/home/yourpartialviewresult',
    dataType: 'html', //be sure to use html dataType
    contentType: 'application/json; charset=utf-8',
    success: function(data){
         $(container).html(data);
    },
    complete: function(){ }
 });    

it is very simple you just have to create a strongly typed partial view(or user control) then in your cotroller something like this:

public PartialViewResult yourpartialviewresult()
{
    var yourModel
    return PartialView("yourPartialView", yourModel);
}

then you can use JQuery to perform the request whener you want:

$.ajax({
    type: 'GET',
    url: '/home/yourpartialviewresult',
    dataType: 'html', //be sure to use html dataType
    contentType: 'application/json; charset=utf-8',
    success: function(data){
         $(container).html(data);
    },
    complete: function(){ }
 });    
榕城若虚 2024-07-16 10:59:21

我发现这一行代码可以完美工作。 orderModel 是我的模型对象。 就我而言,我有一个辅助方法,其中我必须合并部分视图的 html。

System.Web.Mvc.Html.PartialExtensions.Partial(html, "~/Views/Orders/OrdersPartialView.cshtml", orderModel).ToString();

I found this one line code to work perfectly. orderModel being my model object. In my case I had a helper method in which I had to merge a partial view's html.

System.Web.Mvc.Html.PartialExtensions.Partial(html, "~/Views/Orders/OrdersPartialView.cshtml", orderModel).ToString();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文