5

親オブジェクト タイプから継承された動的ビジネス オブジェクトを使用する 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 つのメソッドのメソッドを交換し、他のメソッドのHtmlHelperforの使用法をすべて変更し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)
4

4 に答える 4

1

FindPartialView メソッドを試して、ビューが存在するかどうかを確認できます。これらの行に沿った何かが機能する可能性があります(テストされていません):

public bool DoesViewExist(string name)
 {
     string viewName = "_" + Model.Type.TypeName + "Aside";
     ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName , null);
     return (viewResult.View != null);
 }

ASP MVC 3 の FindPartialView メソッドに関する情報

于 2013-02-22T19:06:49.567 に答える