Question

Certains site que je suis la programmation utilise à la fois ASP.NET MVC et WebForms.

J'ai une vue partielle et je veux inclure cela à l'intérieur d'un formulaire en ligne. La vue partielle a un code qui doit être traitée dans le serveur, en utilisant Response.WriteFile ne fonctionnent pas. Il devrait travailler avec javascript qui est désactivé.

Comment puis-je faire?

Était-ce utile?

La solution

J'ai eu un coup d'oeil à la source MVC pour voir si je pouvais comprendre comment faire cela. Il semble y avoir couplage très étroit entre le contexte du contrôleur, des vues, des données de vue, les données de routage et le code html rendre les méthodes.

En gros, pour faire cela, vous devez arriver pour créer tous ces éléments supplémentaires. Certains d'entre eux sont relativement simples (telles que les données de vue), mais certains sont un peu plus complexe -. Par exemple les données de routage envisageront la page WebForms actuelle à ignorer

Le gros problème semble être le HttpContext - pages de type MVC comptent sur une HttpContextBase (plutôt que HttpContext comme WebForms faire) et tout à la fois mettre en œuvre IServiceProvider ils ne sont pas liés. Les concepteurs de MVC a pris une décision délibérée de ne pas modifier les WebForms héritées d'utiliser la nouvelle base de contexte, mais ils ont fourni une enveloppe.

Cela fonctionne et vous permet d'ajouter une vue partielle à un 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 );
    }

}

Ensuite, dans votre WebForm vous pouvez faire ceci:

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

Autres conseils

Il a fallu un certain temps, mais je l'ai trouvé une excellente solution. La solution de Keith travaille pour beaucoup de gens, mais dans certaines situations, il est pas le meilleur, parce que parfois vous voulez que votre application passer par le processus du contrôleur pour rendre la vue, et solution de Keith juste rend la vue avec un modèle donné 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 en vue factice
  3. Dans votre aspx ou master page, appelez la méthode utilitaire pour rendre partielle passage du contrôleur, vue et si vous avez besoin, le modèle de rendre (comme un objet),

Voyons attentivement dans cet exemple

1) Créer un MVCUtility appelé classe et créer les méthodes suivantes:

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

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

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

2) Maintenant, créez un contrôleur DummyController nommé

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

Créer une vue factice appelé PartialRender.cshtml (vue rasoir) pour le DummyController avec le contenu suivant, notez qu'il effectuera une autre action Render en utilisant l'assistant Html.

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

3) Maintenant, il suffit de mettre dans votre MasterPage ou fichier aspx, à une vue partielle rendu que vous voulez. Notez que ceci est une excellente réponse lorsque vous avez plusieurs vues de rasoir que vous voulez mélanger avec vos pages MasterPage ou aspx. (En supposant que nous avons un PartialView appelé Connectez-vous pour le contrôleur Home).

    <% 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 grande, ne pas utiliser appel ajax , qui ne provoquera pas un retardé rendu pour les vues imbriquées, il ne fait pas nouveau WebRequest il ne vous apportera pas une nouvelle session , et traitera la méthode pour récupérer le ActionResult pour la vue que vous voulez, il fonctionne sans passer aucun modèle

Merci à Utilisation de MVC RenderAction dans un Webform

façon la plus évidente serait via AJAX

quelque chose comme ceci (en utilisant jQuery)

<div id="mvcpartial"></div>

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

Cela tombe bien, merci!

J'utilise MVC 2 sur 4 .NET, ce qui nécessite un TextWriter est transmis dans le ViewContext, donc vous devez passer httpContextWrapper.Response.Output comme indiqué ci-dessous.

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

Voici une approche similaire qui a travaillé pour moi. La stratégie est de rendre la vue partielle à une chaîne, puis sortie qui dans la page Web Forms.

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

Dans la page behind, vous pouvez faire

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

    }
}

et la page que vous aurez accès au contenu rendu

<%= NavigationBarContent %>

L'espoir qui aide!

Cette solution adopte une approche différente. Il définit un System.Web.UI.UserControl qui peut être placé sur un formulaire Web et être configuré pour afficher le contenu de toute URL ... y compris une vue partielle MVC. Cette approche est similaire à un appel AJAX pour HTML que les paramètres (le cas échéant) sont données via la chaîne de requête URL.

D'abord, définir 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 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);
        }
    }
}

Ensuite, ajoutez le contrôle utilisateur sur votre page de formulaire 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/"  />

FWIW, je devais être en mesure de rendre une vue partielle dynamique du code existant webforms, et l'insérer dans la partie supérieure d'un contrôle donné. Je trouve que la réponse de Keith peut causer la vue partielle rendue en dehors de la balise <html />.

En utilisant les réponses de Keith et Hilarius d'inspiration, plutôt que de rendre directement à HttpContext.Current.Response.Output, je rendais la chaîne html et ajouté comme un LiteralControl au contrôle correspondant.

Dans la classe d'aide statique:

    public static string RenderPartial(string partialName, object model)
    {
        //get a wrapper for the legacy WebForm context
        var httpCtx = new HttpContextWrapper(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(), new StringWriter());

        // This will render the partial view direct to the output, but be careful as it may end up outside of the <html /> tag
        //view.Render(vctx, HttpContext.Current.Response.Output);

        // Better to render like this and create a literal control to add to the parent
        var html = new StringWriter();
        view.Render(vctx, html);
        return html.GetStringBuilder().ToString();
    }

En classe appelant:

    internal void AddPartialViewToControl(HtmlGenericControl ctrl, int? insertAt = null, object model)
    {
        var lit = new LiteralControl { Text = MvcHelper.RenderPartial("~/Views/Shared/_MySharedView.cshtml", model};
        if (insertAt == null)
        {
            ctrl.Controls.Add(lit);
            return;
        }
        ctrl.Controls.AddAt(insertAt.Value, lit);
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top