如何让视图呈现来自不同文件夹的部分(用户控件)?在预览版 3 中,我曾经使用完整路径调用 RenderUserControl,但升级到预览版 5 后,这不再可能了。相反,我们得到了 RenderPartial 方法,但它没有为我提供我正在寻找的功能。
10 回答
只需包含视图的路径和文件扩展名。
剃刀:
@Html.Partial("~/Views/AnotherFolder/Messages.cshtml", ViewData.Model.Successes)
ASP.NET 引擎:
<% Html.RenderPartial("~/Views/AnotherFolder/Messages.ascx", ViewData.Model.Successes); %>
如果这不是您的问题,能否请您包含您曾经与 RenderUserControl 一起使用的代码?
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)
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());
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://docs.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-3.1#partial-tag-helper is helpful too.
对于位于 Views/Account 文件夹中名为 myPartial.ascx 的用户控件,如下所示:
<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>
我创建了一个似乎运行良好的解决方法。我发现需要切换到不同控制器的上下文以进行操作名称查找、视图查找等。为了实现这一点,我创建了一个新的扩展方法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.
}
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.
WebFormsViewEngine 所基于的 VirtualPathProviderViewEngine 应该支持路径前面的“~”和“/”字符,因此您上面的示例应该可以工作。
我注意到您的示例使用路径“~/Account/myPartial.ascx”,但您提到您的用户控件位于 Views/Account 文件夹中。你有没有尝试过
<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>
或者这只是你问题中的一个错字?
你应该试试这个
~/Views/Shared/parts/UMFview.ascx
将代码放在~/Views/
您的代码之前
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);
}
尝试使用RenderAction("myPartial","Account");