4cd57f4a90
Migrate all SignalR 1.x Persistent Connections to SignalR 2.x Hubs. Abstracts ScheduledTaskStatus with core interface and adds a Mock for optional status reporting. Noticeboards rewritten (with new theme) to be more resilient and accurate.
372 lines
18 KiB
C#
372 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Disco.Data.Repository;
|
|
using System.IO;
|
|
using System.Web.Mvc;
|
|
using System.Web.WebPages;
|
|
using System.Web.Routing;
|
|
using System.Web;
|
|
using System.Web.Mvc.Html;
|
|
using System.Globalization;
|
|
using Disco.Services.Web.Bundles;
|
|
|
|
namespace Disco.Services.Plugins
|
|
{
|
|
public static class PluginExtensions
|
|
{
|
|
#region Model Binding from Controller
|
|
public static bool TryUpdateModel<TModel>(this Controller controller, TModel model) where TModel : class
|
|
{
|
|
return controller.TryUpdateModel<TModel>(model, null, controller.ValueProvider);
|
|
}
|
|
public static bool TryUpdateModel<TModel>(this Controller controller, TModel model, IValueProvider valueProvider) where TModel : class
|
|
{
|
|
return controller.TryUpdateModel<TModel>(model, null, valueProvider);
|
|
}
|
|
public static bool TryUpdateModel<TModel>(this Controller controller, TModel model, string prefix) where TModel : class
|
|
{
|
|
return controller.TryUpdateModel<TModel>(model, prefix, controller.ValueProvider);
|
|
}
|
|
public static bool TryUpdateModel<TModel>(this Controller controller, TModel model, string prefix, IValueProvider valueProvider) where TModel : class
|
|
{
|
|
if (model == null)
|
|
throw new ArgumentNullException("model");
|
|
if (valueProvider == null)
|
|
throw new ArgumentNullException("valueProvider");
|
|
|
|
Predicate<string> predicate = propertyName => true;
|
|
IModelBinder binder = ModelBinders.Binders.GetBinder(typeof(TModel));
|
|
|
|
ModelBindingContext context2 = new ModelBindingContext
|
|
{
|
|
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(TModel)),
|
|
ModelName = prefix,
|
|
ModelState = controller.ModelState,
|
|
PropertyFilter = predicate,
|
|
ValueProvider = valueProvider
|
|
};
|
|
|
|
ModelBindingContext bindingContext = context2;
|
|
|
|
binder.BindModel(controller.ControllerContext, bindingContext);
|
|
|
|
return controller.ModelState.IsValid;
|
|
}
|
|
public static bool TryUpdateModel(this Controller controller, object model)
|
|
{
|
|
return controller.TryUpdateModel(model, null, controller.ValueProvider);
|
|
}
|
|
public static bool TryUpdateModel(this Controller controller, object model, IValueProvider valueProvider)
|
|
{
|
|
return controller.TryUpdateModel(model, null, valueProvider);
|
|
}
|
|
public static bool TryUpdateModel(this Controller controller, object model, string prefix)
|
|
{
|
|
return controller.TryUpdateModel(model, prefix, controller.ValueProvider);
|
|
}
|
|
public static bool TryUpdateModel(this Controller controller, object model, string prefix, IValueProvider valueProvider)
|
|
{
|
|
if (model == null)
|
|
throw new ArgumentNullException("model");
|
|
if (valueProvider == null)
|
|
throw new ArgumentNullException("valueProvider");
|
|
|
|
Predicate<string> predicate = propertyName => true;
|
|
IModelBinder binder = ModelBinders.Binders.GetBinder(model.GetType());
|
|
|
|
ModelBindingContext context2 = new ModelBindingContext
|
|
{
|
|
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()),
|
|
ModelName = prefix,
|
|
ModelState = controller.ModelState,
|
|
PropertyFilter = predicate,
|
|
ValueProvider = valueProvider
|
|
};
|
|
|
|
ModelBindingContext bindingContext = context2;
|
|
|
|
binder.BindModel(controller.ControllerContext, bindingContext);
|
|
|
|
return controller.ModelState.IsValid;
|
|
}
|
|
#endregion
|
|
|
|
#region Bundling
|
|
public static void IncludeStyleSheetResource(this HttpContextBase Context, string Resource, PluginManifest manifest)
|
|
{
|
|
var resourceUrl = manifest.WebResourceUrl(Resource);
|
|
|
|
var deferredBundles = Context.Items[BundleTable.UIExtensionCssKey] as List<string>;
|
|
if (deferredBundles == null)
|
|
{
|
|
deferredBundles = new List<string>();
|
|
HttpContext.Current.Items[BundleTable.UIExtensionCssKey] = deferredBundles;
|
|
}
|
|
if (!deferredBundles.Contains(resourceUrl))
|
|
deferredBundles.Add(resourceUrl);
|
|
}
|
|
public static void IncludeScriptResource(this HttpContextBase Context, string Resource, PluginManifest manifest)
|
|
{
|
|
var resourcePath = manifest.WebResourceUrl(Resource);
|
|
|
|
var deferredBundles = Context.Items[BundleTable.UIExtensionScriptsKey] as List<string>;
|
|
if (deferredBundles == null)
|
|
{
|
|
deferredBundles = new List<string>();
|
|
HttpContext.Current.Items[BundleTable.UIExtensionScriptsKey] = deferredBundles;
|
|
}
|
|
if (!deferredBundles.Contains(resourcePath))
|
|
deferredBundles.Add(resourcePath);
|
|
}
|
|
#endregion
|
|
|
|
#region Virtual Directories
|
|
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static HtmlString DiscoPluginResourceUrl<T>(this WebViewPage<T> ViewPage, string Resource)
|
|
{
|
|
return ViewPage.DiscoPluginResourceUrl(Resource, false);
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static HtmlString DiscoPluginResourceUrl<T>(this WebViewPage<T> ViewPage, string Resource, bool Download)
|
|
{
|
|
if (string.IsNullOrEmpty(Resource))
|
|
throw new ArgumentNullException("Resource");
|
|
|
|
// Find Plugin
|
|
var pageType = ViewPage.GetType();
|
|
var pageAssembly = pageType.Assembly;
|
|
var manifest = Plugins.GetPlugin(pageAssembly);
|
|
|
|
return ViewPage.DiscoPluginResourceUrl(Resource, false, manifest);
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static HtmlString DiscoPluginResourceUrl<T>(this WebViewPage<T> ViewPage, string Resource, bool Download, PluginManifest manifest)
|
|
{
|
|
return ViewPage.ViewContext.RequestContext.DiscoPluginResourceUrl(Resource, Download, manifest);
|
|
}
|
|
[Obsolete]
|
|
public static HtmlString DiscoPluginResourceUrl(this RequestContext RequestContext, string Resource, bool Download, PluginManifest manifest)
|
|
{
|
|
var resourcePath = manifest.WebResourcePath(Resource);
|
|
|
|
var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id, res = Resource });
|
|
string pluginActionUrl = UrlHelper.GenerateUrl("Plugin_Resources", null, null, routeValues, RouteTable.Routes, RequestContext, false);
|
|
|
|
pluginActionUrl += string.Format("?v={0}", resourcePath.Item2);
|
|
|
|
if (Download)
|
|
pluginActionUrl += "&Download=true";
|
|
|
|
return new HtmlString(pluginActionUrl);
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static HtmlString DiscoPluginActionUrl<T>(this WebViewPage<T> ViewPage, string PluginAction)
|
|
{
|
|
if (string.IsNullOrEmpty(PluginAction))
|
|
throw new ArgumentNullException("PluginAction");
|
|
|
|
// Find Plugin
|
|
var pageType = ViewPage.GetType();
|
|
var pageAssembly = pageType.Assembly;
|
|
var manifest = Plugins.GetPlugin(pageAssembly);
|
|
|
|
return ViewPage.DiscoPluginActionUrl(PluginAction, manifest);
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static HtmlString DiscoPluginActionUrl<T>(this WebViewPage<T> ViewPage, string PluginAction, PluginManifest manifest)
|
|
{
|
|
return ViewPage.ViewContext.RequestContext.DiscoPluginActionUrl(PluginAction, manifest);
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static HtmlString DiscoPluginActionUrl(this RequestContext RequestContext, string PluginAction, PluginManifest manifest)
|
|
{
|
|
var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id, PluginAction = PluginAction });
|
|
string pluginActionUrl = UrlHelper.GenerateUrl("Plugin", null, null, routeValues, RouteTable.Routes, RequestContext, false);
|
|
return new HtmlString(pluginActionUrl);
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static HtmlString DiscoPluginConfigureUrl<T>(this WebViewPage<T> ViewPage)
|
|
{
|
|
// Find Plugin
|
|
var pageType = ViewPage.GetType();
|
|
var pageAssembly = pageType.Assembly;
|
|
var manifest = Plugins.GetPlugin(pageAssembly);
|
|
|
|
return ViewPage.DiscoPluginConfigureUrl(manifest);
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static HtmlString DiscoPluginConfigureUrl<T>(this WebViewPage<T> ViewPage, PluginManifest manifest)
|
|
{
|
|
return new HtmlString(ViewPage.ViewContext.RequestContext.DiscoPluginConfigureUrl(manifest));
|
|
}
|
|
[Obsolete]
|
|
public static string DiscoPluginConfigureUrl(this RequestContext RequestContext, PluginManifest manifest)
|
|
{
|
|
var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id });
|
|
string pluginActionUrl = UrlHelper.GenerateUrl("Config_Plugins_Configure", null, null, routeValues, RouteTable.Routes, RequestContext, false);
|
|
return pluginActionUrl;
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction, FormMethod method, IDictionary<string, object> htmlAttributes)
|
|
{
|
|
if (string.IsNullOrEmpty(PluginAction))
|
|
throw new ArgumentNullException("PluginAction");
|
|
|
|
// Find Plugin
|
|
var pageType = ViewPage.GetType();
|
|
var pageAssembly = pageType.Assembly;
|
|
var manifest = Plugins.GetPlugin(pageAssembly);
|
|
|
|
var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id, PluginAction = PluginAction });
|
|
string pluginActionUrl = UrlHelper.GenerateUrl("Plugin", null, null, routeValues, RouteTable.Routes, ViewPage.ViewContext.RequestContext, false);
|
|
|
|
#pragma warning disable 618
|
|
return ViewPage.FormHelper(pluginActionUrl, method, htmlAttributes);
|
|
#pragma warning restore 618
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction, FormMethod method)
|
|
{
|
|
#pragma warning disable 618
|
|
return ViewPage.DiscoPluginActionBeginForm(PluginAction, method, null);
|
|
#pragma warning restore 618
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction, IDictionary<string, object> htmlAttributes)
|
|
{
|
|
#pragma warning disable 618
|
|
return ViewPage.DiscoPluginActionBeginForm(PluginAction, FormMethod.Post, htmlAttributes);
|
|
#pragma warning restore 618
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction)
|
|
{
|
|
#pragma warning disable 618
|
|
return ViewPage.DiscoPluginActionBeginForm(PluginAction, FormMethod.Post, null);
|
|
#pragma warning restore 618
|
|
}
|
|
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
private static MvcForm FormHelper<T>(this WebViewPage<T> ViewPage, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes)
|
|
{
|
|
TagBuilder builder = new TagBuilder("form");
|
|
builder.MergeAttributes<string, object>(htmlAttributes);
|
|
builder.MergeAttribute("action", formAction);
|
|
builder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);
|
|
bool flag = ViewPage.ViewContext.ClientValidationEnabled && !ViewPage.ViewContext.UnobtrusiveJavaScriptEnabled;
|
|
if (flag)
|
|
{
|
|
object obj2 = ViewPage.ViewContext.HttpContext.Items["DiscoPluginLastFormNum"];
|
|
int num = (obj2 != null) ? (((int)obj2) + 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 (flag)
|
|
{
|
|
ViewPage.ViewContext.FormContext.FormId = builder.Attributes["id"];
|
|
}
|
|
return form;
|
|
}
|
|
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static void DiscoPluginRegisterStylesheet<T>(this WebViewPage<T> ViewPage, string Resource)
|
|
{
|
|
if (string.IsNullOrEmpty(Resource))
|
|
throw new ArgumentNullException("Resource");
|
|
|
|
// Find Plugin
|
|
var pageType = ViewPage.GetType();
|
|
var pageAssembly = pageType.Assembly;
|
|
var manifest = Plugins.GetPlugin(pageAssembly);
|
|
|
|
ViewPage.DiscoPluginRegisterStylesheet(Resource, manifest);
|
|
}
|
|
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
|
|
public static void DiscoPluginRegisterStylesheet<T>(this WebViewPage<T> ViewPage, string Resource, PluginManifest manifest)
|
|
{
|
|
ViewPage.ViewContext.RequestContext.DiscoPluginRegisterStylesheet(Resource, manifest);
|
|
}
|
|
[Obsolete]
|
|
public static void DiscoPluginRegisterStylesheet(this RequestContext RequestContext, string Resource, PluginManifest manifest)
|
|
{
|
|
var resourcePath = manifest.WebResourcePath(Resource);
|
|
|
|
var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id, res = Resource });
|
|
string pluginResourceUrl = UrlHelper.GenerateUrl("Plugin_Resources", null, null, routeValues, RouteTable.Routes, RequestContext, false);
|
|
|
|
pluginResourceUrl += string.Format("?v={0}", resourcePath.Item2);
|
|
|
|
HtmlString pluginResourceUrlHtml = new HtmlString(pluginResourceUrl);
|
|
|
|
var deferredBundles = RequestContext.HttpContext.Items[BundleTable.UIExtensionCssKey] as List<HtmlString>;
|
|
if (deferredBundles == null)
|
|
{
|
|
deferredBundles = new List<HtmlString>();
|
|
HttpContext.Current.Items[BundleTable.UIExtensionCssKey] = deferredBundles;
|
|
}
|
|
if (!deferredBundles.Contains(pluginResourceUrlHtml))
|
|
deferredBundles.Add(pluginResourceUrlHtml);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Request Caching
|
|
[Obsolete]
|
|
public static void SetCacheability(this PluginWebHandler Handler, TimeSpan CacheDuration)
|
|
{
|
|
var cache = Handler.HostController.Response.Cache;
|
|
cache.SetOmitVaryStar(true);
|
|
cache.SetExpires(DateTime.Now.Add(CacheDuration));
|
|
cache.SetValidUntilExpires(true);
|
|
cache.SetCacheability(HttpCacheability.Private);
|
|
}
|
|
[Obsolete]
|
|
public static void SetCacheabilityOff(this PluginWebHandler Handler)
|
|
{
|
|
var cache = Handler.HostController.Response.Cache;
|
|
cache.SetExpires(DateTime.Now.AddDays(-1));
|
|
cache.SetCacheability(HttpCacheability.NoCache);
|
|
}
|
|
#endregion
|
|
|
|
#region Render Partial Compiled
|
|
[Obsolete]
|
|
private static void RenderPartialCompiledInternal(this HtmlHelper htmlHelper, Type viewType, object model, TextWriter writer)
|
|
{
|
|
if (writer == null)
|
|
throw new ArgumentNullException("writer");
|
|
WebViewPage page = Activator.CreateInstance(viewType) as WebViewPage;
|
|
if (page == null)
|
|
throw new InvalidOperationException("Invalid View Type");
|
|
page.ViewContext = htmlHelper.ViewContext;
|
|
page.ViewData = new ViewDataDictionary(model);
|
|
page.InitHelpers();
|
|
HttpContextBase httpContext = htmlHelper.ViewContext.HttpContext;
|
|
page.ExecutePageHierarchy(new WebPageContext(httpContext, null, model), writer, null);
|
|
}
|
|
[Obsolete]
|
|
public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType)
|
|
{
|
|
return PartialCompiled(htmlHelper, viewType, null);
|
|
}
|
|
[Obsolete]
|
|
public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType, object model)
|
|
{
|
|
using (StringWriter writer = new StringWriter(CultureInfo.CurrentCulture))
|
|
{
|
|
#pragma warning disable 618
|
|
htmlHelper.RenderPartialCompiledInternal(viewType, model, writer);
|
|
#pragma warning restore 618
|
|
return MvcHtmlString.Create(writer.ToString());
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|