1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| public static class ComposeViewHelper
{
// Convention : Pour ajouter du contenu provenant d'une vue d'un module, la vue parent doit contenir un Tag <ModulePart></ModulePart> dans son HTML.
// Ce tag sera alors remplacé au rendu par le contenu de la vue (du module) que l'on souhaite intégré à la vue commune (projet web commun)
public static readonly string ModuleHtmlTag = "<ModulePart></ModulePart>";
// Convention de nommage : Une vue enfant utilisée pour la composition doit avoir son nom suffixé par la chaine "Part" ==> ViewNamePart
public static readonly string ModuleViewSuffix = "Part";
public static ActionResult MergeViews(ControllerContext controllerContext, string parentViewName, string childViewName)
{
var parentViewSourceCode = GetViewToString(controllerContext, parentViewName);
var childViewSourceCode = GetViewToString(controllerContext, childViewName, parentViewName);
return MergeViews(parentViewSourceCode, childViewSourceCode);
}
public static ActionResult MergeViews(ControllerContext controllerContext, ViewResultBase parentViewResult, ViewResultBase childViewResult)
{
var parentViewSourceCode = GetViewToString(controllerContext, parentViewResult, isChildView: false);
var childViewSourceCode = GetViewToString(controllerContext, childViewResult, isChildView: true);
return MergeViews(parentViewSourceCode, childViewSourceCode);
}
public static ActionResult MergeViews(ControllerContext controllerContext, ViewResultBase parentViewResult, string childViewName)
{
var parentViewSourceCode = GetViewToString(controllerContext, parentViewResult, isChildView: false);
var childViewSourceCode = GetViewToString(controllerContext, childViewName, parentViewName: parentViewResult.ViewName);
return MergeViews(parentViewSourceCode, childViewSourceCode);
}
public static string GetViewToString(ControllerContext controllerContext, ViewResultBase viewResult, bool isChildView)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (viewResult == null)
throw new ArgumentNullException("viewResult");
using (StringWriter viewStringWriter = new StringWriter())
{
viewResult.View = GetView(controllerContext, viewResult, isChildView);
var viewContext = new ViewContext(controllerContext, viewResult.View, viewResult.ViewData, viewResult.TempData, viewStringWriter);
viewResult.View.Render(viewContext, viewStringWriter);
ViewEngines.Engines.Single().ReleaseView(controllerContext, viewResult.View);
return viewStringWriter.GetStringBuilder().ToString();
}
}
/// <summary>
/// Récupère le code source HTML d'une vue MVC
/// </summary>
/// <param name="controllerContext"></param>
/// <param name="viewName"></param>
/// <param name="parentViewName">
/// Nom de la vue parent permettant de récupérer son emplacement et déterminer où la vue enfant doit se situer.
/// Exemple : Si le nom de la vue parent est : DisplayTemplates/VueParent.cshtml, la vue enfant sera DisplayTemplates/VueEnfant.cshtml
/// </param>
/// <returns>code source HTML sous forme de chaine de caractères de la vue spécifiée en paramètre</returns>
public static string GetViewToString(ControllerContext controllerContext, string viewName, string parentViewName = "")
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (string.IsNullOrEmpty(viewName))
throw new ArgumentNullException("viewName");
using (StringWriter viewStringWriter = new StringWriter())
{
if (!string.IsNullOrEmpty(parentViewName))
viewName = Path.Combine(parentViewName.Replace(Path.GetFileName(parentViewName), ""), viewName);
var viewEngineResult = ViewEngines.Engines.FindView(controllerContext, viewName, masterName: "");
var viewContext = new ViewContext(controllerContext, viewEngineResult.View, controllerContext.Controller.ViewData, controllerContext.Controller.TempData, viewStringWriter);
viewEngineResult.View.Render(viewContext, viewStringWriter);
viewEngineResult.ViewEngine.ReleaseView(controllerContext, viewEngineResult.View);
return viewStringWriter.GetStringBuilder().ToString();
}
}
public static ActionResult MergeViews(string parentViewSourceCode, string childViewSourceCode)
{
return new ContentResult { Content = parentViewSourceCode.Replace(ModuleHtmlTag, childViewSourceCode) };
}
private static IView GetView(ControllerContext controllerContext, ViewResultBase viewResult, bool isChildView)
{
if (viewResult.View != null)
return viewResult.View;
if (string.IsNullOrEmpty(viewResult.ViewName))
viewResult.ViewName = controllerContext.RouteData.GetRequiredString("action");
if (isChildView)
viewResult.ViewName += ModuleViewSuffix;
if (viewResult.GetType().IsGenericType)
{
if (viewResult.GetType().GetGenericTypeDefinition() == typeof(DisplayViewResult<>))
viewResult.ViewName = (viewResult as TemplatedViewResult).BuildViewPath(DataBoundControlMode.ReadOnly, viewResult.ViewName);
else if (viewResult.GetType().GetGenericTypeDefinition() == typeof(EditorViewResult<>))
viewResult.ViewName = (viewResult as TemplatedViewResult).BuildViewPath(DataBoundControlMode.Edit, viewResult.ViewName);
}
ViewEngineResult viewEngineResult = ViewEngines.Engines.FindView(controllerContext, viewResult.ViewName, masterName: "");
return viewEngineResult.View;
}
} |
Partager