从不同文件夹渲染部分(不共享)

发布于 2024-07-07 13:50:57 字数 133 浏览 13 评论 0原文

如何让视图从不同的文件夹渲染部分(用户控件)? 在预览版 3 中,我曾经使用完整路径调用 RenderUserControl,但升级到预览版 5 后,这不再可能了。 相反,我们得到了 RenderPartial 方法,但它没有提供我正在寻找的功能。

How can I have a view render a partial (user control) from a different folder?
With preview 3 I used to call RenderUserControl with the complete path, but whith upgrading to preview 5 this is not possible anymore.
Instead we got the RenderPartial method, but it's not offering me the functionality I'm looking for.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

不必了 2024-07-14 13:50:57

只需包含视图的路径以及文件扩展名即可。

Razor:

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

ASP.NET 引擎:

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

如果这不是您的问题,您能否包含用于与 RenderUserControl 一起使用的代码?

Just include the path to the view, with the file extension.

Razor:

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

ASP.NET engine:

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

If that isn't your issue, could you please include your code that used to work with the RenderUserControl?

美胚控场 2024-07-14 13:50:57

就我而言,我使用的是 MvcMailer (https://github.com/smsohan/MvcMailer),并且想要从另一个文件夹访问部分视图,该文件夹不在“共享”中。 上面的解决方案不起作用,但使用相对路径却可以。

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

In my case I was using MvcMailer (https://github.com/smsohan/MvcMailer) and wanted to access a partial view from another folder, that wasn't in "Shared." The above solutions didn't work, but using a relative path did.

@Html.Partial("../MyViewFolder/Partials/_PartialView", Model.MyObject)
迷途知返 2024-07-14 13:50:57

如果您经常使用其他路径,则可以永久修复此问题,而无需始终指定路径。 默认情况下,它会检查“视图”文件夹和“共享”文件夹中的部分视图。 但假设您想添加一个。

将类添加到 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());

If you are using this other path a lot of the time you can fix this permanently without having to specify the path all of the time. By default, it is checking for partial views in the View folder and in the Shared folder. But say you want to add one.

Add a class to your Models folder:

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

Then in your Global.asax.cs file, add the following line:

ViewEngines.Engines.Add(new NewViewEngine());
枫以 2024-07-14 13:50:57

对于使用 ASP.NET Core 2.1 或更高版本并希望使用 部分标记帮助程序 语法,请尝试以下操作:

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

波形符 (~) 是可选的。

信息位于 https://learn.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-3.1#partial-tag-helper 也很有帮助。

For readers using ASP.NET Core 2.1 or later and wanting to use Partial Tag Helper syntax, try this:

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

The tilde (~) is optional.

The information at https://learn.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-3.1#partial-tag-helper is helpful too.

抚笙 2024-07-14 13:50:57

对于位于 Views/Account 文件夹中名为 myPartial.ascx 的用户控件,请像这样编写:

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

For a user control named myPartial.ascx located at Views/Account folder write like this:

<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>
天煞孤星 2024-07-14 13:50:57

我创建了一个似乎运行良好的解决方法。 我发现需要切换到不同控制器的上下文以进行操作名称查找、视图查找等。为了实现这一点,我为 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 路由组件不更改,则可能会产生不需要的副作用,但到目前为止在我们的代码中,这种方法似乎没有任何负面影响。

I've created a workaround that seems to be working pretty well. I found the need to switch to the context of a different controller for action name lookup, view lookup, etc. To implement this, I created a new extension method for HtmlHelper:

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

ControllerContextRegion is defined as:

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

The way this is used within a view is as follows:

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

There may be unwanted side effects for this if your code requires the controller route component to not change, but in our code so far, there doesn't seem to be any negatives to this approach.

不甘平庸 2024-07-14 13:50:57

WebFormsViewEngine 所基于的 VirtualPathProviderViewEngine 应该支持路径前面的“~”和“/”字符,因此上面的示例应该可以工作。

我注意到您的示例使用路径“~/Account/myPartial.ascx”,但您提到您的用户控件位于 Views/Account 文件夹中。 你有没有尝试过

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

或者这只是您问题中的拼写错误?

The VirtualPathProviderViewEngine, on which the WebFormsViewEngine is based, is supposed to support the "~" and "/" characters at the front of the path so your examples above should work.

I noticed your examples use the path "~/Account/myPartial.ascx", but you mentioned that your user control is in the Views/Account folder. Have you tried

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

or is that just a typo in your question?

美煞众生 2024-07-14 13:50:57

您应该尝试将

~/Views/Shared/parts/UMFview.ascx

~/Views/ 放置在代码之前

you should try this

~/Views/Shared/parts/UMFview.ascx

place the ~/Views/ before your code

橪书 2024-07-14 13:50:57

创建自定义视图引擎并具有返回 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

Create a Custom View Engine and have a method that returns a ViewEngineResult
In this example you just overwrite the _options.ViewLocationFormats and add your folder directory
:

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

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

寒尘 2024-07-14 13:50:57

尝试使用 RenderAction("myPartial","Account");

Try using RenderAction("myPartial","Account");

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文