Renderizar parcial de uma pasta diferente (não compartilhada)

256

Como posso ter uma exibição renderizada parcial (controle de usuário) de uma pasta diferente? Na pré-visualização 3, eu costumava chamar RenderUserControl com o caminho completo, mas com a atualização para a pré-visualização 5, isso não é mais possível. Em vez disso, obtivemos o método RenderPartial, mas ele não está me oferecendo a funcionalidade que estou procurando.

Boris Callens
fonte

Respostas:

443

Basta incluir o caminho para a visualização, com a extensão do arquivo.

Navalha:

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

Mecanismo do ASP.NET:

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

Se esse não é o seu problema, você poderia incluir seu código que funcionava com o RenderUserControl?

Elijah Manor
fonte
19
Eu gostaria que pudéssemos dizer / Outra Pasta / Mensagens
Simon_Weaver 13/03/2009
4
@ Simon_Weaver Você pode conseguir isso. Uma forma seria a de modificar ViewEngine e substituí-lo do FindPartialViewmétodo com algo comoif(partialViewName.Contains"/")partialViewName="~/Views/"+partialViewName;
Arnis Lapsa
2
Também funciona no mecanismo MVC 3 Razor, mas, como o acima, você precisa da extensão (.cshtml).
Chris
Se a sua sob diferentes que você precisa para dar caminho "~ / Áreas / TestArea / Views / Shared / _SomePartial.mobile.cshtml"
sandeep talabathula
Como você lida com diferentes culturas dessa exibição parcial (por exemplo, ~ / Views / AnotherFolder / Messages.en.cshtml)?
jasdefer
29

No meu caso, eu estava usando o MvcMailer (https://github.com/smsohan/MvcMailer) e queria acessar uma exibição parcial de outra pasta que não estivesse em "Compartilhado". As soluções acima não funcionaram, mas o uso de um caminho relativo funcionou.

@Html.Partial("../MyViewFolder/Partials/_PartialView", Model.MyObject)
Aaron Sherman
fonte
Da mesma forma, @ Html.Partial ("../ Shared / _PartialView") para usar a pasta compartilhada.
Curtis Yallop
11
Estou descobrindo que isso não funciona sem a extensão .cshtml no final.
Luke
28

Se você estiver usando esse outro caminho muitas vezes, poderá corrigi-lo permanentemente sem precisar especificar o caminho o tempo todo. Por padrão, está verificando vistas parciais na pasta Exibir e na pasta Compartilhada. Mas diga que você deseja adicionar um.

Adicione uma classe à sua pasta Modelos:

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

Em seguida, no seu arquivo Global.asax.cs, adicione a seguinte linha:

ViewEngines.Engines.Add(new NewViewEngine());
Paulo
fonte
6
É claro que sei que essa pergunta foi feita há muito tempo. Pensei em acrescentar isso a futuros Googlers e futuros Bingers.
Paul
- Não funcionará no .Net Core 2.2, pois o RazorViewEngine.PartialViewLocationFormats não existe.
Demian Berisford-Maynard
7

Para um controle de usuário chamado myPartial.ascx localizado na pasta Views / Account, escreva assim:

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

Eu criei uma solução alternativa que parece estar funcionando muito bem. Eu encontrei a necessidade de mudar para o contexto de um controlador diferente para pesquisar nomes de ações, visualizar pesquisas etc. Para implementar isso, criei um novo método de extensão para HtmlHelper:

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

ControllerContextRegion é definido como:

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

A maneira como isso é usado em uma visualização é a seguinte:

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

Pode haver efeitos colaterais indesejados para isso, se o seu código exigir que o controllercomponente de rota não seja alterado, mas em nosso código até agora, não parece haver nenhum negativo nessa abordagem.

Jacob
fonte
4

O VirtualPathProviderViewEngine, no qual o WebFormsViewEngine se baseia, deve suportar os caracteres "~" e "/" na frente do caminho, para que seus exemplos acima funcionem.

Notei que seus exemplos usam o caminho "~ / Account / myPartial.ascx", mas você mencionou que seu controle de usuário está na pasta Views / Account. Você tentou

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

ou isso é apenas um erro de digitação na sua pergunta?

Andrew Stanton-Nurse
fonte
0

você deveria tentar isso

~/Views/Shared/parts/UMFview.ascx

coloque o ~/Views/antes do seu código

mounir
fonte
0

Crie um Mecanismo de Visualização Personalizado e tenha um método que retorne um ViewEngineResult Neste exemplo, você apenas sobrescreve o _options.ViewLocationFormatsdiretório da pasta e adiciona-o:

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

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

Demian Berisford-Maynard
fonte
-5

Tente usar RenderAction("myPartial","Account");

Siva Kandaraj
fonte
3
Leia a pergunta, pois o usuário está perguntando sobre a exibição em uma pasta diferente, onde está a pasta no seu código?
Pamma