简体   繁体   English

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

[英]Getting a Partial View's HTML from inside of the controller

I have developed a simple mechanism for my mvc website to pull in html via jquery which then populates a specified div. 我为我的mvc网站开发了一个简单的机制,通过jquery引入html,然后填充指定的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. 我的问题是我现在正在我的控制器内部创建html标记(这在VB.net中很容易做到btw)我宁可不要混淆一些关注点。

Is it possible to use a custom 'MVC View User Control' to suit this need? 是否可以使用自定义的“MVC View用户控件”来满足这种需求? Can I create an instance of a control, pass in the model data and render to html? 我可以创建控件的实例,传入模型数据并渲染为html吗? It would then be a simple matter of rendering and passing back to the calling browser. 然后,这将是一个简单的渲染和传递回调用浏览器的问题。

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): 这是一个与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);
}

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

I put together a rough framework which allows you to render views to a string from a controller method in MVC Beta. 我整理了一个粗略的框架,它允许您从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. 此外,我还为MVC Beta组建了一个类似Rails的RJS javascript生成框架。

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. 请访问http://www.brightmix.com/blog/how-to-renderpartial-to-string-in-asp-net-mvc查看,并告诉我您的想法。

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. 并且该操作会将呈现的部分视图返回到您的jquery响应。

Your jquery could look something like this: 你的jquery看起来像这样:

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

You should use jquery to populate your divs (and create new html elements if needed), and Json serialization for ActionResult. 您应该使用jquery来填充div(如果需要,还可以创建新的html元素),以及ActionResult的Json序列化。

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. 其他方法是使用jquery来调用一些控制器/动作,但是json使用常规View(aspx或ascx,webforms视图引擎)来呈现内容,而jquery只是将html注入到某个div中。 This is half way to UpdatePanels from asp.net ajax... 这是来自asp.net ajax的UpdatePanels的一半...

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. 我可能会选择第一种方法,使用json,你可以做更多的工作,但它更加“优化”,因为你不会通过电线传输整个html,只有序列化的对象。 It's the way that "big ones" (gmail, g docs, hotmail,..) do it - lot of JS code that manipulates with UI. 这就是“大人物”(gmail,g docs,hotmail,..)这样做的方式 - 许多用UI操作的JS代码。

If you don't need ajax, then you basically have two ways of calling partial views: 如果你不需要ajax,那么你基本上有两种方法来调用局部视图:

  • html.renderpartial("name of ascx") html.renderpartial(“ascx名称”)
  • html.RenderAction(x=>x.ActionName) from Microsoft.web.mvc (mvc futures) 来自Microsoft.web.mvc的html.RenderAction(x => x.ActionName)(mvc期货)

After much digging in google i have found the answer. 经过深入挖掘谷歌我找到了答案。 You can not get easy access to the html outputted by the view. 您无法轻松访问视图输出的html。

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

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: 我有部分视图返回渲染内容可以使用他们的REST路径或使用:

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

Then in my actual display HTML I have a DIV which is filled from jQuery: 然后在我的实际显示HTML中我有一个从jQuery填充的DIV:

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

The jQuery looks like this: 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>

This scans for all DIV that match the "onload" class and reads the REST path from their content. 这将扫描与“onload”类匹配的所有DIV,并从其内容中读取REST路径。 It then does a jQuery.load on that REST path and populates the DIV with the result. 然后它在该REST路径上执行jQuery.load并使用结果填充DIV。

Sorry gotta go catch my ride home. 对不起,我得赶紧回家。 Let me know if you want me to elaborate more. 如果您想让我详细说明,请告诉我。

You have several options. 你有几个选择。

Create a MVC View User Control and action handler in your controller for the view. 在控制器中为视图创建MVC视图用户控件和操作处理程序。 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: 在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,
   });
 %>

it is very simple you just have to create a strongly typed partial view(or user control) then in your cotroller something like this: 你只需要创建一个强类型的局部视图(或用户控件),然后在你的cotroller中就像这样:

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

then you can use JQuery to perform the request whener you want: 然后你可以使用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(){ }
 });    

In rails this is called rendering a partial view, and you do it with render :partial => 'yourfilename' . 在rails中,这称为渲染局部视图,您可以使用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. 我相信ASP.NET MVC有一个类似的RenderPartial方法,但我找不到MVC的官方文档来确认或否认这样的事情。

I found this one line code to work perfectly. 我发现这一行代码完美无缺。 orderModel being my model object. orderModel是我的模型对象。 In my case I had a helper method in which I had to merge a partial view's html. 在我的情况下,我有一个帮助方法,我必须合并部分视图的HTML。

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

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

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