Comment inclure une vue partielle dans un formulaire Web

Certains sites que je programme utilisent à la fois ASP.NET MVC et WebForms.

J’ai une vue partielle et je veux l’inclure dans un formulaire Web. La vue partielle contient du code qui doit être traité sur le serveur. L’utilisation de Response.WriteFile ne fonctionne donc pas. Il devrait fonctionner avec JavaScript désactivé.

Comment puis-je faire ceci?

J’ai regardé la source de MVC pour voir si je pouvais comprendre comment faire. Il semble y avoir un couplage très étroit entre le contexte du contrôleur, les vues, les données de vue, les données de routage et les méthodes de rendu HTML.

Fondamentalement, pour que cela se produise, vous devez créer tous ces éléments supplémentaires. Certains d’entre eux sont relativement simples (comme les données de vue), mais d’autres sont un peu plus complexes. Par exemple, les données de routage considéreront que la page WebForms actuelle est ignorée.

Le gros problème semble être le HttpContext – les pages MVC reposent sur une base HttpContextBase (plutôt que HttpContext comme WebForms) et bien que les deux implémentent IServiceProvider, elles ne sont pas liées. Les concepteurs de MVC ont pris la décision délibérée de ne pas modifier les anciens formulaires Web pour utiliser la nouvelle base de contexte, mais ils ont toutefois fourni un wrapper.

Cela fonctionne et vous permet d’append une vue partielle à un WebForm:

public class WebFormController : Controller { } public static class WebFormMVCUtil { public static void RenderPartial( ssortingng 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 ); } } 

Ensuite, dans votre formulaire Web, vous pouvez le faire:

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

Cela a pris du temps, mais j’ai trouvé une excellente solution. Comme la solution Keith convient à beaucoup de gens, mais dans certaines situations, ce n’est pas le meilleur, car parfois vous voulez que votre application passe par le processus du contrôleur pour rendre la vue, et la solution de Keith ne fait que rendre la vue avec un model Je présente ici une nouvelle solution qui exécutera le processus normal.

Étapes générales:

  1. Créer une classe utilitaire
  2. Créer un contrôleur factice avec une vue factice
  3. Dans votre aspx ou master page , appelez la méthode utilitaire pour rendre partielle la vue du contrôleur, et si vous avez besoin du modèle à rendre (en tant qu’object),

Vérifions-le de près dans cet exemple

1) Créez une classe appelée MVCUtility et créez les méthodes suivantes:

  //Render a partial view, like Keith's solution private static void RenderPartial(ssortingng 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, ssortingng partialViewName) { ViewEngineResult result = ViewEngines.Engines.FindPartialView(controllerContext, partialViewName); if (result.View != null) { return result.View; } SsortingngBuilder locationsText = new SsortingngBuilder(); foreach (ssortingng location in result.SearchedLocations) { locationsText.AppendLine(); locationsText.Append(location); } throw new InvalidOperationException(Ssortingng.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(ssortingng controllerName, ssortingng actionName, object routeValues) { RenderPartial("PartialRender", new RenderActionViewModel() { ControllerName = controllerName, ActionName = actionName, RouteValues = routeValues }); } 

Créer une classe pour passer les parameters, je vais appeler ici RendeActionViewModel (vous pouvez créer dans le même fichier de la classe MvcUtility)

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

2) Créez maintenant un contrôleur nommé DummyController

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

Créez une vue PartialRender.cshtml appelée PartialRender.cshtml (vue du razor) pour DummyController avec le contenu suivant, notez qu’elle effectuera une autre action de rendu à l’aide de l’assistant HTML.

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

3) Maintenant, placez simplement ceci dans votre fichier MasterPage ou aspx , pour rendre partiellement une vue que vous voulez. Notez que ceci est une excellente réponse lorsque vous souhaitez combiner plusieurs vues de razor avec vos pages MasterPage ou aspx . (Nous avons une vue partielle appelée Login pour le contrôleur

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

ou si vous avez un modèle pour passer dans l’action

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

Cette solution est géniale, elle n’utilise pas l’appel ajax , qui ne retardera pas le rendu des vues nestedes, il ne crée pas de nouveau WebRequest , il ne vous apportera pas de nouvelle session et traitera la méthode de récupération. le ActionResult pour la vue que vous voulez, il fonctionne sans passer aucun modèle

Grâce à l’ utilisation de MVC RenderAction dans un formulaire Web

le moyen le plus évident serait via AJAX

quelque chose comme ça (en utilisant jQuery)

 

C’est génial, merci!

J’utilise MVC 2 sur .NET 4, qui nécessite qu’un TextWriter soit transmis à ViewContext, vous devez donc passer httpContextWrapper.Response.Output comme indiqué ci-dessous.

  public static void RenderPartial(Ssortingng 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); } 

Voici une approche similaire qui a fonctionné pour moi. La stratégie consiste à rendre la vue partielle à une chaîne, puis à la générer dans la page WebForm.

  public class TemplateHelper { ///  /// Render a Partial View (MVC User Control, .ascx) to a ssortingng using the given ViewData. /// http://www.joeyb.org/blog/2010/01/23/aspnet-mvc-2-render-template-to-ssortingng ///  ///  ///  ///  public static ssortingng RenderPartialToSsortingng(ssortingng controlName, object viewData) { ViewDataDictionary vd = new ViewDataDictionary(viewData); ViewPage vp = new ViewPage { ViewData = vd}; Control control = vp.LoadControl(controlName); vp.Controls.Add(control); SsortingngBuilder sb = new SsortingngBuilder(); using (SsortingngWriter sw = new SsortingngWriter(sb)) { using (HtmlTextWriter tw = new HtmlTextWriter(sw)) { vp.RenderControl(tw); } } return sb.ToSsortingng(); } } 

Dans la page codebehind, vous pouvez faire

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

et dans la page, vous aurez access au contenu rendu

 < %= NavigationBarContent %> 

J’espère que cela pourra aider!

Cette solution adopte une approche différente. Il définit un System.Web.UI.UserControl qui peut être placé sur n’importe quel formulaire Web et être configuré pour afficher le contenu à partir de n’importe quelle URL, y compris une vue partielle MVC. Cette approche est similaire à un appel AJAX pour HTML dans la mesure où les parameters (le cas échéant) sont donnés via la chaîne de requête URL.

Tout d’abord, définissez un contrôle utilisateur dans 2 fichiers:

Fichier /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 ssortingng contentUrl { get; set; } protected override void Render(HtmlTextWriter writer) { ssortingng 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); } } } 

Ajoutez ensuite le contrôle utilisateur à votre page de formulaire Web:

 < %@ Page Language="C#" %> < %@ Register Src="~/controls/PartialViewControl.ascx" TagPrefix="mcs" TagName="PartialViewControl" %> 

My MVC Partial View

Below is the content from by MVC partial view (or any other URL).