我有一个 MVC 应用程序,它使用从父对象类型继承的动态业务对象。例如,基类Client
可能有两个名为Vendor
and的子类ServiceProvider
,它们都由同一个控制器处理。我有一个局部视图,当查看名为_Aside.cshtml
. 当我加载客户端时,我尝试先查找特定的 Aside,然后加载通用的 Aside 失败。下面是代码的样子。
@try
{
@Html.Partial("_" + Model.Type.TypeName + "Aside")
}
catch (InvalidOperationException ex)
{
@Html.Partial("_Aside")
}
TypeName 属性将包含单词“Vendor”或“ServiceProvider”。
现在这工作正常,但问题是我只希望它在未找到视图时进行故障转移,当InvalidOperationException
部分视图实际抛出时(通常是它可能调用的子操作的结果),它也会进行故障转移。我曾考虑过检查,Exception.Message
但这似乎有点骇人听闻。有没有其他方法可以在无需检查Message
属性的情况下获得所需的结果,或者这是我目前唯一的选择?
ex.Message = "The partial view '_ServiceProviderAside' was not found or no view
engine supports the searched locations. The following locations were
searched: (... etc)"
更新:根据 Jack 的回答和 Chao 的建议,这是我目前在项目中使用的具有扩展方法的类。
//For ASP.NET MVC
public static class ViewExtensionMethods
{
public static bool PartialExists(this HtmlHelper helper, string viewName)
{
if (string.IsNullOrEmpty(viewName)) throw new ArgumentNullException(viewName, "View name cannot be empty");
var view = ViewEngines.Engines.FindPartialView(helper.ViewContext, viewName);
return view.View != null;
}
public static bool PartialExists(this ControllerContext controllerContext, string viewName)
{
if (string.IsNullOrEmpty(viewName)) throw new ArgumentNullException(viewName, "View name cannot be empty");
var view = ViewEngines.Engines.FindPartialView(controllerContext, viewName);
return view.View != null;
}
public static MvcHtmlString OptionalPartial(this HtmlHelper helper, string viewName)
{
return PartialExists(helper, viewName) ? helper.Partial(viewName) : HtmlString.Empty;
}
public static MvcHtmlString OptionalPartial(this HtmlHelper helper, string viewName, string fallbackViewName)
{
return OptionalPartial(helper, viewName, fallbackViewName, null);
}
public static MvcHtmlString OptionalPartial(this HtmlHelper helper, string viewName, object model)
{
return PartialExists(helper, viewName) ? helper.Partial(viewName, model) : MvcHtmlString.Empty;
}
public static MvcHtmlString OptionalPartial(this HtmlHelper helper, string viewName, string fallbackViewName, object model)
{
return helper.Partial(PartialExists(helper, viewName) ? viewName : fallbackViewName, model);
}
public static void RenderOptionalPartial(this HtmlHelper helper, string viewName)
{
if (PartialExists(helper, viewName))
{
helper.RenderPartial(viewName);
}
}
public static void RenderOptionalPartial(this HtmlHelper helper, string viewName, string fallbackViewName)
{
helper.RenderPartial(PartialExists(helper, viewName) ? viewName : fallbackViewName);
}
}
更新:如果您碰巧使用的是 ASP.NET Core MVC,请交换PartialExists()
这三种方法的方法,并更改其他方法中HtmlHelper
forIHtmlHelper
的所有用法。如果您不使用 ASP.NET Core,请跳过此步骤
//For ASP.NET Core MVC
public static class ViewExtensionMethods
{
public static bool PartialExists(this IHtmlHelper helper, string viewName)
{
var viewEngine = helper.ViewContext.HttpContext.RequestServices.GetService<ICompositeViewEngine>();
if (string.IsNullOrEmpty(viewName)) throw new ArgumentNullException(viewName, "View name cannot be empty");
var view = viewEngine.FindView(helper.ViewContext, viewName, false);
return view.View != null;
}
public static bool PartialExists(this ControllerContext controllerContext, string viewName)
{
var viewEngine = controllerContext.HttpContext.RequestServices.GetService<ICompositeViewEngine>();
if (string.IsNullOrEmpty(viewName)) throw new ArgumentNullException(viewName, "View name cannot be empty");
var view = viewEngine.FindView(controllerContext, viewName, false);
return view.View != null;
}
public static bool PartialExists(this ViewContext viewContext, string viewName)
{
var viewEngine = viewContext.HttpContext.RequestServices.GetService<ICompositeViewEngine>();
if (string.IsNullOrEmpty(viewName)) throw new ArgumentNullException(viewName, "View name cannot be empty");
var view = viewEngine.FindView(viewContext, viewName, false);
return view.View != null;
}
}
在我看来...
@Html.OptionalPartial("_" + Model.Type.TypeName + "Aside", "_Aside")
//or
@Html.OptionalPartial("_" + Model.Type.TypeName + "Aside", "_Aside", Model.AsideViewModel)