У меня есть приложение MVC, которое использует динамические бизнес-объекты, которые наследуются от родительского типа объекта. Например, базовый класс Client
может иметь два подкласса, называемых Vendor
и ServiceProvider
, и все они обрабатываются одним и тем же контроллером. У меня есть частичный вид, который я загружаю с правой стороны страницы при просмотре деталей клиента под названием _Aside.cshtml
. Когда я загружаю клиента, я стараюсь сначала искать конкретную версию и не могу загрузить общий. Ниже приведен код.Отказ от альтернативного режима просмотра, когда частичный просмотр не найден?
@try
{
@Html.Partial("_" + Model.Type.TypeName + "Aside")
}
catch (InvalidOperationException ex)
{
@Html.Partial("_Aside")
}
Свойство TypeName будет содержать в нем слово «Поставщик» или «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)"
UPDATE: Это класс с методами расширения я в настоящее время в моем проекте основаны от ответа Джека, и предложения Чао, а также.
//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 MVC сердечника, поменять местами PartialExists()
методы этих трех методов, и изменить все использований HtmlHelper
для IHtmlHelper
в других методах. Пропустить это, если вы не используете ASP.NET Сердечник
//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)
Это должно сработать на самом деле, я был слишком сфокусирован на обработке ошибки, которую я не думал искать, используя открытые методы механизма просмотра. Я изменил вопрос, чтобы включить код, который я придумал. –