Update: Plugin Framework & Update

This commit is contained in:
Gary Sharp
2013-02-19 16:10:27 +11:00
parent 8f769809c2
commit e589c5edb4
14 changed files with 855 additions and 149 deletions
+4 -5
View File
@@ -50,9 +50,9 @@
<Reference Include="Quartz"> <Reference Include="Quartz">
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath> <HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
</Reference> </Reference>
<Reference Include="RazorGenerator.Mvc, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="RazorGenerator.Mvc, Version=1.5.4.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\RazorGenerator.Mvc.1.5.0.0\lib\net40\RazorGenerator.Mvc.dll</HintPath> <HintPath>..\packages\RazorGenerator.Mvc.1.5.4.0\lib\net40\RazorGenerator.Mvc.dll</HintPath>
</Reference> </Reference>
<Reference Include="SignalR, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SignalR, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
@@ -83,9 +83,8 @@
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="WebActivator, Version=1.5.3.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="WebActivatorEx">
<SpecificVersion>False</SpecificVersion> <HintPath>..\packages\WebActivatorEx.2.0.1\lib\net40\WebActivatorEx.dll</HintPath>
<HintPath>..\packages\WebActivator.1.5.3\lib\net40\WebActivator.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
-1
View File
@@ -17,7 +17,6 @@ namespace Disco.Services.Plugins
public virtual void Install(DiscoDataContext dbContext, ScheduledTaskStatus Status) { return; } public virtual void Install(DiscoDataContext dbContext, ScheduledTaskStatus Status) { return; }
public virtual void Initialize(DiscoDataContext dbContext) { return; } public virtual void Initialize(DiscoDataContext dbContext) { return; }
public virtual void Uninstall(DiscoDataContext dbContext, bool UninstallData, ScheduledTaskStatus Status) { return; } public virtual void Uninstall(DiscoDataContext dbContext, bool UninstallData, ScheduledTaskStatus Status) { return; }
public virtual void BeforeUpdate(DiscoDataContext dbContext, PluginManifest UpdateManifest, ScheduledTaskStatus Status) { return; }
public virtual void AfterUpdate(DiscoDataContext dbContext, PluginManifest PreviousManifest) { return; } public virtual void AfterUpdate(DiscoDataContext dbContext, PluginManifest PreviousManifest) { return; }
#endregion #endregion
-12
View File
@@ -257,18 +257,6 @@ namespace Disco.Services.Plugins
return true; return true;
} }
internal bool BeforePluginUpdate(DiscoDataContext dbContext, PluginManifest UpdateManifest, ScheduledTaskStatus Status)
{
// Initialize Plugin
InitializePluginEnvironment(dbContext);
using (var pluginInstance = this.CreateInstance())
{
pluginInstance.BeforeUpdate(dbContext, UpdateManifest, Status);
}
return true;
}
internal bool AfterPluginUpdate(DiscoDataContext dbContext, PluginManifest PreviousManifest) internal bool AfterPluginUpdate(DiscoDataContext dbContext, PluginManifest PreviousManifest)
{ {
// Initialize Plugin // Initialize Plugin
+104 -2
View File
@@ -86,6 +86,7 @@ namespace Disco.Services.Plugins
{ {
string pluginsLocation; string pluginsLocation;
string pluginPackagesLocation; string pluginPackagesLocation;
string pluginsStorageLocation;
PluginLibraryUpdateResponse pluginCatalogue; PluginLibraryUpdateResponse pluginCatalogue;
List<Tuple<PluginManifest, string, PluginLibraryItem>> UpdatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>(); List<Tuple<PluginManifest, string, PluginLibraryItem>> UpdatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>();
@@ -94,11 +95,14 @@ namespace Disco.Services.Plugins
pluginCatalogue = Plugins.LoadCatalogue(dbContext); pluginCatalogue = Plugins.LoadCatalogue(dbContext);
pluginsLocation = dbContext.DiscoConfiguration.PluginsLocation; pluginsLocation = dbContext.DiscoConfiguration.PluginsLocation;
pluginPackagesLocation = dbContext.DiscoConfiguration.PluginPackagesLocation; pluginPackagesLocation = dbContext.DiscoConfiguration.PluginPackagesLocation;
pluginsStorageLocation = dbContext.DiscoConfiguration.PluginStorageLocation;
} }
DirectoryInfo pluginDirectoryRoot = new DirectoryInfo(pluginsLocation); DirectoryInfo pluginDirectoryRoot = new DirectoryInfo(pluginsLocation);
if (pluginDirectoryRoot.Exists) if (pluginDirectoryRoot.Exists)
{ {
MirgrateV1Plugins(pluginsLocation, pluginsStorageLocation);
foreach (DirectoryInfo pluginDirectory in pluginDirectoryRoot.EnumerateDirectories()) foreach (DirectoryInfo pluginDirectory in pluginDirectoryRoot.EnumerateDirectories())
{ {
string pluginManifestFilename = Path.Combine(pluginDirectory.FullName, "manifest.json"); string pluginManifestFilename = Path.Combine(pluginDirectory.FullName, "manifest.json");
@@ -131,6 +135,105 @@ namespace Disco.Services.Plugins
} }
} }
internal static void MirgrateV1Plugins(string pluginsLocation, string pluginsStorageLocation)
{
var migrationPackage = Path.Combine(HttpRuntime.BinDirectory, "Disco1.1-1.2PluginMigration.zip");
if (File.Exists(migrationPackage))
{
// eduSTAR.net
var eduSTARPluginPath = Path.Combine(pluginsLocation, "EduSTARnetCertificateProvider");
if (Directory.Exists(eduSTARPluginPath))
{
var eduSTARPluginAssemblyPath = Path.Combine(eduSTARPluginPath, "EduSTARnetCertificateProvider.dll");
if (File.Exists(eduSTARPluginAssemblyPath))
{
// Delete Old Plugin
Directory.Delete(eduSTARPluginPath, true);
// Add New Plugin
eduSTARPluginPath = Path.Combine(pluginsLocation, "eduSTARnet");
using (var migrationZipPackageStream = new FileStream(migrationPackage, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (ZipArchive migrationZipPackage = new ZipArchive(migrationZipPackageStream))
{
var pluginZipPackage = migrationZipPackage.Entries.Where(e => e.Name.Equals("eduSTARnet.discoPlugin", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
if (pluginZipPackage != null)
{
using (var pluginPackageStream = pluginZipPackage.Open())
{
using (ZipArchive pluginPackageArchive = new ZipArchive(pluginPackageStream))
{
foreach (var entry in pluginPackageArchive.Entries)
{
var entryPath = Path.Combine(eduSTARPluginPath, entry.FullName);
Directory.CreateDirectory(Path.GetDirectoryName(entryPath));
using (var entryOutput = new FileStream(entryPath, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (var entryStream = entry.Open())
{
entryStream.CopyTo(entryOutput);
}
}
}
}
}
}
}
}
}
}
// LWT
var LWTPluginPath = Path.Combine(pluginsLocation, "LWTWarrantyProvider");
if (Directory.Exists(LWTPluginPath))
{
var LWTPluginAssemblyPath = Path.Combine(LWTPluginPath, "LWTWarrantyProvider.dll");
if (File.Exists(LWTPluginAssemblyPath))
{
// Delete Old Plugin
Directory.Delete(LWTPluginPath, true);
// Delete Plugin Storage
var LWTPluginStoragePath = Path.Combine(pluginsStorageLocation, "LWTWarrantyProvider");
if (Directory.Exists(LWTPluginStoragePath))
Directory.Delete(LWTPluginStoragePath, true);
// Add New Plugin
LWTPluginPath = Path.Combine(pluginsLocation, "LWTPlugin");
using (var migrationZipPackageStream = new FileStream(migrationPackage, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (ZipArchive migrationZipPackage = new ZipArchive(migrationZipPackageStream))
{
var pluginZipPackage = migrationZipPackage.Entries.Where(e => e.Name.Equals("LWTPlugin.discoPlugin", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
if (pluginZipPackage != null)
{
using (var pluginPackageStream = pluginZipPackage.Open())
{
using (ZipArchive pluginPackageArchive = new ZipArchive(pluginPackageStream))
{
foreach (var entry in pluginPackageArchive.Entries)
{
var entryPath = Path.Combine(LWTPluginPath, entry.FullName);
Directory.CreateDirectory(Path.GetDirectoryName(entryPath));
using (var entryOutput = new FileStream(entryPath, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (var entryStream = entry.Open())
{
entryStream.CopyTo(entryOutput);
}
}
}
}
}
}
}
}
}
}
}
}
internal static void ExecuteTaskInternal(ScheduledTaskStatus Status, string pluginPackagesLocation, List<Tuple<PluginManifest, string, PluginLibraryItem>> UpdatePlugins) internal static void ExecuteTaskInternal(ScheduledTaskStatus Status, string pluginPackagesLocation, List<Tuple<PluginManifest, string, PluginLibraryItem>> UpdatePlugins)
{ {
while (UpdatePlugins.Count > 0) while (UpdatePlugins.Count > 0)
@@ -211,10 +314,9 @@ namespace Disco.Services.Plugins
var updatePluginPath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, string.Format("{0}.discoPlugin", updateManifest.Id)); var updatePluginPath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, string.Format("{0}.discoPlugin", updateManifest.Id));
File.Move(packageTempFilePath, updatePluginPath); File.Move(packageTempFilePath, updatePluginPath);
if (existingManifest != null && Plugins.PluginsLoaded) if (existingManifest != null)
{ {
PluginsLog.LogBeforeUpdate(existingManifest, updateManifest); PluginsLog.LogBeforeUpdate(existingManifest, updateManifest);
existingManifest.BeforePluginUpdate(dbContext, updateManifest, Status);
} }
} }
} }
@@ -17,11 +17,11 @@ namespace Disco.Services.Plugins
{ {
this.Status.UpdateStatus(0, "Updating plugins after Disco update", "Starting, please wait..."); this.Status.UpdateStatus(0, "Updating plugins after Disco update", "Starting, please wait...");
// Wait for App to Load (6 Seconds) // Wait for App to Load (10 Seconds)
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
this.Status.UpdateStatus(10 * i); this.Status.UpdateStatus(10 * i);
System.Threading.Thread.Sleep(600); System.Threading.Thread.Sleep(1000);
} }
// Update Catalogue // Update Catalogue
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0214.1848")] [assembly: AssemblyVersion("1.2.0219.1605")]
[assembly: AssemblyFileVersion("1.2.0214.1848")] [assembly: AssemblyFileVersion("1.2.0219.1605")]
+14
View File
@@ -4,6 +4,7 @@ using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Routing; using System.Web.Routing;
using SignalR;
namespace Disco.Web namespace Disco.Web
{ {
@@ -71,6 +72,19 @@ namespace Disco.Web
public static void RegisterUpdateRoutes(RouteCollection routes) public static void RegisterUpdateRoutes(RouteCollection routes)
{ {
// Task Status SignalR Route
routes.MapConnection<Disco.Services.Tasks.ScheduledTasksLiveStatusService>(
"API_Logging_TaskStatusNotifications",
"API/Logging/TaskStatusNotifications/{*operation}");
// Task Status Ajax Route
routes.MapRoute(
name: "API_Logging_ScheduledTaskStatus", // Route name
url: "API/Logging/ScheduledTaskStatus/{id}", // URL with parameters
defaults: new { area = "API", controller = "Logging", action = "ScheduledTaskStatus", id = UrlParameter.Optional }, // Parameter defaults
namespaces: new string[] { "Disco.Web.Areas.API.Controllers" } // Controllers Namespace Only
);
// Update Route // Update Route
routes.MapRoute( routes.MapRoute(
name: "Update", // Route name name: "Update", // Route name
+7 -2
View File
@@ -21,7 +21,7 @@ namespace Disco.Web.Controllers
{ {
if (!Request.IsLocal && !InitialConfigController.ServerIsCoreSKU.Value) if (!Request.IsLocal && !InitialConfigController.ServerIsCoreSKU.Value)
{ {
filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.ServiceUnavailable, "Initial Configuration of Disco is only allowed via a local connection"); filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.ServiceUnavailable, "Initialization Configuration of Disco is only allowed via a local connection");
} }
base.OnActionExecuting(filterContext); base.OnActionExecuting(filterContext);
} }
@@ -30,7 +30,12 @@ namespace Disco.Web.Controllers
{ {
var status = UpdatePluginsAfterDiscoUpdateTask.UpdateDiscoPlugins(true); var status = UpdatePluginsAfterDiscoUpdateTask.UpdateDiscoPlugins(true);
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId)); var model = new Models.Update.IndexModel()
{
SessionId = status.SessionId
};
return View(model);
} }
} }
} }
+12 -7
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@@ -43,13 +44,18 @@ namespace Disco.Web
timer_last = timer.ElapsedMilliseconds; timer_last = timer.ElapsedMilliseconds;
// Check for Post-Update // Check for Post-Update
Version previousVersion; bool ignoreVersionUpdate = false;
Version currentVersion = Disco.BI.Interop.Community.UpdateCheck.CurrentDiscoVersion(); bool.TryParse(ConfigurationManager.AppSettings["DiscoIgnoreVersionUpdate"], out ignoreVersionUpdate);
using (DiscoDataContext dbContext = new DiscoDataContext()) Version previousVersion = null;
if (!ignoreVersionUpdate)
{ {
previousVersion = dbContext.DiscoConfiguration.InstalledDatabaseVersion; using (DiscoDataContext dbContext = new DiscoDataContext())
{
previousVersion = dbContext.DiscoConfiguration.InstalledDatabaseVersion;
}
} }
if (currentVersion == previousVersion) if (ignoreVersionUpdate || Disco.BI.Interop.Community.UpdateCheck.CurrentDiscoVersion() == previousVersion)
{ {
// Normal Startup // Normal Startup
@@ -86,7 +92,6 @@ namespace Disco.Web
else else
{ {
// Post-Update Startup // Post-Update Startup
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterUpdateRoutes(RouteTable.Routes); RouteConfig.RegisterUpdateRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(); BundleConfig.RegisterBundles();
@@ -94,7 +99,7 @@ namespace Disco.Web
using (DiscoDataContext dbContext = new DiscoDataContext()) using (DiscoDataContext dbContext = new DiscoDataContext())
{ {
dbContext.DiscoConfiguration.InstalledDatabaseVersion = currentVersion; dbContext.DiscoConfiguration.InstalledDatabaseVersion = Disco.BI.Interop.Community.UpdateCheck.CurrentDiscoVersion();
dbContext.SaveChanges(); dbContext.SaveChanges();
} }
} }
+12
View File
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Disco.Web.Models.Update
{
public class IndexModel
{
public string SessionId { get; set; }
}
}
+261
View File
@@ -0,0 +1,261 @@
@model Disco.Web.Models.Update.IndexModel
@{
ViewBag.Title = "Disco Post-Update Configuration";
Layout = "~/Areas/Public/Views/Shared/_Layout.cshtml";
Html.BundleDeferred("~/ClientScripts/Modules/Knockout");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
Html.BundleDeferred("~/Style/Config");
}
<div style="min-height: 300px;">
<div id="scheduledTaskStatus" class="form" style="width: 520px;" data-bind="visible: Initialized">
<h2 data-bind="text: TaskName">&nbsp;</h2>
<table>
<tr data-bind="visible: IsRunning">
<th class="process" data-bind="text: CurrentProcess">&nbsp;
</th>
</tr>
<tr data-bind="visible: IsRunning">
<td class="description" data-bind="text: CurrentDescription">&nbsp;
</td>
</tr>
<tr data-bind="visible: IsRunning">
<td class="progress">
<div data-bind="progressValue: Progress">
</div>
</td>
</tr>
<tr data-bind="visible: FinishedTimestamp">
<td class="finishedTimestamp">
<h3>Finished: <span data-bind="text: FinishedTimestampFormatted"></span>
</h3>
</td>
</tr>
<tr data-bind="visible: FinishedTimestamp() && !TaskExceptionMessage()">
<td class="finishedMessage" data-bind="css: { finishedRedirect: FinishedUrl }">
<span data-bind="text: FinishedMessage"></span>
</td>
</tr>
<tr data-bind="visible: TaskExceptionMessage">
<td class="exception">Last Error:
<div class="code" data-bind="text: TaskExceptionMessage">
</div>
</td>
</tr>
<tr data-bind="visible: NextScheduledTimestamp">
<td class="nextScheduledTimestamp">Next Scheduled: <span data-bind="text: NextScheduledTimestampFormatted"></span>
</td>
</tr>
</table>
</div>
</div>
<script type="text/javascript">
ko.bindingHandlers.progressValue = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var $element = $(element);
if (!$element.is('.ui-progressbar'))
$element.progressbar();
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var v = ko.utils.unwrapObservable(valueAccessor());
var vInt = parseInt(v);
if (vInt >= 0) {
$(element).progressbar('option', 'value', vInt);
}
}
};
//* http://webcloud.se/log/JavaScript-and-ISO-8601/
Date.prototype.setISO8601 = function (string) {
var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
var d = string.match(new RegExp(regexp));
var offset = 0;
var date = new Date(d[1], 0, 1);
if (d[3]) { date.setMonth(d[3] - 1); }
if (d[5]) { date.setDate(d[5]); }
if (d[7]) { date.setHours(d[7]); }
if (d[8]) { date.setMinutes(d[8]); }
if (d[10]) { date.setSeconds(d[10]); }
if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
if (d[14]) {
offset = (Number(d[16]) * 60) + Number(d[17]);
offset *= ((d[15] == '-') ? 1 : -1);
}
offset -= date.getTimezoneOffset();
time = (Number(date) + (offset * 60 * 1000));
this.setTime(Number(time));
return this;
}
</script>
<script type="text/javascript">
$(function () {
var sessionId = '@(Model.SessionId)';
var sessionStatusUrl = '@(Url.Action(MVC.API.Logging.ScheduledTaskStatus(Model.SessionId)))';
// Clear Menu
$('#menu').empty();
var view = $('#scheduledTaskStatus');
var vm = null;
var liveConnection = null;
var statusViewModel = function (sessionId) {
var self = this;
self.Initialized = ko.observable(false);
self.TimestampParse = function (timestamp) {
if (timestamp) {
if (timestamp.indexOf("\/Date(") == 0)
return new Date(parseInt(timestamp.substr(6)));
else
return (new Date()).setISO8601(timestamp);
}
return new Date();
}
self.TimestampFormat = function (timestamp) {
var addZero = function (v) { v = v + ''; if (v.length == 1) v = '0' + v; return v; }
return timestamp.getFullYear() + '/' + addZero((1 + timestamp.getMonth())) + '/' + addZero(timestamp.getDate()) + ' ' + addZero(timestamp.getHours()) + ':' + addZero(timestamp.getMinutes()) + ':' + addZero(timestamp.getSeconds());
}
self.SessionId = sessionId;
self.TaskName = ko.observable(null);
self.StatusVersion = -1;
self.Progress = ko.observable(0);
self.CurrentProcess = ko.observable(null);
self.CurrentDescription = ko.observable(null);
self.IsRunning = ko.observable(null);
self.TaskExceptionMessage = ko.observable(null);
self.FinishedTimestamp = ko.observable(null);
self.NextScheduledTimestamp = ko.observable(null)
self.NextScheduledTimestampFormatted = ko.computed(function () {
return self.TimestampFormat(self.TimestampParse(self.NextScheduledTimestamp()));
});
self.FinishedTimestampFormatted = ko.computed(function () {
return self.TimestampFormat(self.TimestampParse(self.FinishedTimestamp()));
});
self.FinishedUrl = ko.observable(null);
self.FinishedMessage = ko.observable(null);
self.Finished = function () {
if (self.FinishedTimestamp()) {
if (self.FinishedUrl() && !self.TaskExceptionMessage()) {
if (self.FinishedMessage())
window.setTimeout(function () { window.location.href = self.FinishedUrl(); }, 3000);
else
window.location.href = self.FinishedUrl();
}
}
}
self.Initialize = function (taskStatus) {
self.TaskName(taskStatus.TaskName);
self.FinishedUrl(taskStatus.FinishedUrl);
self.Progress(taskStatus.Progress);
self.CurrentProcess(taskStatus.CurrentProcess);
self.CurrentDescription(taskStatus.CurrentDescription);
self.IsRunning(taskStatus.IsRunning);
self.TaskExceptionMessage(taskStatus.TaskExceptionMessage);
self.FinishedTimestamp(taskStatus.FinishedTimestamp);
self.NextScheduledTimestamp(taskStatus.NextScheduledTimestamp);
self.FinishedMessage(taskStatus.FinishedMessage);
self.Initialized(true);
self.Finished();
}
self.Update = function (taskStatus) {
if (!self.Initialized())
return self.Initialize(taskStatus);
if (taskStatus.StatusVersion < self.StatusVersion)
return; // Have Newer Status Update
self.StatusVersion = taskStatus.StatusVersion;
if (taskStatus.ChangedProperties) {
for (var changedPropertyIndex = 0; changedPropertyIndex < taskStatus.ChangedProperties.length; changedPropertyIndex++) {
switch (taskStatus.ChangedProperties[changedPropertyIndex]) {
case 'Progress':
self.Progress(taskStatus.Progress);
break;
case 'CurrentProcess':
self.CurrentProcess(taskStatus.CurrentProcess);
break;
case 'CurrentDescription':
self.CurrentDescription(taskStatus.CurrentDescription);
break;
case 'IsRunning':
self.IsRunning(taskStatus.IsRunning);
break;
case 'TaskException':
self.TaskExceptionMessage(taskStatus.TaskExceptionMessage);
break;
case 'NextScheduledTimestamp':
self.NextScheduledTimestamp(taskStatus.NextScheduledTimestamp);
break;
case 'FinishedUrl':
self.FinishedUrl(taskStatus.FinishedUrl);
break;
case 'FinishedMessage':
self.FinishedMessage(taskStatus.FinishedMessage);
break;
case 'FinishedTimestamp':
self.FinishedTimestamp(taskStatus.FinishedTimestamp);
window.setTimeout(self.Finished, 1);
break;
default:
// Ignore
}
}
}
}
}
vm = new statusViewModel(sessionId);
ko.applyBindings(vm, view[0]);
// Start Live Connection
updateWithLive();
function updateWithAjax(onSuccess) {
$.ajax({
url: sessionStatusUrl,
dataType: 'json',
type: 'POST',
traditional: true,
success: update_Received,
error: function (jqXHR, textStatus, errorThrown) {
alert('Unable to load Session: ' + errorThrown);
}
});
}
function updateWithLive() {
liveConnection = $.connection('@(Url.Content("~/API/Logging/TaskStatusNotifications"))');
liveConnection.received(update_Received);
liveConnection.start(function () {
liveConnection.send('/addToGroups:' + sessionId);
updateWithAjax();
});
}
function update_Received(taskStatus) {
vm.Update(taskStatus);
}
});
</script>
+317
View File
@@ -0,0 +1,317 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.17929
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Disco.Web.Views.Update
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Web.Security;
using System.Web.UI;
using System.Web.WebPages;
using Disco.BI.Extensions;
using Disco.Models.Repository;
using Disco.Web;
using Disco.Web.Extensions;
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "1.5.0.0")]
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/Update/Index.cshtml")]
public class Index : System.Web.Mvc.WebViewPage<Disco.Web.Models.Update.IndexModel>
{
public Index()
{
}
public override void Execute()
{
#line 2 "..\..\Views\Update\Index.cshtml"
ViewBag.Title = "Disco Post-Update Configuration";
Layout = "~/Areas/Public/Views/Shared/_Layout.cshtml";
Html.BundleDeferred("~/ClientScripts/Modules/Knockout");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
Html.BundleDeferred("~/Style/Config");
#line default
#line hidden
WriteLiteral("\r\n<div");
WriteLiteral(" style=\"min-height: 300px;\"");
WriteLiteral(">\r\n <div");
WriteLiteral(" id=\"scheduledTaskStatus\"");
WriteLiteral(" class=\"form\"");
WriteLiteral(" style=\"width: 520px;\"");
WriteLiteral(" data-bind=\"visible: Initialized\"");
WriteLiteral(">\r\n <h2");
WriteLiteral(" data-bind=\"text: TaskName\"");
WriteLiteral(">&nbsp;</h2>\r\n <table>\r\n <tr");
WriteLiteral(" data-bind=\"visible: IsRunning\"");
WriteLiteral(">\r\n <th");
WriteLiteral(" class=\"process\"");
WriteLiteral(" data-bind=\"text: CurrentProcess\"");
WriteLiteral(">&nbsp;\r\n </th>\r\n </tr>\r\n <tr");
WriteLiteral(" data-bind=\"visible: IsRunning\"");
WriteLiteral(">\r\n <td");
WriteLiteral(" class=\"description\"");
WriteLiteral(" data-bind=\"text: CurrentDescription\"");
WriteLiteral(">&nbsp;\r\n </td>\r\n </tr>\r\n <tr");
WriteLiteral(" data-bind=\"visible: IsRunning\"");
WriteLiteral(">\r\n <td");
WriteLiteral(" class=\"progress\"");
WriteLiteral(">\r\n <div");
WriteLiteral(" data-bind=\"progressValue: Progress\"");
WriteLiteral(">\r\n </div>\r\n </td>\r\n </tr>\r\n " +
" <tr");
WriteLiteral(" data-bind=\"visible: FinishedTimestamp\"");
WriteLiteral(">\r\n <td");
WriteLiteral(" class=\"finishedTimestamp\"");
WriteLiteral(">\r\n <h3>Finished: <span");
WriteLiteral(" data-bind=\"text: FinishedTimestampFormatted\"");
WriteLiteral("></span>\r\n </h3>\r\n </td>\r\n </tr>\r\n " +
" <tr");
WriteLiteral(" data-bind=\"visible: FinishedTimestamp() && !TaskExceptionMessage()\"");
WriteLiteral(">\r\n <td");
WriteLiteral(" class=\"finishedMessage\"");
WriteLiteral(" data-bind=\"css: { finishedRedirect: FinishedUrl }\"");
WriteLiteral(">\r\n <span");
WriteLiteral(" data-bind=\"text: FinishedMessage\"");
WriteLiteral("></span>\r\n </td>\r\n </tr>\r\n <tr");
WriteLiteral(" data-bind=\"visible: TaskExceptionMessage\"");
WriteLiteral(">\r\n <td");
WriteLiteral(" class=\"exception\"");
WriteLiteral(">Last Error:\r\n <div");
WriteLiteral(" class=\"code\"");
WriteLiteral(" data-bind=\"text: TaskExceptionMessage\"");
WriteLiteral(">\r\n </div>\r\n </td>\r\n </tr>\r\n " +
" <tr");
WriteLiteral(" data-bind=\"visible: NextScheduledTimestamp\"");
WriteLiteral(">\r\n <td");
WriteLiteral(" class=\"nextScheduledTimestamp\"");
WriteLiteral(">Next Scheduled: <span");
WriteLiteral(" data-bind=\"text: NextScheduledTimestampFormatted\"");
WriteLiteral("></span>\r\n </td>\r\n </tr>\r\n </table>\r\n </div>\r" +
"\n</div>\r\n<script");
WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(">\r\n ko.bindingHandlers.progressValue = {\r\n init: function (element, val" +
"ueAccessor, allBindingsAccessor, viewModel) {\r\n var $element = $(elem" +
"ent);\r\n if (!$element.is(\'.ui-progressbar\'))\r\n $elemen" +
"t.progressbar();\r\n },\r\n update: function (element, valueAccessor, " +
"allBindingsAccessor, viewModel) {\r\n var v = ko.utils.unwrapObservable" +
"(valueAccessor());\r\n var vInt = parseInt(v);\r\n if (vInt >=" +
" 0) {\r\n $(element).progressbar(\'option\', \'value\', vInt);\r\n " +
" }\r\n }\r\n };\r\n //* http://webcloud.se/log/JavaScript-and-ISO-860" +
"1/\r\n Date.prototype.setISO8601 = function (string) {\r\n var regexp = \"(" +
"[0-9]{4})(-([0-9]{2})(-([0-9]{2})\" +\r\n \"(T([0-9]{2}):([0-9]{2})(:([0-9]{2" +
"})(\\.([0-9]+))?)?\" +\r\n \"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?\";\r\n " +
" var d = string.match(new RegExp(regexp));\r\n\r\n var offset = 0;\r\n " +
" var date = new Date(d[1], 0, 1);\r\n\r\n if (d[3]) { date.setMonth(d[3] - 1)" +
"; }\r\n if (d[5]) { date.setDate(d[5]); }\r\n if (d[7]) { date.setHour" +
"s(d[7]); }\r\n if (d[8]) { date.setMinutes(d[8]); }\r\n if (d[10]) { d" +
"ate.setSeconds(d[10]); }\r\n if (d[12]) { date.setMilliseconds(Number(\"0.\" " +
"+ d[12]) * 1000); }\r\n if (d[14]) {\r\n offset = (Number(d[16]) *" +
" 60) + Number(d[17]);\r\n offset *= ((d[15] == \'-\') ? 1 : -1);\r\n " +
" }\r\n\r\n offset -= date.getTimezoneOffset();\r\n time = (Number(date) " +
"+ (offset * 60 * 1000));\r\n this.setTime(Number(time));\r\n return th" +
"is;\r\n }\r\n</script>\r\n<script");
WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(">\r\n $(function () {\r\n var sessionId = \'");
#line 96 "..\..\Views\Update\Index.cshtml"
Write(Model.SessionId);
#line default
#line hidden
WriteLiteral("\';\r\n var sessionStatusUrl = \'");
#line 97 "..\..\Views\Update\Index.cshtml"
Write(Url.Action(MVC.API.Logging.ScheduledTaskStatus(Model.SessionId)));
#line default
#line hidden
WriteLiteral("\';\r\n\r\n // Clear Menu\r\n $(\'#menu\').empty();\r\n\r\n var view = $(" +
"\'#scheduledTaskStatus\');\r\n var vm = null;\r\n\r\n var liveConnection =" +
" null;\r\n\r\n var statusViewModel = function (sessionId) {\r\n var " +
"self = this;\r\n\r\n self.Initialized = ko.observable(false);\r\n\r\n " +
" self.TimestampParse = function (timestamp) {\r\n if (timestamp)" +
" {\r\n if (timestamp.indexOf(\"\\/Date(\") == 0)\r\n " +
" return new Date(parseInt(timestamp.substr(6)));\r\n els" +
"e\r\n return (new Date()).setISO8601(timestamp);\r\n " +
" }\r\n return new Date();\r\n }\r\n self.Ti" +
"mestampFormat = function (timestamp) {\r\n var addZero = function (" +
"v) { v = v + \'\'; if (v.length == 1) v = \'0\' + v; return v; }\r\n re" +
"turn timestamp.getFullYear() + \'/\' + addZero((1 + timestamp.getMonth())) + \'/\' +" +
" addZero(timestamp.getDate()) + \' \' + addZero(timestamp.getHours()) + \':\' + addZ" +
"ero(timestamp.getMinutes()) + \':\' + addZero(timestamp.getSeconds());\r\n " +
" }\r\n\r\n self.SessionId = sessionId;\r\n self.TaskName = ko.o" +
"bservable(null);\r\n self.StatusVersion = -1;\r\n\r\n self.Progr" +
"ess = ko.observable(0);\r\n self.CurrentProcess = ko.observable(null);\r" +
"\n self.CurrentDescription = ko.observable(null);\r\n\r\n self." +
"IsRunning = ko.observable(null);\r\n\r\n self.TaskExceptionMessage = ko.o" +
"bservable(null);\r\n\r\n self.FinishedTimestamp = ko.observable(null);\r\n " +
" self.NextScheduledTimestamp = ko.observable(null)\r\n\r\n self" +
".NextScheduledTimestampFormatted = ko.computed(function () {\r\n re" +
"turn self.TimestampFormat(self.TimestampParse(self.NextScheduledTimestamp()));\r\n" +
" });\r\n self.FinishedTimestampFormatted = ko.computed(funct" +
"ion () {\r\n return self.TimestampFormat(self.TimestampParse(self.F" +
"inishedTimestamp()));\r\n });\r\n\r\n self.FinishedUrl = ko.obse" +
"rvable(null);\r\n self.FinishedMessage = ko.observable(null);\r\n\r\n " +
" self.Finished = function () {\r\n if (self.FinishedTimestamp(" +
")) {\r\n if (self.FinishedUrl() && !self.TaskExceptionMessage()" +
") {\r\n if (self.FinishedMessage())\r\n " +
" window.setTimeout(function () { window.location.href = self.FinishedUrl();" +
" }, 3000);\r\n else\r\n window.loc" +
"ation.href = self.FinishedUrl();\r\n }\r\n }\r\n " +
" }\r\n\r\n self.Initialize = function (taskStatus) {\r\n " +
" self.TaskName(taskStatus.TaskName);\r\n self.FinishedUrl(taskSt" +
"atus.FinishedUrl);\r\n\r\n self.Progress(taskStatus.Progress);\r\n " +
" self.CurrentProcess(taskStatus.CurrentProcess);\r\n self" +
".CurrentDescription(taskStatus.CurrentDescription);\r\n\r\n self.IsRu" +
"nning(taskStatus.IsRunning);\r\n\r\n self.TaskExceptionMessage(taskSt" +
"atus.TaskExceptionMessage);\r\n\r\n self.FinishedTimestamp(taskStatus" +
".FinishedTimestamp);\r\n self.NextScheduledTimestamp(taskStatus.Nex" +
"tScheduledTimestamp);\r\n\r\n self.FinishedMessage(taskStatus.Finishe" +
"dMessage);\r\n\r\n self.Initialized(true);\r\n\r\n self.Fi" +
"nished();\r\n }\r\n self.Update = function (taskStatus) {\r\n " +
" if (!self.Initialized())\r\n return self.Initializ" +
"e(taskStatus);\r\n\r\n if (taskStatus.StatusVersion < self.StatusVers" +
"ion)\r\n return; // Have Newer Status Update\r\n s" +
"elf.StatusVersion = taskStatus.StatusVersion;\r\n\r\n if (taskStatus." +
"ChangedProperties) {\r\n for (var changedPropertyIndex = 0; cha" +
"ngedPropertyIndex < taskStatus.ChangedProperties.length; changedPropertyIndex++)" +
" {\r\n switch (taskStatus.ChangedProperties[changedProperty" +
"Index]) {\r\n case \'Progress\':\r\n " +
" self.Progress(taskStatus.Progress);\r\n br" +
"eak;\r\n case \'CurrentProcess\':\r\n " +
" self.CurrentProcess(taskStatus.CurrentProcess);\r\n " +
" break;\r\n case \'CurrentDescription\':\r\n " +
" self.CurrentDescription(taskStatus.CurrentDescription" +
");\r\n break;\r\n case \'Is" +
"Running\':\r\n self.IsRunning(taskStatus.IsRunning);" +
"\r\n break;\r\n case \'Task" +
"Exception\':\r\n self.TaskExceptionMessage(taskStatu" +
"s.TaskExceptionMessage);\r\n break;\r\n " +
" case \'NextScheduledTimestamp\':\r\n se" +
"lf.NextScheduledTimestamp(taskStatus.NextScheduledTimestamp);\r\n " +
" break;\r\n case \'FinishedUrl\':\r\n " +
" self.FinishedUrl(taskStatus.FinishedUrl);\r\n " +
" break;\r\n case \'FinishedMessage\':\r\n" +
" self.FinishedMessage(taskStatus.FinishedMessage)" +
";\r\n break;\r\n case \'Fin" +
"ishedTimestamp\':\r\n self.FinishedTimestamp(taskSta" +
"tus.FinishedTimestamp);\r\n window.setTimeout(self." +
"Finished, 1);\r\n break;\r\n " +
" default:\r\n // Ignore\r\n " +
"}\r\n }\r\n }\r\n }\r\n }\r\n\r\n " +
" vm = new statusViewModel(sessionId);\r\n ko.applyBindings(vm, view[0]);\r\n\r" +
"\n // Start Live Connection\r\n updateWithLive();\r\n\r\n function" +
" updateWithAjax(onSuccess) {\r\n $.ajax({\r\n url: session" +
"StatusUrl,\r\n dataType: \'json\',\r\n type: \'POST\',\r\n " +
" traditional: true,\r\n success: update_Received,\r\n " +
" error: function (jqXHR, textStatus, errorThrown) {\r\n " +
" alert(\'Unable to load Session: \' + errorThrown);\r\n }\r\n " +
" });\r\n }\r\n function updateWithLive() {\r\n liveConne" +
"ction = $.connection(\'");
#line 249 "..\..\Views\Update\Index.cshtml"
Write(Url.Content("~/API/Logging/TaskStatusNotifications"));
#line default
#line hidden
WriteLiteral(@"');
liveConnection.received(update_Received);
liveConnection.start(function () {
liveConnection.send('/addToGroups:' + sessionId);
updateWithAjax();
});
}
function update_Received(taskStatus) {
vm.Update(taskStatus);
}
});
</script>
");
}
}
}
#pragma warning restore 1591
+37 -34
View File
@@ -1,35 +1,38 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- For more information on using Web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 --> <!-- For more information on using Web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!-- <!--
In the example below, the "SetAttributes" transform will change the value of In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator "connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an atrribute "name" that has a value of "MyDB". finds an atrribute "name" that has a value of "MyDB".
<connectionStrings> <connectionStrings>
<add name="MyDB" <add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings> </connectionStrings>
--> -->
<connectionStrings xdt:Transform="Remove" /> <connectionStrings xdt:Transform="Remove" />
<system.web> <appSettings>
<compilation xdt:Transform="RemoveAttributes(debug)" /> <add key="DiscoIgnoreVersionUpdate" xdt:Transform="Remove" xdt:Locator="Match(key)" />
<!-- </appSettings>
In the example below, the "Replace" transform will replace the entire <system.web>
<customErrors> section of your Web.config file. <compilation xdt:Transform="RemoveAttributes(debug)" />
Note that because there is only one customErrors section under the <!--
<system.web> node, there is no need to use the "xdt:Locator" attribute. In the example below, the "Replace" transform will replace the entire
<customErrors> section of your Web.config file.
<customErrors defaultRedirect="GenericError.htm" Note that because there is only one customErrors section under the
mode="RemoteOnly" xdt:Transform="Replace"> <system.web> node, there is no need to use the "xdt:Locator" attribute.
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors> <customErrors defaultRedirect="GenericError.htm"
--> mode="RemoteOnly" xdt:Transform="Replace">
</system.web> <error statusCode="500" redirect="InternalError.htm"/>
<system.webServer> </customErrors>
<modules xdt:Transform="Remove" /> -->
</system.webServer> </system.web>
<system.webServer>
<modules xdt:Transform="Remove" />
</system.webServer>
</configuration> </configuration>
+83 -82
View File
@@ -1,83 +1,84 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<configSections> <configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections> </configSections>
<appSettings> <appSettings>
<add key="webpages:Version" value="2.0.0.0" /> <add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" /> <add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" /> <add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" /> <add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings> <add key="DiscoIgnoreVersionUpdate" value="false" />
<connectionStrings> </appSettings>
<add name="DiscoDataContext" connectionString="data source=(local);Initial Catalog=Disco;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" /> <connectionStrings>
</connectionStrings> <add name="DiscoDataContext" connectionString="data source=(local);Initial Catalog=Disco;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
<system.web> </connectionStrings>
<compilation debug="true" targetFramework="4.5" /> <system.web>
<httpRuntime targetFramework="4.5" /> <compilation debug="true" targetFramework="4.5" />
<authentication mode="Windows" /> <httpRuntime targetFramework="4.5" />
<customErrors mode="Off" /> <authentication mode="Windows" />
<pages controlRenderingCompatibilityVersion="4.0"> <customErrors mode="Off" />
<namespaces> <pages controlRenderingCompatibilityVersion="4.0">
<add namespace="System.Web.Helpers" /> <namespaces>
<add namespace="System.Web.Mvc" /> <add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Routing" /> <add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.WebPages" /> <add namespace="System.Web.Routing" />
<add namespace="Disco.BI.Extensions" /> <add namespace="System.Web.WebPages" />
<add namespace="Disco.Web.Extensions" /> <add namespace="Disco.BI.Extensions" />
</namespaces> <add namespace="Disco.Web.Extensions" />
</pages> </namespaces>
</system.web> </pages>
<system.webServer> </system.web>
<handlers> <system.webServer>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" /> <handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" /> <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<!--<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />--> <!--<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />-->
<add name="ExtensionlessUrlHandler-Integrated-4.0-PluginResources" path="/Plugin/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers> <add name="ExtensionlessUrlHandler-Integrated-4.0-PluginResources" path="/Plugin/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</system.webServer> </handlers>
<runtime> </system.webServer>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <runtime>
<dependentAssembly> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" /> <dependentAssembly>
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
</dependentAssembly> <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
<dependentAssembly> </dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> <dependentAssembly>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
</dependentAssembly> <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
<dependentAssembly> </dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" /> <dependentAssembly>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
</dependentAssembly> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
<dependentAssembly> </dependentAssembly>
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" /> <dependentAssembly>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
</dependentAssembly> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
<dependentAssembly> </dependentAssembly>
<assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral" /> <dependentAssembly>
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" /> <assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral" />
</dependentAssembly> <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</assemblyBinding> </dependentAssembly>
</runtime> </assemblyBinding>
<entityFramework> </runtime>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework"> <entityFramework>
<parameters> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework">
<parameter value="System.Data.SqlServerCe.4.0" /> <parameters>
</parameters> <parameter value="System.Data.SqlServerCe.4.0" />
</defaultConnectionFactory> </parameters>
</entityFramework> </defaultConnectionFactory>
<system.data> </entityFramework>
<DbProviderFactories> <system.data>
<remove invariant="System.Data.SqlServerCe.4.0" /> <DbProviderFactories>
<add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" /> <remove invariant="System.Data.SqlServerCe.4.0" />
</DbProviderFactories> <add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
</system.data> </DbProviderFactories>
</system.data>
</configuration> </configuration>