I found a solution long ago and forgot to post back here... I can't post everything I did, but the basic idea is to add a property to the ISettings
interface like:
public interface ISettings
{
string Name { get; }
string EditorTemplatePath { get; }
}
You then need to override this in each class. For example:
public class SettingsA : ISettings
{
public string Name { get { return "Example A"; } }
public string EditorTemplatePath
{
get{ return "~/Views/Shared/EditorTemplates/SettingsA.cshtml"; }
}
public string CustomAttributeA1 { get; set; }
public string CustomAttributeA2 { get; set; }
}
public class SettingsB : ISettings
{
public string Name { get { return "Example B"; } }
public string EditorTemplatePath
{
get{ return "~/Views/Shared/EditorTemplates/SettingsB.cshtml"; }
}
public string CustomAttributeB1 { get; set; }
public string CustomAttributeB2 { get; set; }
}
And of course you need to implement your own logic in a controller somewhere to return the custom HTML. For me, I use AJAX and do something like this:
[Route("get-editor-ui/{type}")]
public ActionResult GetEditorUI(string type)
{
var model = // logic to get the model from "type" argument
if (model == null)
{
return HttpNotFound();
}
string content = RenderRazorPartialViewToString(model.EditorTemplatePath, model);
return Json(new { Content = content }, JsonRequestBehavior.AllowGet);
}
FYI, RenderRazorPartialViewToString
is in my base controller and is defined as follows:
public string RenderRazorPartialViewToString(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = System.Web.Mvc.ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}