web-dev-qa-db-fra.com

Rendu partiel à partir d'un dossier différent (non partagé)

Comment faire en sorte qu'une vue rende un partiel (contrôle utilisateur) à partir d'un autre dossier? Avec Preview 3, j’appelais RenderUserControl avec le chemin complet, mais lors de la mise à niveau vers Preview 5, cela n’est plus possible. Au lieu de cela, nous avons eu la méthode RenderPartial, mais elle ne m'offre pas les fonctionnalités que je recherche.

239
Boris Callens

Incluez simplement le chemin d'accès à la vue, avec l'extension de fichier.

Rasoir:

@Html.Partial("~/Views/AnotherFolder/Messages.cshtml", ViewData.Model.Successes)

Moteur ASP.NET:

<% Html.RenderPartial("~/Views/AnotherFolder/Messages.ascx", ViewData.Model.Successes); %>

Si ce n'est pas votre problème, pourriez-vous s'il vous plaît inclure votre code qui fonctionnait auparavant avec RenderUserControl?

422
Elijah Manor

Dans mon cas, j'utilisais MvcMailer (https://github.com/smsohan/MvcMailer) et je voulais accéder à une vue partielle à partir d'un autre dossier, qui n'était pas dans "Partagé". Les solutions ci-dessus n'ont pas fonctionné, mais l'utilisation d'un chemin relatif a fonctionné.

@Html.Partial("../MyViewFolder/Partials/_PartialView", Model.MyObject)
26
Aaron Sherman

Si vous utilisez souvent cet autre chemin, vous pouvez résoudre ce problème de façon permanente sans avoir à spécifier le chemin tout le temps. Par défaut, il recherche des vues partielles dans le dossier View et dans le dossier Shared. Mais disons que vous voulez en ajouter un.

Ajoutez une classe à votre dossier Modèles:

public class NewViewEngine : RazorViewEngine {

   private static readonly string[] NEW_PARTIAL_VIEW_FORMATS = new[] {
      "~/Views/Foo/{0}.cshtml",
      "~/Views/Shared/Bar/{0}.cshtml"
   };

   public NewViewEngine() {
      // Keep existing locations in sync
      base.PartialViewLocationFormats = base.PartialViewLocationFormats.Union(NEW_PARTIAL_VIEW_FORMATS).ToArray();
   }
}

Ensuite, dans votre fichier Global.asax.cs, ajoutez la ligne suivante:

ViewEngines.Engines.Add(new NewViewEngine());
25
Paul

Pour un contrôle utilisateur nommé myPartial.ascx situé dans le dossier Views/Account, écrivez comme ceci:

<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>
7
Rahatur

J'ai créé une solution de contournement qui semble fonctionner assez bien. J'ai trouvé qu'il était nécessaire de basculer vers le contexte d'un autre contrôleur pour la recherche de nom d'action, de vue, etc. Pour implémenter cela, j'ai créé une nouvelle méthode d'extension pour HtmlHelper:

public static IDisposable ControllerContextRegion(
    this HtmlHelper html, 
    string controllerName)
{
    return new ControllerContextRegion(html.ViewContext.RouteData, controllerName);
}

ControllerContextRegion est défini comme:

internal class ControllerContextRegion : IDisposable
{
    private readonly RouteData routeData;
    private readonly string previousControllerName;

    public ControllerContextRegion(RouteData routeData, string controllerName)
    {
        this.routeData = routeData;
        this.previousControllerName = routeData.GetRequiredString("controller");
        this.SetControllerName(controllerName);
    }

    public void Dispose()
    {
        this.SetControllerName(this.previousControllerName);
    }

    private void SetControllerName(string controllerName)
    {
        this.routeData.Values["controller"] = controllerName;
    }
}

La manière dont cela est utilisé dans une vue est la suivante:

@using (Html.ControllerContextRegion("Foo")) {
    // Html.Action, Html.Partial, etc. now looks things up as though
    // FooController was our controller.
}

Cela pourrait avoir des effets secondaires indésirables si votre code demande au composant de route controller de ne pas changer, mais dans notre code jusqu'à présent, il ne semble pas y avoir de négatif à cette approche.

5
Jacob

VirtualPathProviderViewEngine, sur lequel est basé WebFormsViewEngine, est supposé prendre en charge les caractères "~" et "/" situés au début du chemin afin que vos exemples ci-dessus fonctionnent.

J'ai remarqué que vos exemples utilisent le chemin "~/Account/myPartial.ascx", mais vous avez indiqué que votre contrôle utilisateur se trouvait dans le dossier Views/Account. As-tu essayé

<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>

ou est-ce juste une faute de frappe dans votre question?

4

Créez un moteur de vue personnalisé et utilisez une méthode qui renvoie un ViewEngineResult. Dans cet exemple, vous écrasez simplement le _options.ViewLocationFormats et ajoutez votre répertoire de dossiers:

public ViewEngineResult FindView(ActionContext context, string viewName, bool isMainPage)
        {
            var controllerName = context.GetNormalizedRouteValue(CONTROLLER_KEY);
            var areaName = context.GetNormalizedRouteValue(AREA_KEY);

            var checkedLocations = new List<string>();
            foreach (var location in _options.ViewLocationFormats)
            {
                var view = string.Format(location, viewName, controllerName);
                if (File.Exists(view))
                {
                    return ViewEngineResult.Found("Default", new View(view, _ViewRendering));
                }
                checkedLocations.Add(view);
            }

            return ViewEngineResult.NotFound(viewName, checkedLocations);
        }

Exemple: https://github.com/AspNetMonsters/pugzor

tu devrais essayer ça

~/Views/Shared/parts/UMFview.ascx

placez le ~/Views/ devant votre code

0
mounir