親オブジェクト タイプから継承された動的ビジネス オブジェクトを使用する MVC アプリがあります。たとえば、基本クラスにClient
は と という 2 つのサブクラスがVendor
ありServiceProvider
、これらはすべて同じコントローラーによって処理されます。と呼ばれるクライアントの詳細を表示するときに、ページの右側にロードする部分的なビューがあります_Aside.cshtml
。クライアントをロードするとき、最初に特定の 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);
}
}
UPDATE : ASP.NET Core MVC を使用している場合はPartialExists()
、これら 3 つのメソッドのメソッドを交換し、他のメソッドのHtmlHelper
forの使用法をすべて変更しIHtmlHelper
てください。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)