Мне удалось реализовать (мою интерпретацию) совет, предоставленный @SoWeLie, довольно просто. Он включал в себя создание новой модели для размещения расширенного набора возможных свойств элемента управления и нового представления для каждого отдельного набора элементов управления (один для аудита и один для просмотра). Проблема с этим заключалась в том, что получившийся API представления был уродлив:
@Html.RenderAction("DrawControl", new { id = "ID" ... })
// Repeated for all of the overloads of DrawControl
и каждое действие контроллера содержало что-то вроде:
public ActionResult DrawControl(string id, ...)
{
// FieldControl being the name of my Model
var viewModel = new FieldControl() { ID = id, ... };
if (shouldRenderAudit)
return PartialView("AuditControl", viewModel);
else
return PartialView("ReviewControl", viewModel);
Я не мог понять, как заставить моего универсального помощника работать в этом сценарии, и, кроме того, я хотел убрать уменьшить очевидное дублирование кода, чтобы это быстро стало:
@functions {
public string DrawControl(string id, ...)
{
return Html.Render("DrawControl", new { id = "ID" });
}
// Repeated for all of the overloads of DrawControl
}
@DrawControl("ID", ...)
С тем же действием контроллера. Проблема с этим (игнорирование того факта, что представление вообще имело функции) заключалась в том, что блок @functions
необходимо было включать в любое представление, которое хотело получить выгоду от их использования (которое в настоящее время составляет только 2, но скоро будет достаточно всплывать до 5). и кто знает, что мой предшественник собирается с этим делать). Я быстро переработал код снова, на этот раз, чтобы вернуть помощников (обычно сохраняя представления, модель и изменения контроллера), и в итоге получил следующее:
Вид:
@(Html.DrawComplexControl<ProviderName>("id", ...))
@Html.DrawSimpleControl("id", ...)
Контроллер:
// One common action that is used to determine which control should be drawn
public ActionResult DrawControl(FieldControl model)
{
if (shouldRenderAudit)
return PartialView("AuditControl", model);
else
return PartialView("ReviewControl", model);
}
Помощник:
public static MvcHtmlString DrawControl(this HtmlHelper htmlHelper, string id, ...)
{
var model = new FieldControl() { ID = id, ... };
return htmlHelper.Action("DrawControl", model);
}
public static MvcHtmlString DrawSimpleControl(this HtmlHelper htmlHelper, string id, ...)
{
return DrawSimpleControl(htmlHelper, id, ...);
}
public static MvcHtmlString DrawSimpleControl(this HtmlHelper htmlHelper, string id, ...)
{
// Set some defaults to simplify the API
return DrawControl(htmlHelper, id, ...);
}
public static MvcHtmlString DrawComplexControl<T>(this HtmlHelper htmlHelper, string id, ...) where T : AbstractComplex, new()
{
// Build the required controls based on `T`
return DrawControl(htmlHelper, id, ...);
}
Конечно, было около полудюжины других итераций между показанными, чтобы помочь ситуации, и ни одна из них не сделала в той мере, в которой это необходимо. Я уверен, что улучшения еще не сделаны, но это то, что у меня есть.
Делая это таким способом, вы получаете очень простой API для использования без необходимости знать или заботиться о реализации, и он может удовлетворить все требования моего ранее существующего API с незначительными изменениями (в конце концов, по крайней мере, ). Я не уверен, что именно так и задумывался ответ, но он функциональный и обеспечивает необходимую простоту.
Надеюсь, мои головные боли помогут кому-то еще в будущем.