如何在webform中包含局部视图

我正在编程的一些网站使用ASP.NET MVC和WebForms。

我有一个局部视图,我想包括在一个networking表单。 部分视图有一些代码必须在服务器中处理,所以使用Response.WriteFile不起作用。 它应该与JavaScript禁用。

我该怎么做?

我看了一下MVC的源代码,看看能不能弄清楚如何做到这一点。 控制器上下文,视图,视图数据,路由数据和html渲染方法之间似乎有非常紧密的耦合。

基本上为了做到这一点,你需要创build所有这些额外的元素。 其中一些比较简单(比如视图数据),但有些则比较复杂 – 比如路由数据会认为当前WebForms页面被忽略。

最大的问题似乎是HttpContext – MVC页面依赖于HttpContextBase(而不是像WebForms那样的HttpContext),而两者都实现IServiceProvider,它们是不相关的。 MVC的devise者做出了一个慎重的决定,即不改变传统的WebForms来使用新的上下文库,但是他们提供了一个包装器。

这工作,并让您添加到WebForm的部分视图:

public class WebFormController : Controller { } public static class WebFormMVCUtil { public static void RenderPartial( string partialName, object model ) { //get a wrapper for the legacy WebForm context var httpCtx = new HttpContextWrapper( System.Web.HttpContext.Current ); //create a mock route that points to the empty controller var rt = new RouteData(); rt.Values.Add( "controller", "WebFormController" ); //create a controller context for the route and http context var ctx = new ControllerContext( new RequestContext( httpCtx, rt ), new WebFormController() ); //find the partial view using the viewengine var view = ViewEngines.Engines.FindPartialView( ctx, partialName ).View; //create a view context and assign the model var vctx = new ViewContext( ctx, view, new ViewDataDictionary { Model = model }, new TempDataDictionary() ); //render the partial view view.Render( vctx, System.Web.HttpContext.Current.Response.Output ); } } 

然后在你的WebForm中,你可以这样做:

 <% WebFormMVCUtil.RenderPartial( "ViewName", this.GetModel() ); %> 

这花了一段时间,但我find了一个很好的解决scheme。 由于Keith解决scheme适用于很多人,但是在某些情况下并不是最好的,因为有时候你希望你的应用程序通过控制器来渲染视图,而Keith的解决scheme只是给出一个给定的视图模型我在这里提出一个新的解决scheme,将运行正常的过程。

一般步骤:

  1. 创build一个Utility类
  2. 用虚拟视图创build一个虚拟控制器
  3. 在您的aspxmaster page ,调用实用程序方法渲染部分传递Controller,视图(如果需要),渲染的模型(作为对象),

在这个例子中我们仔细检查一下

1)创build一个名为MVCUtility的类并创build以下方法:

  //Render a partial view, like Keith's solution private static void RenderPartial(string partialViewName, object model) { HttpContextBase httpContextBase = new HttpContextWrapper(HttpContext.Current); RouteData routeData = new RouteData(); routeData.Values.Add("controller", "Dummy"); ControllerContext controllerContext = new ControllerContext(new RequestContext(httpContextBase, routeData), new DummyController()); IView view = FindPartialView(controllerContext, partialViewName); ViewContext viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary { Model = model }, new TempDataDictionary(), httpContextBase.Response.Output); view.Render(viewContext, httpContextBase.Response.Output); } //Find the view, if not throw an exception private static IView FindPartialView(ControllerContext controllerContext, string partialViewName) { ViewEngineResult result = ViewEngines.Engines.FindPartialView(controllerContext, partialViewName); if (result.View != null) { return result.View; } StringBuilder locationsText = new StringBuilder(); foreach (string location in result.SearchedLocations) { locationsText.AppendLine(); locationsText.Append(location); } throw new InvalidOperationException(String.Format("Partial view {0} not found. Locations Searched: {1}", partialViewName, locationsText)); } //Here the method that will be called from MasterPage or Aspx public static void RenderAction(string controllerName, string actionName, object routeValues) { RenderPartial("PartialRender", new RenderActionViewModel() { ControllerName = controllerName, ActionName = actionName, RouteValues = routeValues }); } 

创build一个用于传递参数的类,我将在这里调用RendeActionViewModel(可以在MvcUtility类的同一个文件中创build)

  public class RenderActionViewModel { public string ControllerName { get; set; } public string ActionName { get; set; } public object RouteValues { get; set; } } 

2)现在创build一个名为DummyController的控制器

  //Here the Dummy controller with Dummy view public class DummyController : Controller { public ActionResult PartialRender() { return PartialView(); } } 

PartialRender.cshtml创build一个名为PartialRender.cshtml (razor视图)的Dummy视图, DummyController包含以下内容,请注意,它将使用Html助手执行另一个Render Action

 @model Portal.MVC.MvcUtility.RenderActionViewModel @{Html.RenderAction(Model.ActionName, Model.ControllerName, Model.RouteValues);} 

3)现在把它放在你的MasterPage或者aspx文件中,以部分渲染你想要的视图。 请注意,当您想要将多个razor的视图混合到您的MasterPageaspx页面时,这是一个很好的答案。 (假设我们在Controller Home中有一个名为Login的PartialView

  <% MyApplication.MvcUtility.RenderAction("Home", "Login", new { }); %> 

或者如果你有一个模型传递到行动

  <% MyApplication.MvcUtility.RenderAction("Home", "Login", new { Name="Daniel", Age = 30 }); %> 

这个解决scheme非常好, 不使用ajax调用 ,这不会导致嵌套视图的延迟渲染 ,它不会创build一个新的WebRequest,所以它不会给你一个新的会话它将处理检索的方法你想要的视图的ActionResult它的工作原理没有传递任何模型

感谢 在Webform中使用MVC RenderAction

最显而易见的方式是通过AJAX

这样的事情(使用jQuery)

 <div id="mvcpartial"></div> <script type="text/javascript"> $(document).load(function () { $.ajax( { type: "GET", url : "urltoyourmvcaction", success : function (msg) { $("#mvcpartial").html(msg); } }); }); </script> 

这很好,谢谢!

我在.NET 4上使用MVC 2,这需要一个TextWriter传递到ViewContext,所以你必须传递httpContextWrapper.Response.Output,如下所示。

  public static void RenderPartial(String partialName, Object model) { // get a wrapper for the legacy WebForm context var httpContextWrapper = new HttpContextWrapper(HttpContext.Current); // create a mock route that points to the empty controller var routeData = new RouteData(); routeData.Values.Add(_controller, _webFormController); // create a controller context for the route and http context var controllerContext = new ControllerContext(new RequestContext(httpContextWrapper, routeData), new WebFormController()); // find the partial view using the viewengine var view = ViewEngines.Engines.FindPartialView(controllerContext, partialName).View as WebFormView; // create a view context and assign the model var viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary { Model = model }, new TempDataDictionary(), httpContextWrapper.Response.Output); // render the partial view view.Render(viewContext, httpContextWrapper.Response.Output); } 

这是一个类似的方法,一直在为我工作。 该策略是将局部视图呈现为string,然后将其输出到WebForm页面中。

  public class TemplateHelper { /// <summary> /// Render a Partial View (MVC User Control, .ascx) to a string using the given ViewData. /// http://www.joeyb.org/blog/2010/01/23/aspnet-mvc-2-render-template-to-string /// </summary> /// <param name="controlName"></param> /// <param name="viewData"></param> /// <returns></returns> public static string RenderPartialToString(string controlName, object viewData) { ViewDataDictionary vd = new ViewDataDictionary(viewData); ViewPage vp = new ViewPage { ViewData = vd}; 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(); } } 

在页面代码隐藏,你可以做

 public partial class TestPartial : System.Web.UI.Page { public string NavigationBarContent { get; set; } protected void Page_Load(object sender, EventArgs e) { NavigationVM oVM = new NavigationVM(); NavigationBarContent = TemplateHelper.RenderPartialToString("~/Views/Shared/NavigationBar.ascx", oVM); } } 

并在页面中可以访问呈现的内容

 <%= NavigationBarContent %> 

希望有所帮助!

这个解决scheme采取不同的方法。 它定义了一个System.Web.UI.UserControl ,它可以放置在任何Web窗体上,并被configuration为显示来自任何URL的内容…包括一个MVC局部视图。 这种方法类似于AJAX对HTML的调用,因为通过URL查询string给出参数(如果有的话)。

首先,在两个文件中定义一个用户控件:

/controls/PartialViewControl.ascx文件

 <%@ Control Language="C#" AutoEventWireup="true" CodeFile="PartialViewControl.ascx.cs" Inherits="PartialViewControl" %> 

/controls/PartialViewControl.ascx.cs:

 public partial class PartialViewControl : System.Web.UI.UserControl { [Browsable(true), Category("Configutation"), Description("Specifies an absolute or relative path to the content to display.")] public string contentUrl { get; set; } protected override void Render(HtmlTextWriter writer) { string requestPath = (contentUrl.StartsWith("http") ? contentUrl : "http://" + Request.Url.DnsSafeHost + Page.ResolveUrl(contentUrl)); WebRequest request = WebRequest.Create(requestPath); WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); var responseStreamReader = new StreamReader(responseStream); var buffer = new char[32768]; int read; while ((read = responseStreamReader.Read(buffer, 0, buffer.Length)) > 0) { writer.Write(buffer, 0, read); } } } 

然后将用户控件添加到您的Web表单页面:

 <%@ Page Language="C#" %> <%@ Register Src="~/controls/PartialViewControl.ascx" TagPrefix="mcs" TagName="PartialViewControl" %> <h1>My MVC Partial View</h1> <p>Below is the content from by MVC partial view (or any other URL).</p> <mcs:PartialViewControl runat="server" contentUrl="/MyMVCView/" />