Resiliency to alternate view when partial view not found?

I have an MVC application that uses dynamic business objects that inherit from the parent type of an object. For example, a base class Clientcan have two subclasses of Vendorand ServiceProvider, and all of them are handled by the same controller. I have a partial view that I load on the right side of the page when viewing client details called _Aside.cshtml. When I download the client, I try to search for a specific version first and cannot load the general one. Below is the code code.

@try
{
    @Html.Partial("_" + Model.Type.TypeName + "Aside")
}
catch (InvalidOperationException ex)
{
    @Html.Partial("_Aside")
}

The TypeName property will contain the word "Provider" or "ServiceProvider" in it.

Now this works fine, but the problem is that I only want it to fail, if the view is not found, it also fails when there is an actual InvalidOperationExceptionone deduced by the partial view (usually the result of a child action it can call). I thought about checking with Exception.Message, but it seems a bit hacky. Is there any other way to get the desired result without checking the property Messageor is this my only option at this point?

ex.Message = "The partial view '_ServiceProviderAside' was not found or no view
              engine supports the searched locations. The following locations were
              searched: (... etc)"

The UPDATE . This is a class with extension methods that I have in my project based on Jack's answer, as well as Chao's suggestion.

//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 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)
+5
4

FindPartialView, , . - ():

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

FindPartialView ASP MVC 3

+1

, , . , - templatename_scripts templatename_styles.

, .

public static class OptionalPartialExtensions
{
    public static MvcHtmlString OptionalPartial(this HtmlHelper helper, string viewName)
    {
        return PartialExists(helper, viewName) ? helper.Partial(viewName) : MvcHtmlString.Empty;
    }

    public static MvcHtmlString OptionalPartial(this HtmlHelper helper, string viewName, string fallbackViewName)
    {
        return helper.Partial(PartialExists(helper, viewName) ? viewName : fallbackViewName);
    }

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

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

, , , RenderPartials .

+5

. . , ( ):

:

public static string FindPartial(this HtmlHelper html, string typeName)
{
    // If you wanted to keep it in the view, you could move this concatenation out:
    string viewName = "_" + typeName + "Aside";

    ViewEngineResult result = ViewEngines.Engines.FindPartialView(html.ViewContext, viewName);
    if (result.View != null)
        return viewName;

    return "_Aside";
}

:

@Html.Partial(Html.FindPartial(Model.Type.TypeName))

:

@Html.Partial(Html.FindPartial(Model.Type.TypeName), Model)
+3

null viewName null fallbackViewName ( OP):

public static MvcHtmlString OptionalPartial(this HtmlHelper helper, string viewName, string fallbackViewName, object model)
{
    string partialToRender = null;
    if (viewName != null && PartialExists(helper, viewName))
    {
        partialToRender = viewName;
    }
    else if (fallbackViewName != null && PartialExists(helper, fallbackViewName)) 
    {
        partialToRender = fallbackViewName;
    }
    if (partialToRender != null)
    {
        return helper.Partial(partialToRender, model);
    }
    else
    {
        return MvcHtmlString.Empty;
    }
}

OP ( ), .

0

All Articles