Renderuj częściowo z innego folderu (nieudostępnione)

256

Jak mogę renderować widok częściowy (kontrola użytkownika) z innego folderu? W wersji zapoznawczej 3 wywoływałem RenderUserControl z pełną ścieżką, ale przy aktualizacji do wersji 5 nie jest to już możliwe. Zamiast tego mamy metodę RenderPartial, ale nie oferuje mi ona funkcji, której szukam.

Boris Callens
źródło

Odpowiedzi:

443

Wystarczy podać ścieżkę do widoku z rozszerzeniem pliku.

Brzytwa:

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

Silnik ASP.NET:

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

Jeśli to nie jest twój problem, czy możesz dołączyć swój kod, który pracował z RenderUserControl?

Dwór Eliasza
źródło
19
Chciałbym tylko powiedzieć / AnotherFolder / Messages
Simon_Weaver
4
@Simon_Weaver Możesz to osiągnąć. Jednym ze sposobów byłoby zmodyfikować ViewEngine i zastąpić ją za FindPartialViewmetodę z czymś takimif(partialViewName.Contains"/")partialViewName="~/Views/"+partialViewName;
Arnis Lapsa
2
Działa również w silniku MVC 3 Razor, ale podobnie jak powyżej, potrzebujesz rozszerzenia (.cshtml).
Chris
Jeśli jest inaczej, należy podać ścieżkę „~ / Obszary / TestArea / Views / Shared / _SomePartial.mobile.cshtml”
sandeep talabathula
Jak radzisz sobie z różnymi kulturami tego częściowego widoku (na przykład ~ / Views / AnotherFolder / Messages.en.cshtml)?
jasdefer
29

W moim przypadku korzystałem z MvcMailer (https://github.com/smsohan/MvcMailer) i chciałem uzyskać dostęp do częściowego widoku z innego folderu, który nie był w folderze „Shared”. Powyższe rozwiązania nie działały, ale działało przy użyciu ścieżki względnej.

@Html.Partial("../MyViewFolder/Partials/_PartialView", Model.MyObject)
Aaron Sherman
źródło
Podobnie @ Html.Partial („../ Shared / _PartialView”), aby użyć folderu współdzielonego.
Curtis Yallop
11
Zauważyłem, że to nie działa bez rozszerzenia .cshtml na końcu.
Łukasz
28

Jeśli często używasz tej innej ścieżki, możesz to naprawić na stałe, bez konieczności ciągłego określania ścieżki. Domyślnie sprawdza częściowe widoki w folderze Widok i folderze współdzielonym. Ale powiedz, że chcesz go dodać.

Dodaj klasę do folderu Modele:

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

Następnie w pliku Global.asax.cs dodaj następujący wiersz:

ViewEngines.Engines.Add(new NewViewEngine());
Paweł
źródło
6
Oczywiście zdaję sobie sprawę, że to pytanie zostało zadane dawno temu. Pomyślałem, że dodam to do przyszłych Googlerów i przyszłych Bingerów.
Paul
- Nie będzie działać w .Net Core 2.2, ponieważ RazorViewEngine.PartialViewLocationFormats nie istnieje.
Demian Berisford-Maynard
7

Dla kontrolki użytkownika o nazwie myPartial.ascx znajdującej się w folderze Views / Account napisz:

<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>
Rahatur
źródło
5

Stworzyłem obejście, które wydaje się działać całkiem dobrze. Znalazłem potrzebę przejścia do kontekstu innego kontrolera w celu wyszukiwania nazw akcji, wyszukiwania itp. Aby to zaimplementować, stworzyłem nową metodę rozszerzenia dla HtmlHelper:

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

ControllerContextRegion jest zdefiniowany jako:

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

Sposób użycia tego w widoku jest następujący:

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

Mogą występować niepożądane skutki uboczne, jeśli Twój kod wymaga, aby controllerskładnik trasy nie zmieniał się, ale do tej pory w naszym kodzie nie wydaje się, aby to podejście było negatywne.

Jakub
źródło
4

VirtualPathProviderViewEngine, na którym oparty jest WebFormsViewEngine, powinien obsługiwać znaki „~” i „/” z przodu ścieżki, więc powyższe przykłady powinny działać.

Zauważyłem, że twoje przykłady wykorzystują ścieżkę „~ / Account / myPartial.ascx”, ale wspomniałeś, że twoja kontrola użytkownika znajduje się w folderze Views / Account. Czy próbowałeś

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

czy to tylko literówka w twoim pytaniu?

Andrew Stanton-Nurse
źródło
0

powinieneś tego spróbować

~/Views/Shared/parts/UMFview.ascx

umieść ~/Views/przed swoim kodem

mounir
źródło
0

Utwórz niestandardowy silnik widoku i zastosuj metodę, która zwraca ViewEngineResult W tym przykładzie po prostu nadpisujesz _options.ViewLocationFormatsi dodajesz katalog folderów:

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

Przykład: https://github.com/AspNetMonsters/pugzor

Demian Berisford-Maynard
źródło
-5

Spróbuj użyć RenderAction("myPartial","Account");

Siva Kandaraj
źródło
3
Przeczytaj pytanie, gdy użytkownik pyta o widok w innym folderze, gdzie jest folder w twoim kodzie?
Pamma,