Rendering parziale da cartella diversa (non condivisa)


256

Come posso avere una vista renderizzare un parziale (controllo utente) da una cartella diversa? Con l'anteprima 3 chiamavo RenderUserControl con il percorso completo, ma con l'aggiornamento all'anteprima 5 questo non è più possibile. Invece abbiamo ottenuto il metodo RenderPartial, ma non mi offre la funzionalità che sto cercando.

Risposte:


443

Includi solo il percorso della vista, con l'estensione del file.

Rasoio:

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

Motore ASP.NET:

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

Se questo non è il tuo problema, potresti includere il tuo codice che funzionava con RenderUserControl?


19
Vorrei solo dire / AnotherFolder / Messaggi
Simon_Weaver

4
@Simon_Weaver Puoi raggiungerlo. Un modo sarebbe modificare ViewEngine e sovrascriverne il FindPartialViewmetodo con qualcosa del genereif(partialViewName.Contains"/")partialViewName="~/Views/"+partialViewName;
Arnis Lapsa,

2
Funziona anche con il motore MVC 3 Razor, ma come sopra, è necessaria l'estensione (.cshtml).
Chris

Se è diverso dovresti dare il percorso "~ / Areas / TestArea / Views / Shared / _SomePartial.mobile.cshtml"
sandeep talabathula

Come gestite le diverse culture di quella vista parziale (ad esempio ~ / Views / AnotherFolder / Messages.en.cshtml)?
jasdefer,

29

Nel mio caso stavo usando MvcMailer (https://github.com/smsohan/MvcMailer) e volevo accedere a una vista parziale da un'altra cartella, che non era in "Condiviso". Le soluzioni di cui sopra non hanno funzionato, ma utilizzando un percorso relativo ha funzionato.

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

Allo stesso modo @ Html.Partial ("../ Shared / _PartialView") per utilizzare la cartella condivisa.
Curtis Yallop,

11
Sto scoprendo che questo non funziona senza l'estensione .cshtml alla fine.
Luca,

28

Se si utilizza questo altro percorso per la maggior parte del tempo, è possibile risolverlo in modo permanente senza dover specificare il percorso per tutto il tempo. Per impostazione predefinita, controlla le viste parziali nella cartella Visualizza e nella cartella Condivisa. Ma dire che vuoi aggiungerne uno.

Aggiungi una classe alla cartella Modelli:

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

Quindi nel tuo file Global.asax.cs, aggiungi la seguente riga:

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

6
Ovviamente mi rendo conto che questa domanda è stata posta molto tempo fa. Ho pensato di aggiungere ad esso per futuri Googler e futuri Bingers.
Paul,

- Non funzionerà in .Net Core 2.2, poiché RazorViewEngine.PartialViewLocationFormats non esiste.
Demian Berisford-Maynard,

7

Per un controllo utente chiamato myPartial.ascx situato nella cartella Views / Account scrivi in ​​questo modo:

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

5

Ho creato una soluzione alternativa che sembra funzionare abbastanza bene. Ho trovato la necessità di passare al contesto di un controller diverso per la ricerca del nome dell'azione, la ricerca della visualizzazione, ecc. Per implementare questo, ho creato un nuovo metodo di estensione per HtmlHelper:

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

ControllerContextRegion è definito come:

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

Il modo in cui questo viene utilizzato in una vista è il seguente:

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

Potrebbero esserci effetti collaterali indesiderati per questo se il tuo codice richiede che il controllercomponente route non cambi, ma nel nostro codice finora non sembrano esserci aspetti negativi di questo approccio.


4

Si suppone che VirtualPathProviderViewEngine, su cui si basa WebFormsViewEngine, supporti i caratteri "~" e "/" nella parte anteriore del percorso, pertanto gli esempi sopra riportati dovrebbero funzionare.

Ho notato che i tuoi esempi usano il percorso "~ / Account / myPartial.ascx", ma hai detto che il tuo controllo utente si trova nella cartella Views / Account. Hai provato

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

o è solo un refuso nella tua domanda?



0

dovresti provare questo

~/Views/Shared/parts/UMFview.ascx

posiziona ~/Views/prima il tuo codice


0

Creare un motore di visualizzazione personalizzato e disporre di un metodo che restituisce un ViewEngineResult In questo esempio è sufficiente sovrascrivere _options.ViewLocationFormatse aggiungere la directory della cartella:

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

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


-5

Prova a usare RenderAction("myPartial","Account");


3
Si prega di leggere la domanda mentre l'utente sta chiedendo la visualizzazione in un'altra cartella in cui si trova la cartella nel codice?
Pamma
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.