Рендеринг частичного из другой папки (не общий)

256

Как я могу сделать представление визуализации частичного (пользовательский элемент управления) из другой папки? В предпросмотре 3 я использовал для вызова RenderUserControl полный путь, но с обновлением до предпросмотра 5 это уже невозможно. Вместо этого мы получили метод RenderPartial, но он не предлагает мне ту функциональность, которую я ищу.

Борис Калленс
источник

Ответы:

443

Просто укажите путь к представлению с расширением файла.

Razor:

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

Движок ASP.NET:

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

Если это не ваша проблема, не могли бы вы включить свой код, который использовался для работы с RenderUserControl?

Поместье Илии
источник
19
Я хотел бы, чтобы мы могли просто сказать / AnotherFolder / Messages
Simon_Weaver
4
@Simon_Weaver Вы можете достичь этого. Одним из способов было бы изменить ViewEngine и переопределить его FindPartialViewметод чем-то вродеif(partialViewName.Contains"/")partialViewName="~/Views/"+partialViewName;
Арнис Лапса,
2
Работает и в движке MVC 3 Razor, но, как и выше, вам нужно расширение (.cshtml).
Крис
Если это не так, вам нужно указать путь "~ / Areas / TestArea / Views / Shared / _SomePartial.mobile.cshtml"
sandeep talabathula
Как вы относитесь к различным культурам этого частичного представления (например, ~ / Views / AnotherFolder / Messages.en.cshtml)?
jasdefer
29

В моем случае я использовал MvcMailer (https://github.com/smsohan/MvcMailer) и хотел получить доступ к частичному представлению из другой папки, которой нет в «Shared». Вышеуказанные решения не сработали, но с использованием относительного пути.

@Html.Partial("../MyViewFolder/Partials/_PartialView", Model.MyObject)
Аарон Шерман
источник
Аналогично @ Html.Partial ("../ Shared / _PartialView") для использования общей папки.
Кертис Яллоп
11
Я считаю, что это не работает без расширения .cshtml в конце.
Лука,
28

Если вы часто используете этот другой путь, вы можете исправить это навсегда без необходимости постоянно указывать путь. По умолчанию он проверяет частичные представления в папке View и в папке Shared. Но скажем, вы хотите добавить один.

Добавьте класс в вашу папку Models:

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

Затем в своем файле Global.asax.cs добавьте следующую строку:

ViewEngines.Engines.Add(new NewViewEngine());
Павел
источник
6
Конечно, я понимаю, что этот вопрос был задан давно. Мысль я бы добавил к этому для будущих Googlers и будущих Bingers.
Пол
- Не работает в .Net Core 2.2, так как RazorViewEngine.PartialViewLocationFormats не существует.
Демиан Берисфорд-Мейнард
7

Для пользовательского элемента управления с именем myPartial.ascx, расположенного в папке Views / Account, напишите так:

<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>
Rahatur
источник
5

Я создал обходной путь, который, кажется, работает довольно хорошо. Я обнаружил необходимость переключиться в контекст другого контроллера для поиска имени действия, просмотра представления и т. Д. Чтобы реализовать это, я создал новый метод расширения для HtmlHelper:

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

ControllerContextRegion определяется как:

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

То, как это используется в представлении, выглядит следующим образом:

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

Это может привести к нежелательным побочным эффектам, если ваш код требует, чтобы controllerкомпонент маршрута не изменился, но в нашем коде пока что нет никаких отрицательных моментов для этого подхода.

Иаков
источник
4

VirtualPathProviderViewEngine, на котором основан WebFormsViewEngine, должен поддерживать символы «~» и «/» в начале пути, поэтому приведенные выше примеры должны работать.

Я заметил, что ваши примеры используют путь "~ / Account / myPartial.ascx", но вы упомянули, что ваш пользовательский элемент управления находится в папке Views / Account. Ты пробовала

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

или это просто опечатка в твоем вопросе?

Эндрю Стэнтон-Медсестра
источник
3

Для читателей, использующих ASP.NET Core 2.1 или новее и желающих использовать синтаксис Partial Tag Helper , попробуйте следующее:

<partial name="~/Views/Folder/_PartialName.cshtml" />

Тильда (~) является необязательной.

Информация на https://docs.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-3.1#partial-tag-helper также полезна.

Феофил
источник
0

ты должен попробовать это

~/Views/Shared/parts/UMFview.ascx

поместите ~/Views/перед вашим кодом

Мунир
источник
0

Создайте пользовательский механизм просмотра и создайте метод, который возвращает ViewEngineResult. В этом примере вы просто перезаписываете _options.ViewLocationFormatsи добавляете каталог вашей папки:

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

Пример: https://github.com/AspNetMonsters/pugzor

Демиан Берисфорд-Мейнард
источник
-5

Попробуйте использовать RenderAction("myPartial","Account");

Шива Кандарадж
источник
3
Пожалуйста, прочитайте вопрос, поскольку пользователь спрашивает о просмотре в другой папке, где находится папка в вашем коде?
Памма