diff --git a/Disco.Services/Disco.Services.csproj b/Disco.Services/Disco.Services.csproj index 10a4582f..915334e7 100644 --- a/Disco.Services/Disco.Services.csproj +++ b/Disco.Services/Disco.Services.csproj @@ -178,6 +178,7 @@ + @@ -224,7 +225,7 @@ - + diff --git a/Disco.Services/Plugins/Features/UIExtension/UIExtensionFeature.cs b/Disco.Services/Plugins/Features/UIExtension/UIExtensionFeature.cs index 77dfb1b9..787695d0 100644 --- a/Disco.Services/Plugins/Features/UIExtension/UIExtensionFeature.cs +++ b/Disco.Services/Plugins/Features/UIExtension/UIExtensionFeature.cs @@ -13,26 +13,26 @@ namespace Disco.Services.Plugins.Features.UIExtension public abstract class UIExtensionFeature : PluginFeature where UIModel : BaseUIModel { public ControllerContext Context { get; set; } + private Lazy plugin; + protected WebHelper Plugin + { + get + { + return plugin.Value; + } + } + public UIExtensionFeature() + { + this.plugin = new Lazy(new Func(() => { + if (this.Context == null) + throw new InvalidOperationException("The Context property is not initialized"); + + return new WebHelper(this.Context.HttpContext, this.Manifest.PluginManifest); + })); + } public abstract UIExtensionResult ExecuteAction(ControllerContext context, UIModel model); - #region Bundles - public void IncludeStyleSheet(string Resource) - { - if (this.Context == null) - throw new NullReferenceException("This method can only be called when a Context is available"); - - this.Context.HttpContext.IncludeStyleSheetResource(Resource, this.Manifest.PluginManifest); - } - public void IncludeScript(string Resource) - { - if (this.Context == null) - throw new NullReferenceException("This method can only be called when a Context is available"); - - this.Context.HttpContext.IncludeScriptResource(Resource, this.Manifest.PluginManifest); - } - #endregion - #region ActionResults protected LiteralResult Literal(string Content) diff --git a/Disco.Services/Plugins/PluginManifest.cs b/Disco.Services/Plugins/PluginManifest.cs index e4c54eac..e536e01d 100644 --- a/Disco.Services/Plugins/PluginManifest.cs +++ b/Disco.Services/Plugins/PluginManifest.cs @@ -457,6 +457,17 @@ namespace Disco.Services.Plugins return string.Format("/Plugin/{0}", HttpUtility.UrlEncode(this.Id)); } } + public string WebActionUrl(string Action) + { + if (!HasWebHandler) + throw new NotSupportedException("This plugin doesn't have a web handler"); + + var url = UrlHelper.GenerateUrl("Plugin", null, null, + new RouteValueDictionary(new Dictionary() { { "PluginId", this.Id }, { "PluginAction", Action } }), + RouteTable.Routes, HttpContext.Current.Request.RequestContext, false); + + return url; + } public Tuple WebResourcePath(string Resource) { diff --git a/Disco.Services/Plugins/PluginWebHandler.cs b/Disco.Services/Plugins/PluginWebHandler.cs index e2ee5e75..199d5bbb 100644 --- a/Disco.Services/Plugins/PluginWebHandler.cs +++ b/Disco.Services/Plugins/PluginWebHandler.cs @@ -17,6 +17,19 @@ namespace Disco.Services.Plugins public PluginManifest Manifest { get; set; } public Controller HostController { get; set; } protected DiscoDataContext Database; + private Lazy plugin; + protected WebHelper Plugin + { + get + { + return plugin.Value; + } + } + + public PluginWebHandler() + { + this.plugin = new Lazy(new Func(() => new WebHelper(this.HostController.HttpContext, this.Manifest))); + } public void OnActionExecuting() { @@ -70,19 +83,6 @@ namespace Disco.Services.Plugins #endregion - #region Bundles - - public void IncludeStyleSheet(string Resource) - { - this.HostController.HttpContext.IncludeStyleSheetResource(Resource, this.Manifest); - } - public void IncludeScript(string Resource) - { - this.HostController.HttpContext.IncludeScriptResource(Resource, this.Manifest); - } - - #endregion - #region Action Results #region Compiled View @@ -124,7 +124,7 @@ namespace Disco.Services.Plugins { return this.CompiledView(); } - + [Obsolete("Use Generic Methods")] public ActionResult CompiledView(Type CompiledViewType, object Model, bool UseDiscoLayout) { diff --git a/Disco.Services/Plugins/PluginWebViewPage.cs b/Disco.Services/Plugins/PluginWebViewPage.cs index de11c634..e024c070 100644 --- a/Disco.Services/Plugins/PluginWebViewPage.cs +++ b/Disco.Services/Plugins/PluginWebViewPage.cs @@ -8,14 +8,14 @@ namespace Disco.Services.Plugins { public abstract class PluginWebViewPage : Disco.Services.Web.WebViewPage { - public WebHelper Plugin { get; private set; } + public WebPageHelper Plugin { get; private set; } public PluginWebViewPage() { var self = this.GetType(); var manifest = Plugins.GetPlugin(self.Assembly); - this.Plugin = new WebHelper(this, manifest); + this.Plugin = new WebPageHelper(this, manifest); } } } diff --git a/Disco.Services/Plugins/WebHelper.cs b/Disco.Services/Plugins/WebHelper.cs index 201e376d..fe10301c 100644 --- a/Disco.Services/Plugins/WebHelper.cs +++ b/Disco.Services/Plugins/WebHelper.cs @@ -8,117 +8,30 @@ using System.Text; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; -using System.Web.Mvc.Html; using System.Web.Routing; -using System.Web.WebPages; namespace Disco.Services.Plugins { - public class WebHelper + public class WebHelper { - private WebViewPage ViewPage { get; set; } + protected HttpContextBase Context { get; set; } public PluginManifest Manifest { get; private set; } - public WebHelper(WebViewPage ViewPage, PluginManifest manifest) + public WebHelper(HttpContextBase Context, PluginManifest Manifest) { - this.ViewPage = ViewPage; - this.Manifest = manifest; + this.Context = Context; + this.Manifest = Manifest; } - #region Html Helpers - - #region Form Helpers - public MvcForm BeginForm(string Action, FormMethod Method, bool MultipartEncoding, IDictionary HtmlAttributes) - { - if (string.IsNullOrEmpty(Action)) - throw new ArgumentNullException("PluginAction"); - - var url = ActionUrl(Action); - - return BeginForm_Helper(url.ToString(), Method, MultipartEncoding, HtmlAttributes); - } - public MvcForm BeginForm(string Action, FormMethod Method, bool MultipartEncoding) - { - return BeginForm(Action, Method, MultipartEncoding, null); - } - public MvcForm BeginForm(string Action, FormMethod Method, IDictionary HtmlAttributes) - { - return BeginForm(Action, Method, false, HtmlAttributes); - } - public MvcForm BeginForm(string Action, FormMethod Method) - { - return BeginForm(Action, Method, false, null); - } - public MvcForm BeginForm(string Action) - { - return BeginForm(Action, FormMethod.Get, false, null); - } - private MvcForm BeginForm_Helper(string FormAction, FormMethod Method, bool MultipartEncoding, IDictionary HtmlAttributes) - { - TagBuilder builder = new TagBuilder("form"); - builder.MergeAttributes(HtmlAttributes); - if (MultipartEncoding) - builder.MergeAttribute("enctype", "multipart/form-data"); - builder.MergeAttribute("action", FormAction); - builder.MergeAttribute("method", HtmlHelper.GetFormMethodString(Method), true); - - bool useClientValidation = ViewPage.ViewContext.ClientValidationEnabled && !ViewPage.ViewContext.UnobtrusiveJavaScriptEnabled; - if (useClientValidation) - { - object lastFormNumber = ViewPage.ViewContext.HttpContext.Items["DiscoPluginLastFormNum"]; - int num = (lastFormNumber != null) ? (((int)lastFormNumber) + 1) : 1000; - ViewPage.ViewContext.HttpContext.Items["DiscoPluginLastFormNum"] = num; - - builder.GenerateId(string.Format(CultureInfo.InvariantCulture, "form{0}", new object[] { num })); - } - ViewPage.ViewContext.Writer.Write(builder.ToString(TagRenderMode.StartTag)); - MvcForm form = new MvcForm(ViewPage.ViewContext); - if (useClientValidation) - { - ViewPage.ViewContext.FormContext.FormId = builder.Attributes["id"]; - } - return form; - } - #endregion - public void IncludeStyleSheet(string Resource) { - ViewPage.Context.IncludeStyleSheetResource(Resource, this.Manifest); + Context.IncludeStyleSheetResource(Resource, this.Manifest); } public void IncludeJavaScript(string Resource) { - ViewPage.Context.IncludeScriptResource(Resource, this.Manifest); + Context.IncludeScriptResource(Resource, this.Manifest); } - public HtmlString PartialCompiled(object Model) where ViewType : WebViewPage - { - using (System.IO.StringWriter writer = new StringWriter(CultureInfo.CurrentCulture)) - { - RenderPartialCompiled(writer, Model); - - return new HtmlString(writer.ToString()); - } - } - public HtmlString PartialCompiled() where ViewType : WebViewPage - { - return PartialCompiled(null); - } - private void RenderPartialCompiled(TextWriter Writer, object Model) - { - if (Writer == null) - throw new ArgumentNullException("Writer"); - WebViewPage page = Activator.CreateInstance(typeof(ViewType)) as WebViewPage; - if (page == null) - throw new InvalidOperationException("Invalid View Type"); - page.ViewContext = ViewPage.ViewContext; - page.ViewData = new ViewDataDictionary(Model); - page.InitHelpers(); - HttpContextBase httpContext = ViewPage.ViewContext.HttpContext; - page.ExecutePageHierarchy(new WebPageContext(httpContext, null, Model), Writer, null); - } - - #endregion - #region Urls public HtmlString ConfigurationUrl() @@ -130,7 +43,7 @@ namespace Disco.Services.Plugins public HtmlString ActionUrl(string Action) { - var url = GenerateUrl("Plugin", new Dictionary() { { "PluginId", Manifest.Id }, { "PluginAction", Action } }); + var url = Manifest.WebActionUrl(Action); return new HtmlString(url); } @@ -155,7 +68,7 @@ namespace Disco.Services.Plugins #region Helpers private string GenerateUrl(string RouteName, RouteValueDictionary RouteValues) { - return UrlHelper.GenerateUrl(RouteName, null, null, RouteValues, RouteTable.Routes, ViewPage.Request.RequestContext, false); + return UrlHelper.GenerateUrl(RouteName, null, null, RouteValues, RouteTable.Routes, Context.Request.RequestContext, false); } private string GenerateUrl(string RouteName, IDictionary RouteValues) { diff --git a/Disco.Services/Plugins/WebPageHelper.cs b/Disco.Services/Plugins/WebPageHelper.cs new file mode 100644 index 00000000..2ac6ba04 --- /dev/null +++ b/Disco.Services/Plugins/WebPageHelper.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using System.Web.Mvc; +using System.Web.Mvc.Html; +using System.Web.WebPages; + +namespace Disco.Services.Plugins +{ + public class WebPageHelper : WebHelper + { + protected WebViewPage ViewPage { get; set; } + + public WebPageHelper(WebViewPage ViewPage, PluginManifest Manifest) + : base(ViewPage.Context, Manifest) + { + this.ViewPage = ViewPage; + } + + #region Html Helpers + + #region Form Helpers + public MvcForm BeginForm(string Action, FormMethod Method, bool MultipartEncoding, IDictionary HtmlAttributes) + { + if (string.IsNullOrEmpty(Action)) + throw new ArgumentNullException("PluginAction"); + + var url = ActionUrl(Action); + + return BeginForm_Helper(url.ToString(), Method, MultipartEncoding, HtmlAttributes); + } + public MvcForm BeginForm(string Action, FormMethod Method, bool MultipartEncoding) + { + return BeginForm(Action, Method, MultipartEncoding, null); + } + public MvcForm BeginForm(string Action, FormMethod Method, IDictionary HtmlAttributes) + { + return BeginForm(Action, Method, false, HtmlAttributes); + } + public MvcForm BeginForm(string Action, FormMethod Method) + { + return BeginForm(Action, Method, false, null); + } + public MvcForm BeginForm(string Action) + { + return BeginForm(Action, FormMethod.Get, false, null); + } + private MvcForm BeginForm_Helper(string FormAction, FormMethod Method, bool MultipartEncoding, IDictionary HtmlAttributes) + { + TagBuilder builder = new TagBuilder("form"); + builder.MergeAttributes(HtmlAttributes); + if (MultipartEncoding) + builder.MergeAttribute("enctype", "multipart/form-data"); + builder.MergeAttribute("action", FormAction); + builder.MergeAttribute("method", HtmlHelper.GetFormMethodString(Method), true); + + bool useClientValidation = ViewPage.ViewContext.ClientValidationEnabled && !ViewPage.ViewContext.UnobtrusiveJavaScriptEnabled; + if (useClientValidation) + { + object lastFormNumber = ViewPage.ViewContext.HttpContext.Items["DiscoPluginLastFormNum"]; + int num = (lastFormNumber != null) ? (((int)lastFormNumber) + 1) : 1000; + ViewPage.ViewContext.HttpContext.Items["DiscoPluginLastFormNum"] = num; + + builder.GenerateId(string.Format(CultureInfo.InvariantCulture, "form{0}", new object[] { num })); + } + ViewPage.ViewContext.Writer.Write(builder.ToString(TagRenderMode.StartTag)); + MvcForm form = new MvcForm(ViewPage.ViewContext); + if (useClientValidation) + { + ViewPage.ViewContext.FormContext.FormId = builder.Attributes["id"]; + } + return form; + } + #endregion + + public HtmlString PartialCompiled(object Model) where ViewType : WebViewPage + { + using (System.IO.StringWriter writer = new StringWriter(CultureInfo.CurrentCulture)) + { + RenderPartialCompiled(writer, Model); + + return new HtmlString(writer.ToString()); + } + } + public HtmlString PartialCompiled() where ViewType : WebViewPage + { + return PartialCompiled(null); + } + private void RenderPartialCompiled(TextWriter Writer, object Model) + { + if (Writer == null) + throw new ArgumentNullException("Writer"); + WebViewPage page = Activator.CreateInstance(typeof(ViewType)) as WebViewPage; + if (page == null) + throw new InvalidOperationException("Invalid View Type"); + page.ViewContext = ViewPage.ViewContext; + page.ViewData = new ViewDataDictionary(Model); + page.InitHelpers(); + HttpContextBase httpContext = ViewPage.ViewContext.HttpContext; + page.ExecutePageHierarchy(new WebPageContext(httpContext, null, Model), Writer, null); + } + + #endregion + + } +}