├── AWS-RedisOfficeStateProvider-Starter ├── README.md └── src │ ├── AWS-RedisOfficeStateProvider-Starter.sln │ └── AWS-RedisOfficeStateProvider-Starter │ ├── AWS-RedisOfficeStateProvider-Starter.csproj │ ├── Global.asax │ ├── Global.asax.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── RichEdit.aspx │ ├── RichEdit.aspx.cs │ ├── Spreadsheet.aspx │ ├── Spreadsheet.aspx.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ └── Web.config ├── AWS-SqlOfficeStateProvider-Starter ├── README.md └── src │ ├── AWS-SqlOfficeStateProvider-Starter.sln │ └── AWS-SqlOfficeStateProvider-Starter │ ├── AWS-SqlOfficeStateProvider-Starter.csproj │ ├── Global.asax │ ├── Global.asax.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── RichEdit.aspx │ ├── RichEdit.aspx.cs │ ├── Spreadsheet.aspx │ ├── Spreadsheet.aspx.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ └── Web.config ├── Azure-RedisOfficeStateProvider-Starter ├── README.md └── src │ ├── Azure-RedisOfficeStateProvider-Starter.sln │ ├── Azure-RedisOfficeStateProvider-Starter │ ├── Azure-RedisOfficeStateProvider-Starter.ccproj │ ├── ServiceConfiguration.Cloud.cscfg │ ├── ServiceConfiguration.Local.cscfg │ ├── ServiceDefinition.csdef │ └── WebServerContent │ │ └── diagnostics.wadcfgx │ └── WebServer │ ├── App_Code │ └── RedisLogger.cs │ ├── App_Data │ └── WorkDirectory │ │ └── README.md │ ├── Global.asax │ ├── Properties │ └── AssemblyInfo.cs │ ├── RichEdit.aspx │ ├── RichEdit.aspx.cs │ ├── RichEdit.aspx.designer.cs │ ├── Spreadsheet.aspx │ ├── Spreadsheet.aspx.cs │ ├── Spreadsheet.aspx.designer.cs │ ├── Web.config │ ├── WebRole.cs │ └── WebServer.csproj ├── Azure-SessionAffinity-Starter ├── README.md └── src │ ├── Azure-SessionAffinity-Starter.sln │ ├── Azure.CloudService.Documents │ ├── Azure.CloudService.Documents.ccproj │ ├── Azure.WebRole.DocumentSiteContent │ │ └── diagnostics.wadcfgx │ ├── Azure.WebRole.RoutingContent │ │ └── diagnostics.wadcfgx │ ├── ServiceConfiguration.Cloud.cscfg │ ├── ServiceConfiguration.Local.cscfg │ └── ServiceDefinition.csdef │ ├── Azure.WebRole.DocumentSite │ ├── App_Code │ │ ├── DocumentsDB │ │ │ ├── Documents.cs │ │ │ └── DocumentsConnectionStrings.cs │ │ ├── Hibernation │ │ │ └── HibernationSettings.cs │ │ ├── UI │ │ │ └── RibbonHelper.cs │ │ └── WebRoleConfiguration.cs │ ├── Azure.WebRole.DocumentSite.csproj │ ├── Default.aspx │ ├── Default.aspx.cs │ ├── Default.aspx.designer.cs │ ├── Diagnostic │ │ ├── Default.aspx │ │ ├── Default.aspx.cs │ │ ├── Default.aspx.designer.cs │ │ ├── Diagnostic.ascx │ │ ├── Diagnostic.ascx.cs │ │ └── Diagnostic.ascx.designer.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── HealthCheck.txt │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── RichEdit.aspx │ ├── RichEdit.aspx.cs │ ├── RichEdit.aspx.designer.cs │ ├── Setup │ │ ├── InstallAppInitializationModule.cmd │ │ └── SetUpAppPoolsToEnable32BitApplications.cmd │ ├── Spreadsheet.aspx │ ├── Spreadsheet.aspx.cs │ ├── Spreadsheet.aspx.designer.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── WebRole.cs │ └── packages.config │ ├── Azure.WebRole.Routing │ ├── App_Code │ │ └── WebRoleConfiguration.cs │ ├── Azure.WebRole.Routing.csproj │ ├── Global.asax │ ├── Global.asax.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Setup │ │ ├── ExternalDiskCache_amd64_en-US.msi │ │ ├── InstallARR.cmd │ │ ├── InstallAppInitializationModule.cmd │ │ ├── SetUpAppPoolsAlwaysRunning.cmd │ │ ├── requestRouter_x64.msi │ │ ├── rewrite_amd64_en-US.msi │ │ └── webfarm_v1.1_amd64_en_us.msi │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── WebRole.cs │ ├── default.aspx │ ├── default.aspx.cs │ ├── default.aspx.designer.cs │ ├── packages.config │ └── setup.cmd │ ├── DB.Documents.DAL │ ├── App.config │ ├── Context.cs │ ├── DB.Documents.DAL.csproj │ ├── Model.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Repository.cs │ ├── UnitOfWork.cs │ └── packages.config │ ├── Database │ ├── Documents.mdf │ └── HibernationStorage.mdf │ ├── DevExpress.Web.DatabaseHibernationProvider │ ├── App.config │ ├── DatabaseOfficeWorkSessionStorage.cs │ ├── DatabaseWorksessionHibernationProvider.cs │ ├── DevExpress.Web.DatabaseHibernationProvider.csproj │ ├── HibernatedItem.cs │ ├── HibernatedItemsStorageSettings.cs │ ├── HibernatetItemsStorage.cs │ └── Properties │ │ └── AssemblyInfo.cs │ ├── DevExpress.Web.OfficeAzureCommunication │ ├── AzureServiceBus │ │ ├── Contract.cs │ │ ├── Message.cs │ │ ├── ServiceBus.cs │ │ └── Settings.cs │ ├── DevExpress.Web.OfficeAzureCommunication.csproj │ ├── Diagnostic │ │ ├── Logger.cs │ │ └── WorkSessionServerView.cs │ ├── InterRoleCommunicator.cs │ ├── MessageProcessing │ │ └── MessageDispatcher.cs │ ├── PingService │ │ ├── PingService.cs │ │ ├── Settings.cs │ │ └── TimeoutService.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── RoutingTable │ │ ├── RoutingTable.cs │ │ ├── RoutingTableSerializer.cs │ │ ├── ServerListStateChangedController.cs │ │ ├── Settings.cs │ │ ├── WorkSessionServerInfo │ │ │ ├── WorkSessionInfo.cs │ │ │ └── WorkSessionServerInfo.cs │ │ └── WorkSessionServerState.cs │ ├── Utils │ │ ├── CommandLineUtils.cs │ │ ├── ConfigurationKeys.cs │ │ ├── NetUtils.cs │ │ ├── RoleInstanceUtils.cs │ │ └── ServiceConfigUtils.cs │ ├── WorkSessionMessenger.cs │ └── packages.config │ ├── DevExpress.Web.OfficeAzureDocumentServer │ ├── DevExpress.Web.OfficeAzureDocumentServer.csproj │ ├── OfficeAzureDocumentServer.cs │ └── Properties │ │ └── AssemblyInfo.cs │ └── DevExpress.Web.OfficeAzureRoutingServer │ ├── Configuration.cs │ ├── DevExpress.Web.OfficeAzureRoutingServer.csproj │ ├── IISWebFarmConfiguration │ ├── ConfigurationElementUtils.cs │ ├── ConfigurationManager.cs │ ├── IISUrlRewriterConfigurationUtils.cs │ └── IISWebFarmConfigurationUtils.cs │ ├── OfficeAzureRoutingServer.cs │ ├── Properties │ └── AssemblyInfo.cs │ └── Routing │ ├── ARRHashHelper.cs │ ├── CustomHandler.cs │ ├── HeaderCookieHelper.cs │ ├── RoutingModule.cs │ └── RoutingModuleBase.cs ├── Azure-SqlOfficeStateProvider-Starter ├── README.md └── src │ ├── Azure-SqlOfficeStateProvider-Starter.sln │ ├── Azure-SqlOfficeStateProvider-Starter │ ├── Azure-SqlOfficeStateProvider-Starter.ccproj │ ├── ServiceConfiguration.Cloud.cscfg │ ├── ServiceConfiguration.Local.cscfg │ ├── ServiceDefinition.csdef │ └── WebServerContent │ │ └── diagnostics.wadcfgx │ └── WebServer │ ├── App_Data │ └── WorkDirectory │ │ └── README.md │ ├── Global.asax │ ├── Properties │ └── AssemblyInfo.cs │ ├── RichEdit.aspx │ ├── RichEdit.aspx.cs │ ├── RichEdit.aspx.designer.cs │ ├── Spreadsheet.aspx │ ├── Spreadsheet.aspx.cs │ ├── Spreadsheet.aspx.designer.cs │ ├── Web.config │ ├── WebRole.cs │ ├── WebServer.csproj │ └── packages.config ├── LICENSE ├── README.md ├── RedisOfficeStateProvider ├── README.md └── src │ ├── DevExpress.Web.RedisOfficeStateProvider.csproj │ ├── Diagnostics │ ├── DiagnosticEvents.cs │ └── RedisConnectionLogger.cs │ ├── Exceptions.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Provider.cs │ ├── RedisConnection.cs │ ├── RedisImplementation.cs │ ├── Storage.cs │ ├── TryRepeater.cs │ └── packages.config └── SqlOfficeStateProvider ├── README.md └── src ├── DevExpress.Web.SQLOfficeStateProvider.csproj ├── Exceptions.cs ├── Properties └── AssemblyInfo.cs ├── Provider.cs ├── SqlImplementation.cs ├── Storage.cs ├── TryRepeater.cs └── sql └── init.sql /AWS-RedisOfficeStateProvider-Starter/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This example demonstrates how to use the DevExpress ASP.NET Spreadsheet and Rich Text Editor controls with the Redis Document State Provider in Amazon Web Services. 4 | 5 | # Structure 6 | 7 | This solution contains a single project - a simple ASP.NET web application that can be deployed to the [AWS Elastic Beanstalk](https://aws.amazon.com/elasticbeanstalk/) environment. 8 | 9 | The project has the following pages: 10 | * **RichEdit.aspx** - Contains a single ASPxRichEdit control. No additional markup or code is needed. 11 | * **Spreadsheet.aspx** - Contains a single ASPxSpreadsheet control. No additional markup or code is needed. 12 | 13 | This project additionally contains: 14 | * **Web.config** - A standard Web.config file with DevExpress control registrations and a State Storage connection string. 15 | * **Global.asax** - A standard Global.asax file with the RedisOfficeStateProvider registration in the *Application_Start* method. 16 | 17 | ## References 18 | 19 | This solution references the DevExpress ASP.NET controls and the *RedisOfficeStateProvider* project. 20 | 21 | # Requirements 22 | 23 | No additional software has to be installed to open the project in the Microsoft Visual Studio environment. 24 | 25 | # How to use it 26 | 27 | >Note: Amazon Web Services is a paid commercial product which may include usage charges. Refer to the official [AWS website](https://aws.amazon.com/) for further details. 28 | 29 | 1. Install the DevExpress ASP.NET Controls. You can download the installation from the [DevExpress website page](https://www.devexpress.com/Home/try.xml). 30 | 2. Download the current solution's source files. 31 | 3. Download the RedisOfficeStateProvider project's source files. 32 | 4. Ensure that the reference to the RedisOfficeStateProvider project is working. 33 | 5. Create a Redis data store in [Amazon ElastiCache](https://aws.amazon.com/elasticache/). 34 | 6. Add a connection string to the Redis data store (deployed to the Amazon ElastiCache) to the Web.config file. 35 | 7. Publish the solution to AWS Elastic Beanstalk using your AWS credentials (refer to the official [AWS website](https://aws.amazon.com/) for details). 36 | 37 | To test all advantages of the stateless mode, the web site should be deployed as a multi-instance environment. 38 | 39 | After the publishing process is completed, you can open the RichEdit.aspx or Spreadsheet.aspx pages to access the corresponding controls. Different requests may be processed on different web server instances. The document states are stored within the Redis Cache in Amazon ElastiCache. You can modify the web servers, reboot some of them, increase or decrease their number, and continue working with the same documents. 40 | 41 | # Contacts 42 | 43 | If you have any feedback, contact us at support@devexpress.com. 44 | -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2020 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWS-RedisOfficeStateProvider-Starter", "AWS-RedisOfficeStateProvider-Starter\AWS-RedisOfficeStateProvider-Starter.csproj", "{7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevExpress.Web.RedisOfficeStateProvider", "..\..\RedisOfficeStateProvider\src\DevExpress.Web.RedisOfficeStateProvider.csproj", "{15DAB813-0130-44D2-8C22-A676BF4C5DD3}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {794A5A08-E982-43A1-8BB1-A4F374F0B6A1} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="AWS_RedisOfficeStateProvider_Starter.Global_asax" Language="C#" %> -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | 4 | namespace AWS_RedisOfficeStateProvider_Starter 5 | { 6 | public class Global_asax : System.Web.HttpApplication 7 | { 8 | void Application_Start(object sender, EventArgs e) 9 | { 10 | DevExpress.Web.ASPxWebControl.CallbackError += new EventHandler(Application_Error); 11 | var redisConnectionString = ConfigurationManager.ConnectionStrings["RedisStateStorageConnectionString"].ConnectionString; 12 | var provider = new DevExpress.Web.RedisOfficeStateProvider.RedisOfficeStateProvider(redisConnectionString); 13 | DevExpress.Web.Office.DocumentManager.StateProvider = provider; 14 | } 15 | void Application_End(object sender, EventArgs e) 16 | { 17 | // Code that runs on application shutdown 18 | } 19 | 20 | void Application_Error(object sender, EventArgs e) 21 | { 22 | // Code that runs when an unhandled error occurs 23 | } 24 | 25 | void Session_Start(object sender, EventArgs e) 26 | { 27 | // Code that runs when a new session is started 28 | } 29 | 30 | void Session_End(object sender, EventArgs e) 31 | { 32 | // Code that runs when a session ends. 33 | // Note: The Session_End event is raised only when the sessionstate mode 34 | // is set to InProc in the Web.config file. If session mode is set to StateServer 35 | // or SQLServer, the event is not raised. 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AWS-RedisOfficeStateProvider-Starter")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AWS-RedisOfficeStateProvider-Starter")] 13 | [assembly: AssemblyCopyright("Copyright ? 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("34cc899b-dcd6-4a34-80b2-56e7a645260c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter/RichEdit.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RichEdit.aspx.cs" Inherits="AWS_RedisOfficeStateProvider_Starter.RichEdit" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.ASPxRichEdit.v20.1, Version=20.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxRichEdit" TagPrefix="dx" %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter/RichEdit.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace AWS_RedisOfficeStateProvider_Starter 9 | { 10 | public partial class RichEdit : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter/Spreadsheet.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Spreadsheet.aspx.cs" Inherits="AWS_RedisOfficeStateProvider_Starter.Spreadsheet" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.ASPxSpreadsheet.v20.1, Version=20.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxSpreadsheet" TagPrefix="dx" %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter/Spreadsheet.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace AWS_RedisOfficeStateProvider_Starter 9 | { 10 | public partial class Spreadsheet : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /AWS-RedisOfficeStateProvider-Starter/src/AWS-RedisOfficeStateProvider-Starter/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This example demonstrates how to use the DevExpress ASP.NET Spreadsheet and Rich Text Editor controls with the SQL Document State Provider in Amazon Web Services. 4 | 5 | # Structure 6 | 7 | This solution contains a single project - a simple ASP.NET web application that can be deployed to the [AWS Elastic Beanstalk](https://aws.amazon.com/elasticbeanstalk/) environment. 8 | 9 | The project has the following pages: 10 | * **RichEdit.aspx** - Contains a single ASPxRichEdit control. No additional markup or code is needed. 11 | * **Spreadsheet.aspx** - Contains a single ASPxSpreadsheet control. No additional markup or code is needed. 12 | 13 | This project additionally contains: 14 | * **Web.config** - A standard Web.config file with DevExpress control registrations and a State Storage connection string. 15 | * **Global.asax** - A standard Global.asax file with the SqlOfficeStateProvider registration in the *Application_Start* method. 16 | 17 | ## References 18 | 19 | This solution references the DevExpress ASP.NET controls and the *SqlOfficeStateProvider* project. 20 | 21 | # Requirements 22 | 23 | No additional software has to be installed to open the project in the Microsoft Visual Studio environment. 24 | 25 | # How to use it 26 | 27 | >Note: Amazon Web Services is a paid commercial product which may include usage charges. Refer to the official [AWS website](https://aws.amazon.com/) for further details. 28 | 29 | 1. Install the DevExpress ASP.NET Controls. You can download the installation from the [DevExpress site page](https://www.devexpress.com/Home/try.xml). 30 | 2. Download the current solution's source files. 31 | 3. Download the SqlOfficeStateProvider project's source files. 32 | 4. Ensure that the reference to the SqlOfficeStateProvider project is working. 33 | 5. Create a Microsoft SQL Server Database in the [Amazon Relational Database Service (RDS)](https://aws.amazon.com/rds/), and copy the database connection string (it will be used in the following steps). 34 | 6. Connect your local *Microsoft SQL Server Management Studio* to the Microsoft SQL Server on Amazon RDS and run the initialization script (SqlOfficeStateProvider/sql/init.sql) against the new database. 35 | 7. Insert the copied connection string into the Web.config file. 36 | 8. Publish the solution to AWS Elastic Beanstalk using your AWS credentials (refer to the official [AWS website](https://aws.amazon.com/) for details). 37 | 38 | To test all advantages of the stateless mode, the web site should be deployed as a multi-instance environment. 39 | 40 | After the publishing process is completed, you can open the RichEdit.aspx or Spreadsheet.aspx pages to access the corresponding controls. Different requests may be processed on different web server instances. The document states are stored within the Microsoft SQL Server database. You can modify the web servers, reboot some of them, increase or decrease their number, and continue working with the same documents. 41 | 42 | # Contacts 43 | 44 | If you have any feedback, contact us at support@devexpress.com. 45 | -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2020 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWS-SqlOfficeStateProvider-Starter", "AWS-SqlOfficeStateProvider-Starter\AWS-SqlOfficeStateProvider-Starter.csproj", "{7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevExpress.Web.SQLOfficeStateProvider", "..\..\SqlOfficeStateProvider\src\DevExpress.Web.SQLOfficeStateProvider.csproj", "{15DAB813-0130-44D2-8C22-A676BF4C5DD3}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {7ADF0D25-F473-4F61-A0C5-61ACB9B9C9F4}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {794A5A08-E982-43A1-8BB1-A4F374F0B6A1} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="AWS_SqlOfficeStateProvider_Starter.Global_asax" Language="C#" %> -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | 4 | namespace AWS_SqlOfficeStateProvider_Starter 5 | { 6 | public class Global_asax : System.Web.HttpApplication 7 | { 8 | void Application_Start(object sender, EventArgs e) 9 | { 10 | DevExpress.Web.ASPxWebControl.CallbackError += new EventHandler(Application_Error); 11 | var sqlConnectionString = ConfigurationManager.ConnectionStrings["SqlStateStorageConnectionString"].ConnectionString; 12 | var provider = new DevExpress.Web.SqlOfficeStateProvider.SqlOfficeStateProvider(sqlConnectionString); 13 | DevExpress.Web.Office.DocumentManager.StateProvider = provider; 14 | } 15 | void Application_End(object sender, EventArgs e) 16 | { 17 | // Code that runs on application shutdown 18 | } 19 | 20 | void Application_Error(object sender, EventArgs e) 21 | { 22 | // Code that runs when an unhandled error occurs 23 | } 24 | 25 | void Session_Start(object sender, EventArgs e) 26 | { 27 | // Code that runs when a new session is started 28 | } 29 | 30 | void Session_End(object sender, EventArgs e) 31 | { 32 | // Code that runs when a session ends. 33 | // Note: The Session_End event is raised only when the sessionstate mode 34 | // is set to InProc in the Web.config file. If session mode is set to StateServer 35 | // or SQLServer, the event is not raised. 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AWS-SqlOfficeStateProvider-Starter")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AWS-SqlOfficeStateProvider-Starter")] 13 | [assembly: AssemblyCopyright("Copyright ? 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("34cc899b-dcd6-4a34-80b2-56e7a645260c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter/RichEdit.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RichEdit.aspx.cs" Inherits="AWS_SqlOfficeStateProvider_Starter.RichEdit" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.ASPxRichEdit.v20.1, Version=20.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxRichEdit" TagPrefix="dx" %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter/RichEdit.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace AWS_SqlOfficeStateProvider_Starter 9 | { 10 | public partial class RichEdit : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter/Spreadsheet.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Spreadsheet.aspx.cs" Inherits="AWS_SqlOfficeStateProvider_Starter.Spreadsheet" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.ASPxSpreadsheet.v20.1, Version=20.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxSpreadsheet" TagPrefix="dx" %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter/Spreadsheet.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace AWS_SqlOfficeStateProvider_Starter 9 | { 10 | public partial class Spreadsheet : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /AWS-SqlOfficeStateProvider-Starter/src/AWS-SqlOfficeStateProvider-Starter/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/Azure-RedisOfficeStateProvider-Starter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{CC5FD16D-436D-48AD-A40C-5A424C6E3E79}") = "Azure-RedisOfficeStateProvider-Starter", "Azure-RedisOfficeStateProvider-Starter\Azure-RedisOfficeStateProvider-Starter.ccproj", "{2B8E8938-680E-41B3-9894-0C9B51BADEA6}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebServer", "WebServer\WebServer.csproj", "{23B4E0DA-A5E7-4808-BB3A-67AA5DE0637D}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevExpress.Web.RedisOfficeStateProvider", "..\..\RedisOfficeStateProvider\src\DevExpress.Web.RedisOfficeStateProvider.csproj", "{7EDA111E-ECA2-49FF-8AA3-868E0AF4D1B8}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {2B8E8938-680E-41B3-9894-0C9B51BADEA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {2B8E8938-680E-41B3-9894-0C9B51BADEA6}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {2B8E8938-680E-41B3-9894-0C9B51BADEA6}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {2B8E8938-680E-41B3-9894-0C9B51BADEA6}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {23B4E0DA-A5E7-4808-BB3A-67AA5DE0637D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {23B4E0DA-A5E7-4808-BB3A-67AA5DE0637D}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {23B4E0DA-A5E7-4808-BB3A-67AA5DE0637D}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {23B4E0DA-A5E7-4808-BB3A-67AA5DE0637D}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {7EDA111E-ECA2-49FF-8AA3-868E0AF4D1B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {7EDA111E-ECA2-49FF-8AA3-868E0AF4D1B8}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {7EDA111E-ECA2-49FF-8AA3-868E0AF4D1B8}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {7EDA111E-ECA2-49FF-8AA3-868E0AF4D1B8}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(NestedProjects) = preSolution 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/Azure-RedisOfficeStateProvider-Starter/ServiceConfiguration.Cloud.cscfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/Azure-RedisOfficeStateProvider-Starter/ServiceConfiguration.Local.cscfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/Azure-RedisOfficeStateProvider-Starter/ServiceDefinition.csdef: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/Azure-RedisOfficeStateProvider-Starter/WebServerContent/diagnostics.wadcfgx: -------------------------------------------------------------------------------- 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 | false 40 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/App_Data/WorkDirectory/README.md: -------------------------------------------------------------------------------- 1 | Put your test office document here. -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Language="C#" %> 2 | 3 | 67 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebServer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WebServer")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("23b4e0da-a5e7-4808-bb3a-67aa5de0637d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/RichEdit.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RichEdit.aspx.cs" Inherits="WebServer.RichEdit" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.ASPxRichEdit.v20.1, Version=20.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxRichEdit" TagPrefix="dx" %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/RichEdit.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace WebServer 9 | { 10 | public partial class RichEdit : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/RichEdit.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace WebServer { 11 | 12 | 13 | public partial class RichEdit { 14 | 15 | /// 16 | /// form1 control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 23 | 24 | /// 25 | /// ASPxRichEdit1 control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::DevExpress.Web.ASPxRichEdit.ASPxRichEdit ASPxRichEdit1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/Spreadsheet.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Spreadsheet.aspx.cs" Inherits="WebServer.Spreadsheet" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.ASPxSpreadsheet.v20.1, Version=20.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxSpreadsheet" TagPrefix="dx" %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/Spreadsheet.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace WebServer 9 | { 10 | public partial class Spreadsheet : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/Spreadsheet.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace WebServer { 11 | 12 | 13 | public partial class Spreadsheet { 14 | 15 | /// 16 | /// form1 control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 23 | 24 | /// 25 | /// ASPxSpreadsheet1 control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::DevExpress.Web.ASPxSpreadsheet.ASPxSpreadsheet ASPxSpreadsheet1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Azure-RedisOfficeStateProvider-Starter/src/WebServer/WebRole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.WindowsAzure; 5 | using Microsoft.WindowsAzure.Diagnostics; 6 | using Microsoft.WindowsAzure.ServiceRuntime; 7 | 8 | namespace WebServer 9 | { 10 | public class WebRole : RoleEntryPoint 11 | { 12 | public override bool OnStart() 13 | { 14 | // For information on handling configuration changes 15 | // see the MSDN topic at https://go.microsoft.com/fwlink/?LinkId=166357. 16 | 17 | return base.OnStart(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.CloudService.Documents/Azure.WebRole.DocumentSiteContent/diagnostics.wadcfgx: -------------------------------------------------------------------------------- 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 | false 50 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.CloudService.Documents/Azure.WebRole.RoutingContent/diagnostics.wadcfgx: -------------------------------------------------------------------------------- 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 | false 42 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.CloudService.Documents/ServiceConfiguration.Cloud.cscfg: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.CloudService.Documents/ServiceConfiguration.Local.cscfg: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.CloudService.Documents/ServiceDefinition.csdef: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/App_Code/DocumentsDB/DocumentsConnectionStrings.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure; 2 | 3 | namespace DocumentSite { 4 | public static class DocumentsConnectionStrings { 5 | static string CONNECTION_STRING_KEY = "DocumentsConnectionString"; 6 | 7 | public static string Current { 8 | get { return CloudConfigurationManager.GetSetting(CONNECTION_STRING_KEY); } 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/App_Code/UI/RibbonHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using DevExpress.Web; 6 | using DevExpress.Web.ASPxRichEdit; 7 | using DevExpress.Web.ASPxSpreadsheet; 8 | 9 | namespace DocumentSite { 10 | public static class RibbonHelper { 11 | public static void HideFileTab(ASPxSpreadsheet spreadsheet) { 12 | spreadsheet.CreateDefaultRibbonTabs(true); 13 | RemoveRibbonTab(spreadsheet.RibbonTabs, typeof(SRFileTab)); 14 | spreadsheet.ActiveTabIndex = 0; 15 | } 16 | public static void HideFileTab(ASPxRichEdit richedit) { 17 | richedit.CreateDefaultRibbonTabs(true); 18 | RemoveRibbonTab(richedit.RibbonTabs, typeof(RERFileTab)); 19 | richedit.ActiveTabIndex = 0; 20 | } 21 | static void RemoveRibbonTab(Collection ribbonTabs, Type tabTypeToRemove) { 22 | foreach(RibbonTab tab in ribbonTabs) { 23 | if(tab.GetType() == tabTypeToRemove) { 24 | ribbonTabs.Remove(tab); 25 | break; 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Default.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DocumentSite._Default" %> 2 | 3 | <%@ Register Src="~/Diagnostic/Diagnostic.ascx" TagPrefix="uc1" TagName="Diagnostic" %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Default.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | using DevExpress.Web; 4 | using DevExpress.Web.OfficeAzureCommunication; 5 | using DevExpress.Web.ASPxRichEdit; 6 | using DevExpress.Web.ASPxSpreadsheet; 7 | using DevExpress.Web.Office; 8 | using DB.Documents.DAL; 9 | 10 | namespace DocumentSite { 11 | public partial class _Default : System.Web.UI.Page { 12 | protected DocumentItemInfo DocumentViewModel { 13 | get { 14 | return new DocumentItemInfo(this.Page.GetDataItem() as Item); 15 | } 16 | } 17 | 18 | protected void Page_Init(object sender, EventArgs e) { 19 | ProcessRequest(HttpContext.Current.Request); 20 | } 21 | 22 | protected void Page_Load(object sender, EventArgs e) { 23 | var unitOfWork = new DocumentsUnitOfWork(); 24 | 25 | Repeater1.DataSource = unitOfWork.ItemRepository.Get(); 26 | Repeater1.DataBind(); 27 | } 28 | 29 | private void ProcessRequest(HttpRequest httpRequest) { 30 | if(DocumentRequestParams.RedirectRequired) { 31 | var workSessionInfo = RoutingTable.GetWorkSessionInfoByDocumentID(DocumentRequestParams.DocumentID); 32 | var workSessionID = workSessionInfo != null ? workSessionInfo.WorkSessionID : Guid.Empty; 33 | if(workSessionID == Guid.Empty) 34 | workSessionID = OpenDocumentID(DocumentRequestParams.DocumentID); 35 | if(workSessionID != Guid.Empty) 36 | Response.Redirect(DocumentRequestParams.GetRedirectUrl(workSessionID.ToString()), true); 37 | } 38 | } 39 | 40 | private Guid OpenDocumentID(string documentID) { 41 | var unitOfWork = new DocumentsUnitOfWork(); 42 | 43 | var documentItem = unitOfWork.ItemRepository.GetByID(long.Parse(documentID)); 44 | var documentItemInfo = new DocumentItemInfo(documentItem); 45 | 46 | var editorType = documentItemInfo.DocumentProcessorType; 47 | OfficeWorkSessionControl editor = null; 48 | 49 | if(editorType == OfficeDocumentProcessorType.Spreadsheet) { 50 | var spreadsheetControl = new ASPxSpreadsheet(); 51 | spreadsheetControl.Open( 52 | documentItemInfo.Id, 53 | (DevExpress.Spreadsheet.DocumentFormat)DocumentFormatUtils.GetDocumentFormat(documentItemInfo.NameExtension), 54 | () => documentItem.Content.Data); 55 | 56 | editor = spreadsheetControl; 57 | } 58 | 59 | if(editorType == OfficeDocumentProcessorType.RichEdit) { 60 | var richEditControl = new ASPxRichEdit(); 61 | richEditControl.Open( 62 | documentItemInfo.Id, 63 | (DevExpress.XtraRichEdit.DocumentFormat)DocumentFormatUtils.GetDocumentFormat(documentItemInfo.NameExtension), 64 | () => documentItem.Content.Data); 65 | 66 | editor = richEditControl; 67 | } 68 | 69 | return editor.GetWorkSessionID(); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Default.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace DocumentSite { 11 | 12 | 13 | public partial class _Default { 14 | 15 | /// 16 | /// form1 control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 23 | 24 | /// 25 | /// Diagnostic control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::DocumentSite.Diagnostic.Diagnostic Diagnostic; 32 | 33 | /// 34 | /// Repeater1 control. 35 | /// 36 | /// 37 | /// Auto-generated field. 38 | /// To modify move field declaration from designer file to code-behind file. 39 | /// 40 | protected global::System.Web.UI.WebControls.Repeater Repeater1; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Diagnostic/Default.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DocumentSite.Default" %> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Diagnostic/Default.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | using DevExpress.Web.OfficeAzureCommunication; 8 | using Microsoft.WindowsAzure.ServiceRuntime; 9 | 10 | namespace DocumentSite { 11 | public partial class Default : System.Web.UI.Page { 12 | #if DEBUG 13 | protected void Page_Load(object sender, EventArgs e) { 14 | CreateDiagnosticPage(); 15 | } 16 | 17 | private void CreateDiagnosticPage() { 18 | DevExpress.Web.OfficeAzureCommunication.Diagnostic.WorkSessionServerView.CreateDianosticPageControl(log, RoleEnvironment.CurrentRoleInstance.Id); 19 | } 20 | 21 | #endif 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Diagnostic/Default.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace DocumentSite { 11 | 12 | 13 | public partial class Default { 14 | 15 | /// 16 | /// form1 control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 23 | 24 | /// 25 | /// log control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::System.Web.UI.WebControls.Panel log; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Diagnostic/Diagnostic.ascx: -------------------------------------------------------------------------------- 1 | <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Diagnostic.ascx.cs" Inherits="DocumentSite.Diagnostic.Diagnostic" %> 2 | 3 | 4 |
5 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Diagnostic/Diagnostic.ascx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | using Microsoft.WindowsAzure.ServiceRuntime; 8 | 9 | namespace DocumentSite.Diagnostic { 10 | public partial class Diagnostic : System.Web.UI.UserControl { 11 | protected void Page_Init(object sender, EventArgs e) { 12 | LabelInstanceID.Text = RoleEnvironment.CurrentRoleInstance.Id; 13 | LabelMachineName.Text = Environment.MachineName; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Diagnostic/Diagnostic.ascx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace DocumentSite.Diagnostic { 11 | 12 | 13 | public partial class Diagnostic { 14 | 15 | /// 16 | /// LabelInstanceID control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.WebControls.Label LabelInstanceID; 23 | 24 | /// 25 | /// LabelMachineName control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::System.Web.UI.WebControls.Label LabelMachineName; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="DocumentSite.Global" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using DevExpress.Web.OfficeAzureDocumentServer; 3 | using DevExpress.Web.DatabaseHibernationProvider; 4 | using Hibernation; 5 | 6 | namespace DocumentSite { 7 | public class Global : System.Web.HttpApplication { 8 | protected void Application_Start(object sender, EventArgs e) { 9 | OfficeAzureDocumentServer.Init(); 10 | HibernationInit(); 11 | } 12 | 13 | private void HibernationInit() { 14 | DevExpress.Web.Office.Internal.WorkSessionProcessing.SetWorkSessionHibernateProvider(new DatabaseWorksessionHibernationProvider(new HibernationStorageSettingsFromWebConfig())); 15 | DevExpress.Web.Office.DocumentManager.HibernateTimeout = HibernationSettings.HibernateTimeout; 16 | DevExpress.Web.Office.DocumentManager.HibernatedDocumentsDisposeTimeout = HibernationSettings.HibernatedDocumentsDisposeTimeout; 17 | DevExpress.Web.Office.DocumentManager.HibernateAllDocumentsOnApplicationEnd = true; 18 | DevExpress.Web.Office.DocumentManager.EnableHibernation = true; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/HealthCheck.txt: -------------------------------------------------------------------------------- 1 | OK -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Azure.WebRole.DocumentSite")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Azure.WebRole.DocumentSite")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0d250088-8e7f-4d2f-9322-ec06d39d4b31")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/RichEdit.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RichEdit.aspx.cs" Inherits="DocumentSite.RichEdit" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.v20.1" Namespace="DevExpress.Web" TagPrefix="dx" %> 4 | <%@ Register Assembly="DevExpress.Web.ASPxRichEdit.v20.1" Namespace="DevExpress.Web.ASPxRichEdit" TagPrefix="dx" %> 5 | 6 | <%@ Register Src="~/Diagnostic/Diagnostic.ascx" TagPrefix="uc1" TagName="Diagnostic" %> 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/RichEdit.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | using DevExpress.Web.Office; 8 | using Microsoft.WindowsAzure.ServiceRuntime; 9 | 10 | namespace DocumentSite { 11 | public partial class RichEdit : System.Web.UI.Page { 12 | protected void Page_Init(object sender, EventArgs e) { 13 | RibbonHelper.HideFileTab(ASPxRichEdit1); 14 | if(DocumentRequestParams.IsOpeningByWorkSessionID) 15 | (ASPxRichEdit1 as OfficeWorkSessionControl).AttachToWorkSession(Guid.Parse(DocumentRequestParams.WorkSessionID)); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/RichEdit.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace DocumentSite { 11 | 12 | 13 | public partial class RichEdit { 14 | 15 | /// 16 | /// form1 control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 23 | 24 | /// 25 | /// Diagnostic control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::DocumentSite.Diagnostic.Diagnostic Diagnostic; 32 | 33 | /// 34 | /// ASPxRichEdit1 control. 35 | /// 36 | /// 37 | /// Auto-generated field. 38 | /// To modify move field declaration from designer file to code-behind file. 39 | /// 40 | protected global::DevExpress.Web.ASPxRichEdit.ASPxRichEdit ASPxRichEdit1; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Setup/InstallAppInitializationModule.cmd: -------------------------------------------------------------------------------- 1 | Echo Installing Application Initialization module 2 | PKGMGR.EXE /iu:IIS-ApplicationInit -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Setup/SetUpAppPoolsToEnable32BitApplications.cmd: -------------------------------------------------------------------------------- 1 | echo Because all HTTP requests and responses for the content sites go through ARR, the worker process for the Default Web Site should always be running. 2 | FOR /F "tokens=* delims=" %%i in ('%systemroot%\system32\inetsrv\appcmd list apppool /text:name') do ( 3 | echo setting up the apppool: "%%i" 4 | %systemroot%\system32\inetsrv\APPCMD set apppool "%%i" /enable32BitAppOnWin64:true 5 | ) -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Spreadsheet.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Spreadsheet.aspx.cs" Inherits="DocumentSite.Spreadsheet" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.v20.1" Namespace="DevExpress.Web" TagPrefix="dx" %> 4 | <%@ Register Assembly="DevExpress.Web.ASPxSpreadsheet.v20.1" Namespace="DevExpress.Web.ASPxSpreadsheet" TagPrefix="dx" %> 5 | 6 | <%@ Register Src="~/Diagnostic/Diagnostic.ascx" TagPrefix="uc1" TagName="Diagnostic" %> 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Spreadsheet.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | using DevExpress.Spreadsheet.Functions; 8 | using DevExpress.Web.Office; 9 | using Microsoft.WindowsAzure.ServiceRuntime; 10 | 11 | namespace DocumentSite { 12 | public partial class Spreadsheet : System.Web.UI.Page { 13 | protected void Page_Init(object sender, EventArgs e) { 14 | RibbonHelper.HideFileTab(ASPxSpreadsheet1); 15 | if(DocumentRequestParams.IsOpeningByWorkSessionID) 16 | (ASPxSpreadsheet1 as OfficeWorkSessionControl).AttachToWorkSession(Guid.Parse(DocumentRequestParams.WorkSessionID)); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Spreadsheet.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace DocumentSite { 11 | 12 | 13 | public partial class Spreadsheet { 14 | 15 | /// 16 | /// form1 control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 23 | 24 | /// 25 | /// Diagnostic control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::DocumentSite.Diagnostic.Diagnostic Diagnostic; 32 | 33 | /// 34 | /// ASPxSpreadsheet1 control. 35 | /// 36 | /// 37 | /// Auto-generated field. 38 | /// To modify move field declaration from designer file to code-behind file. 39 | /// 40 | protected global::DevExpress.Web.ASPxSpreadsheet.ASPxSpreadsheet ASPxSpreadsheet1; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/WebRole.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.WindowsAzure.ServiceRuntime; 2 | 3 | namespace DocumentSite { 4 | public class WebRole : RoleEntryPoint { 5 | public override bool OnStart() { 6 | WebRoleConfiguration.OnStart(); 7 | return base.OnStart(); 8 | } 9 | 10 | public override void OnStop() { 11 | WebRoleConfiguration.OnStop(); 12 | base.OnStop(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.DocumentSite/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Routing.Global" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using DevExpress.Web.OfficeAzureRoutingServer; 3 | 4 | namespace Routing { 5 | public class Global : System.Web.HttpApplication { 6 | 7 | protected void Application_Start(object sender, EventArgs e) { 8 | OfficeAzureRoutingServer.Init(); 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Azure.WebRole.Routing")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Azure.WebRole.Routing")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("eff69ac4-968d-4c07-b9d2-252a8a14c44e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/ExternalDiskCache_amd64_en-US.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress/aspnet-office-solutions/c50c1aaa0b2928c8805627e31d5a84bb56ab161c/Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/ExternalDiskCache_amd64_en-US.msi -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/InstallARR.cmd: -------------------------------------------------------------------------------- 1 | Echo Setting up Application Request Routing 2 | 3 | 4 | Echo Stop IIS (WAS and WMSVC processes) 5 | net stop was /y 6 | net stop wmsvc /y 7 | 8 | Echo Installing Application Request Routing with requirements 9 | .\setup\webfarm_v1.1_amd64_en_us.msi 10 | .\setup\rewrite_amd64_en-US.msi 11 | .\setup\requestRouter_x64.msi 12 | .\setup\ExternalDiskCache_amd64_en-US.msi 13 | 14 | Echo Stop IIS (WAS and WMSVC processes) 15 | net start was 16 | net start wmsvc 17 | net start w3svc -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/InstallAppInitializationModule.cmd: -------------------------------------------------------------------------------- 1 | Echo Installing Application Initialization module 2 | PKGMGR.EXE /iu:IIS-ApplicationInit -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/SetUpAppPoolsAlwaysRunning.cmd: -------------------------------------------------------------------------------- 1 | echo Because all HTTP requests and responses for the content sites go through ARR, the worker process for the Default Web Site should always be running. 2 | FOR /F "tokens=* delims=" %%i in ('%systemroot%\system32\inetsrv\appcmd list apppool /text:name') do ( 3 | echo setting up the apppool: "%%i" 4 | %systemroot%\system32\inetsrv\APPCMD set apppool "%%i" -processModel.idleTimeout:"00:00:00" /commit:apphost 5 | %systemroot%\system32\inetsrv\APPCMD set apppool "%%i" -recycling.periodicRestart.time:00:00:00 /commit:apphost 6 | ) -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/requestRouter_x64.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress/aspnet-office-solutions/c50c1aaa0b2928c8805627e31d5a84bb56ab161c/Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/requestRouter_x64.msi -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/rewrite_amd64_en-US.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress/aspnet-office-solutions/c50c1aaa0b2928c8805627e31d5a84bb56ab161c/Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/rewrite_amd64_en-US.msi -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/webfarm_v1.1_amd64_en_us.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress/aspnet-office-solutions/c50c1aaa0b2928c8805627e31d5a84bb56ab161c/Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Setup/webfarm_v1.1_amd64_en_us.msi -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 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 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/WebRole.cs: -------------------------------------------------------------------------------- 1 | using DevExpress.Web.OfficeAzureCommunication; 2 | using Microsoft.WindowsAzure.ServiceRuntime; 3 | 4 | namespace Routing { 5 | public class WebRole : RoleEntryPoint { 6 | public override bool OnStart() { 7 | WebRoleConfiguration.OnStart(RoleEnvironmentConfig.DocumentServerRoleName, RoleEnvironmentConfig.DocumentServerPort); 8 | return base.OnStart(); 9 | } 10 | 11 | public override void OnStop() { 12 | WebRoleConfiguration.OnStop(); 13 | base.OnStop(); 14 | } 15 | 16 | public override void Run() { 17 | WebRoleConfiguration.TrackServerChanges(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/default.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="Routing._default" %> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/default.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Web; 6 | using System.Web.UI; 7 | using System.Web.UI.WebControls; 8 | using DevExpress.Web.OfficeAzureCommunication; 9 | using Microsoft.WindowsAzure.ServiceRuntime; 10 | 11 | namespace Azure.WebRole.Routing { 12 | 13 | public partial class _default : System.Web.UI.Page { 14 | protected void Page_Load(object sender, EventArgs e) { 15 | DevExpress.Web.OfficeAzureCommunication.DiagnosticTools.WorkSessionServerView.Create(log, RoleEnvironment.CurrentRoleInstance.Id); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/default.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace Azure.WebRole.Routing { 11 | 12 | 13 | public partial class _default { 14 | 15 | /// 16 | /// form1 control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 23 | 24 | /// 25 | /// log control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::System.Web.UI.WebControls.Panel log; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Azure.WebRole.Routing/setup.cmd: -------------------------------------------------------------------------------- 1 | echo setup 2 | 3 | call ./Setup/InstallAppInitializationModule.cmd 4 | 5 | call ./Setup/InstallARR.cmd -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DB.Documents.DAL/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DB.Documents.DAL/Context.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Entity; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DB.Documents.DAL { 9 | public class DocumentsDbContext : DbContext { 10 | public DocumentsDbContext(string connectionString) : base(connectionString) { } 11 | 12 | public DbSet Items { get; set; } 13 | public DbSet Users { get; set; } 14 | public DbSet BinaryContentSet { get; set; } 15 | 16 | protected override void OnModelCreating(DbModelBuilder modelBuilder) { 17 | var itemConfig = modelBuilder.Entity(); 18 | itemConfig.HasKey(i => i.Id); 19 | itemConfig.Property(i => i.Name).IsRequired(); 20 | itemConfig.Property(i => i.IsFolder).IsRequired(); 21 | itemConfig.HasOptional(i => i.Content); 22 | itemConfig.HasOptional(i => i.Owner); 23 | itemConfig.HasOptional(i => i.ParentItem) 24 | .WithMany(pi => pi.ChildItems); 25 | 26 | var userConfig = modelBuilder.Entity(); 27 | userConfig.HasKey(u => u.Id); 28 | userConfig.Property(u => u.Name).IsRequired(); 29 | userConfig.Property(u => u.AccountName).IsRequired(); 30 | userConfig.HasOptional(u => u.Avatar); 31 | 32 | var binaryContentConfig = modelBuilder.Entity(); 33 | binaryContentConfig.HasKey(bc => bc.Id); 34 | 35 | base.OnModelCreating(modelBuilder); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DB.Documents.DAL/Model.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace DB.Documents.DAL { 5 | 6 | public class Item { 7 | public Item() { 8 | ChildItems = new List(); 9 | } 10 | public long Id { get; set; } 11 | public string Name { get; set; } 12 | public bool IsFolder { get; set; } 13 | public virtual BinaryContent Content { get; set; } 14 | public virtual User Owner { get; set; } 15 | public DateTime CreationTime { get; set; } 16 | public DateTime LastAccessTime { get; set; } 17 | public DateTime LastWriteTime { get; set; } 18 | public virtual List ChildItems { get; set; } 19 | public virtual Item ParentItem { get; set; } 20 | public bool IsRoot { 21 | get { 22 | return ParentItem == null; 23 | } 24 | } 25 | 26 | public void UpdateContent(byte[] content) { 27 | Content.Data = content; 28 | LastWriteTime = DateTime.Now; 29 | } 30 | } 31 | 32 | public class BinaryContent { 33 | public long Id { get; set; } 34 | public virtual byte[] Data { get; set; } 35 | } 36 | 37 | public class User { 38 | public long Id { get; set; } 39 | public string AccountName { get; set; } 40 | public string Name { get; set; } 41 | public string Password { get; set; } 42 | public virtual BinaryContent Avatar { get; set; } 43 | } 44 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DB.Documents.DAL/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DB.DAL")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DB.DAL")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a01e242e-ff67-4453-9f03-9029440b90bd")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DB.Documents.DAL/Repository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Entity; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DB.Documents.DAL { 10 | public class GenericRepository where TEntity : class { 11 | internal DbContext context; 12 | internal DbSet dbSet; 13 | 14 | public GenericRepository(DbContext context) { 15 | this.context = context; 16 | this.dbSet = context.Set(); 17 | } 18 | 19 | public virtual IEnumerable Get( 20 | Expression> filter = null, 21 | Func, IOrderedQueryable> orderBy = null, 22 | string includeProperties = "") { 23 | IQueryable query = dbSet; 24 | 25 | if(filter != null) { 26 | query = query.Where(filter); 27 | } 28 | 29 | foreach(var includeProperty in includeProperties.Split 30 | (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { 31 | query = query.Include(includeProperty); 32 | } 33 | 34 | if(orderBy != null) { 35 | return orderBy(query).ToList(); 36 | } else { 37 | return query.ToList(); 38 | } 39 | } 40 | 41 | public virtual TEntity GetByID(object id) { 42 | return dbSet.Find(id); 43 | } 44 | 45 | public virtual void Insert(TEntity entity) { 46 | dbSet.Add(entity); 47 | } 48 | 49 | public virtual void Delete(object id) { 50 | TEntity entityToDelete = dbSet.Find(id); 51 | Delete(entityToDelete); 52 | } 53 | 54 | public virtual void Delete(TEntity entityToDelete) { 55 | if(context.Entry(entityToDelete).State == EntityState.Detached) { 56 | dbSet.Attach(entityToDelete); 57 | } 58 | dbSet.Remove(entityToDelete); 59 | } 60 | 61 | public virtual void Update(TEntity entityToUpdate) { 62 | dbSet.Attach(entityToUpdate); 63 | context.Entry(entityToUpdate).State = EntityState.Modified; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DB.Documents.DAL/UnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.Entity; 3 | 4 | namespace DB.Documents.DAL { 5 | public class UnitOfWork : IDisposable { 6 | private DocumentsDbContext context; 7 | private GenericRepository itemRepository; 8 | 9 | public UnitOfWork(string connectionString) { 10 | this.context = new DocumentsDbContext(connectionString); 11 | Database.SetInitializer(null); 12 | } 13 | 14 | public GenericRepository ItemRepository { 15 | get { 16 | 17 | if(this.itemRepository == null) { 18 | this.itemRepository = new GenericRepository(context); 19 | } 20 | return itemRepository; 21 | } 22 | } 23 | 24 | public void Save() { 25 | context.SaveChanges(); 26 | } 27 | 28 | private bool disposed = false; 29 | 30 | protected virtual void Dispose(bool disposing) { 31 | if(!this.disposed) { 32 | if(disposing) { 33 | context.Dispose(); 34 | } 35 | } 36 | this.disposed = true; 37 | } 38 | 39 | public void Dispose() { 40 | Dispose(true); 41 | GC.SuppressFinalize(this); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DB.Documents.DAL/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Database/Documents.mdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress/aspnet-office-solutions/c50c1aaa0b2928c8805627e31d5a84bb56ab161c/Azure-SessionAffinity-Starter/src/Database/Documents.mdf -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/Database/HibernationStorage.mdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress/aspnet-office-solutions/c50c1aaa0b2928c8805627e31d5a84bb56ab161c/Azure-SessionAffinity-Starter/src/Database/HibernationStorage.mdf -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.DatabaseHibernationProvider/App.config: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.DatabaseHibernationProvider/DatabaseWorksessionHibernationProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using DevExpress.Web.Office.Internal; 8 | 9 | namespace DevExpress.Web.DatabaseHibernationProvider { 10 | public class DatabaseWorksessionHibernationProvider : WorkSessionHibernationProviderBase { 11 | public DatabaseWorksessionHibernationProvider(HibernatedItemsStorageSettings settings) : base(new DatabaseOfficeWorkSessionStorage(settings)) { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.DatabaseHibernationProvider/DevExpress.Web.DatabaseHibernationProvider.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7D9ADD81-188E-4754-8201-717A401B97DD} 8 | Library 9 | Properties 10 | DB.Hibernation.DAL 11 | DB.Hibernation.DAL 12 | v4.5.2 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 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 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.DatabaseHibernationProvider/HibernatedItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using DevExpress.Web.Office.Internal; 7 | 8 | namespace DevExpress.Web.DatabaseHibernationProvider { 9 | public class HibernatedItem { 10 | public Guid WorkSessionId { get; set; } 11 | public string DocumentId { get; set; } 12 | public DateTime HibernationTime { get; set; } 13 | public byte[] Header { get; set; } 14 | public byte[] Content { get; set; } 15 | 16 | public HibernatedItem() { } 17 | 18 | public HibernatedItem(Guid workSessionId) { 19 | WorkSessionId = workSessionId; 20 | } 21 | 22 | public HibernatedItem(Guid workSessionId, string documentId, DateTime hibernationTime, byte[] header, byte[] content) : this(workSessionId) { 23 | DocumentId = documentId; 24 | HibernationTime = hibernationTime; 25 | Header = header; 26 | Content = content; 27 | } 28 | public void CheckOut(HibernatedItemsStorageSettings storageSettings, Guid workSessionId) { 29 | HibernatedItemsStorage storage = new HibernatedItemsStorage(storageSettings); 30 | storage.GetItemByWorkSessionId(workSessionId); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.DatabaseHibernationProvider/HibernatedItemsStorageSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DevExpress.Web.DatabaseHibernationProvider { 8 | public class HibernatedItemsStorageSettings { 9 | public string ConnectionString { get; private set; } 10 | public string TableName { get; private set; } 11 | public HibernationTableColumnNames ColumnNames { get; set; } 12 | public HibernatedItemsStorageSettings(string connectionString, string tableName) { 13 | ConnectionString = connectionString; 14 | TableName = tableName; 15 | ColumnNames = new HibernationTableColumnNames(); 16 | } 17 | } 18 | 19 | public class HibernationTableColumnNames { 20 | const string DefaultWorkSessionId = "WorkSessionId"; 21 | const string DefaultDocumentId = "DocumentId"; 22 | const string DefaultHibernationTime = "HibernationTime"; 23 | const string DefaultHeader = "Header"; 24 | const string DefaultContent = "Content"; 25 | 26 | protected string GetStringProperty(string propertyValue, string defaultValue) { 27 | if(!string.IsNullOrEmpty(propertyValue)) 28 | return propertyValue; 29 | return defaultValue; 30 | } 31 | 32 | private string workSessionId; 33 | public string WorkSessionId { 34 | get { 35 | return GetStringProperty(workSessionId, DefaultWorkSessionId); 36 | } 37 | set { 38 | workSessionId = value; 39 | } 40 | } 41 | 42 | private string documentId; 43 | public string DocumentId { 44 | get { 45 | return GetStringProperty(documentId, DefaultDocumentId); 46 | } 47 | set { 48 | documentId = value; 49 | } 50 | } 51 | 52 | private string hibernationTime; 53 | public string HibernationTime { 54 | get { 55 | return GetStringProperty(hibernationTime, DefaultHibernationTime); 56 | } 57 | set { 58 | hibernationTime = value; 59 | } 60 | } 61 | 62 | private string header; 63 | public string Header { 64 | get { 65 | return GetStringProperty(header, DefaultHeader); 66 | } 67 | set { 68 | header = value; 69 | } 70 | } 71 | 72 | private string content; 73 | public string Content { 74 | get { 75 | return GetStringProperty(content, DefaultContent); 76 | } 77 | set { 78 | content = value; 79 | } 80 | } 81 | public HibernationTableColumnNames() { } 82 | internal List GetAllColumns() { 83 | return new List() { WorkSessionId, DocumentId, HibernationTime, Header, Content }; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.DatabaseHibernationProvider/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DB.Hibernation.DAL")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DB.Hibernation.DAL")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8da210c7-e056-4cd5-b4bb-d661ebdad9a3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/AzureServiceBus/Contract.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.ServiceModel; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DevExpress.Web.OfficeAzureCommunication { 10 | [ServiceContract(Name = "MessageServiceContract", Namespace = BroadcastNamespaces.ServiceContractNamespace)] 11 | public interface IMessageServiceContract { 12 | [OperationContract(IsOneWay = true)] 13 | void Publish(Message msg); 14 | } 15 | 16 | public interface IMessageServiceChannel : IMessageServiceContract, IClientChannel { } 17 | 18 | [ServiceBehavior( 19 | InstanceContextMode = InstanceContextMode.Single, 20 | ConcurrencyMode = ConcurrencyMode.Multiple)] 21 | public class MessageService : IMessageServiceContract { 22 | private object locker = new object(); 23 | 24 | public void Publish(Message msg) { 25 | lock(locker) { 26 | try { 27 | MessageDispatcher.ProcessMessage(msg); 28 | } catch { } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/AzureServiceBus/Message.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | 6 | namespace DevExpress.Web.OfficeAzureCommunication { 7 | 8 | public enum WorkSessionStatus { Loaded, AutoSaved, Hibernated, WokenUp, Removed } 9 | 10 | public enum WorkSessionServerStatus { Online, PingTimeout } 11 | 12 | public enum MessageOperation { Ping, RegisterServer, UnregisterServer, ShutDownServer, ServerNumberDecreased, AddWorkSession, RemoveWorkSession, WakeUpWorkSession, HibernateWorkSession, AutoSaveWorkSession } 13 | 14 | [DataContract(Namespace = BroadcastNamespaces.DataContractNamespace)] 15 | public class Message { 16 | [DataMember] 17 | public string RoleInstanceId { get; private set; } 18 | [DataMember] 19 | public MessageOperation MessageOperation { get; protected set; } 20 | [DataMember] 21 | public List RegisteredServers { get; private set; } 22 | #if DEBUG 23 | [DataMember] 24 | public string DiagnosticMessage { get; set; } 25 | #endif 26 | [DataMember] 27 | public DateTime CreateTime { get; private set; } 28 | 29 | public WorkSessionServerInfo Sender { 30 | get { return RegisteredServers.FirstOrDefault(s => s.RoleInstanceId == RoleInstanceId); } 31 | } 32 | public string HostServerName { get { return Sender.HostServerName; } } 33 | public string HostServerIP { get { return Sender.HostServerIP; } } 34 | 35 | 36 | public Message(string roleInstanceId, string hostServerName, string hostServerIP, MessageOperation messageOperation, List registeredServers) { 37 | RoleInstanceId = roleInstanceId; 38 | MessageOperation = messageOperation; 39 | AppendServers(registeredServers); 40 | SetSenderInfo(new WorkSessionServerInfo(roleInstanceId, hostServerName, hostServerIP)); 41 | CreateTime = DateTime.Now; 42 | } 43 | 44 | void AppendServers(List registeredServers) { 45 | RegisteredServers = new List(); 46 | RegisteredServers.AddRange(registeredServers); 47 | } 48 | 49 | void SetSenderInfo(WorkSessionServerInfo sender) { 50 | if(RegisteredServers.Count == 0 || Sender == null || Sender.RoleInstanceId != RoleInstanceId) 51 | RegisteredServers.Add(sender); 52 | Sender.GetServerParameters(); 53 | } 54 | 55 | public bool HasWorkSessionInfo() { 56 | return RegisteredServers.Select(s => s.WorkSessions.Count()).Sum() > 0; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/AzureServiceBus/Settings.cs: -------------------------------------------------------------------------------- 1 | using DevExpress.Web.OfficeAzureCommunication.Utils; 2 | 3 | namespace DevExpress.Web.OfficeAzureCommunication { 4 | public class ServiceBusSettings { 5 | public virtual string ServiceBusURISchema { get; private set; } 6 | public virtual string ServiceNamespace { get; private set; } 7 | public virtual string ServicePath { get; private set; } 8 | public virtual string SharedAccessKeyName { get; private set; } 9 | public virtual string SharedAccessKey { get; private set; } 10 | 11 | public ServiceBusSettings(string serviceNamespace, 12 | string servicePath, 13 | string sharedAccessKeyName, 14 | string sharedAccessKey) 15 | : this("sb", serviceNamespace, servicePath, sharedAccessKeyName, sharedAccessKey) { 16 | } 17 | public ServiceBusSettings(string serviceBusURISchema, 18 | string serviceNamespace, 19 | string servicePath, 20 | string sharedAccessKeyName, 21 | string sharedAccessKey) { 22 | ServiceBusURISchema = serviceBusURISchema; 23 | ServiceNamespace = serviceNamespace; 24 | ServicePath = servicePath; 25 | SharedAccessKeyName = sharedAccessKeyName; 26 | SharedAccessKey = sharedAccessKey; 27 | } 28 | protected ServiceBusSettings () { } 29 | } 30 | 31 | public class ServiceBusSettingsFromConfiguration : ServiceBusSettings { 32 | public override string ServiceBusURISchema { get { return ServiceConfigUtils.GetAppSetting("ServiceBusURISchema", "sb"); } } 33 | public override string ServiceNamespace { get { return ServiceConfigUtils.GetAppSetting("ServiceBusNamespace"); } } 34 | public override string ServicePath { get { return ServiceConfigUtils.GetAppSetting("ServiceBusPath"); } } 35 | public override string SharedAccessKeyName { get { return ServiceConfigUtils.GetAppSetting("ServiceBusSharedAccessKeyName"); } } 36 | public override string SharedAccessKey { get { return ServiceConfigUtils.GetAppSetting("ServiceBusSharedAccessKey"); } } 37 | 38 | public ServiceBusSettingsFromConfiguration() { } 39 | } 40 | 41 | public static class BroadcastNamespaces { 42 | public const string DataContractNamespace = "http://DataContractNamespace"; 43 | public const string ServiceContractNamespace = "http://ServiceContractNamespace"; 44 | } 45 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/Diagnostic/Logger.cs: -------------------------------------------------------------------------------- 1 | #if DEBUG 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace DevExpress.Web.OfficeAzureCommunication.Diagnostic { 8 | 9 | public static class Logger { 10 | static System.IO.StreamWriter file = null; 11 | static List log = new List(); 12 | 13 | static Logger() { 14 | if(!InitLogFile("")) 15 | InitLogFile(System.IO.Path.GetTempPath()); 16 | } 17 | 18 | private static bool InitLogFile(string path) { 19 | try { 20 | file = new System.IO.StreamWriter(System.IO.Path.Combine(path, "aspxlog.txt")); 21 | file.WriteLine("test start"); 22 | } catch { 23 | return false; 24 | } 25 | return true; 26 | } 27 | 28 | public static void Log(string msg) { 29 | string now = DateTime.Now.ToString(); 30 | msg = now + ": " + msg; 31 | 32 | SaveLogMessage(msg); 33 | } 34 | public static string GetWorkSessionList(Message msg) { 35 | StringBuilder sb = new StringBuilder(); 36 | foreach(var server in msg.RegisteredServers) { 37 | sb.AppendFormat("{0} (remaining memory {1}", server.RoleInstanceId, server.RemainingMemory); 38 | if(server.WorkSessions.Count() > 0) 39 | sb.Append(". WorkSessions: "); 40 | foreach(var ws in server.WorkSessions.Select(v => v.Value)) 41 | sb.AppendFormat("{0}, ", ws.WorkSessionID); 42 | sb.Append("); "); 43 | } 44 | return sb.ToString(); 45 | } 46 | public static void Log(Message msg) { 47 | string message = string.Format("\"{0}\" says: \"{1}\". Registered servers: {2}", 48 | msg.RoleInstanceId, msg.MessageOperation.ToString(), GetWorkSessionList(msg)); 49 | Log(message); 50 | } 51 | 52 | private static void SaveLogMessage(string msg) { 53 | log.Add(msg); 54 | 55 | if(file != null) { 56 | file.WriteLine(msg); 57 | file.Flush(); 58 | } 59 | } 60 | 61 | public static List GetLog() { 62 | return log; 63 | } 64 | 65 | } 66 | } 67 | 68 | #endif -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/PingService/PingService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DevExpress.Web.OfficeAzureCommunication { 4 | 5 | class PingService : TimeoutService { 6 | static object syncRoot = new Object(); 7 | TimeoutServiceSettings settings = new TimeoutServiceSettingsFromConfiguration(); 8 | 9 | private PingService() { } 10 | 11 | private static volatile PingService instance; 12 | protected static PingService Singleton { 13 | get { 14 | if(instance == null) { 15 | lock(syncRoot) { 16 | if(instance == null) { 17 | instance = new PingService(); 18 | } 19 | } 20 | } 21 | 22 | return instance; 23 | } 24 | } 25 | 26 | protected override TimeoutServiceSettings Settings { get { return settings; } } 27 | 28 | protected void InitSettings(TimeoutServiceSettings settings) { 29 | this.settings = settings; 30 | } 31 | 32 | protected override void OnServiceCore() { 33 | var workSessionInfos = RoutingTable.GetWorkSessionServerInstances(); 34 | WorkSessionMessenger.SendMessage(MessageOperation.Ping, workSessionInfos); 35 | } 36 | 37 | public static void Start(TimeoutServiceSettings settings) { 38 | if(settings.BroadcastInterval < 0) 39 | return; 40 | Singleton.InitSettings(settings); 41 | Singleton.StartInternal(); 42 | } 43 | public static void Stop() { 44 | Singleton.StopInternal(); 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/PingService/Settings.cs: -------------------------------------------------------------------------------- 1 | using DevExpress.Web.OfficeAzureCommunication.Utils; 2 | 3 | namespace DevExpress.Web.OfficeAzureCommunication { 4 | public class TimeoutServiceSettings { 5 | protected const int DefaultPingInterval = 30; 6 | protected const int DefaultServerExpirationInterval = 90; 7 | 8 | public virtual int BroadcastInterval { get; private set; } 9 | public virtual int ServerStatusExpirationInterval { get; private set; } 10 | 11 | protected TimeoutServiceSettings() { } 12 | public TimeoutServiceSettings(int broadcastInterval, int timeoutInterval) { 13 | BroadcastInterval = broadcastInterval; 14 | ServerStatusExpirationInterval = timeoutInterval; 15 | } 16 | } 17 | 18 | public class TimeoutServiceSettingsFromConfiguration : TimeoutServiceSettings { 19 | public override int BroadcastInterval { get { return GetTimerInterval(ConfigurationKeys.ServerStatusBroadcastInterval, DefaultPingInterval); } } 20 | public override int ServerStatusExpirationInterval { get { return GetTimerInterval(ConfigurationKeys.ServerStatusExpirationInterval, DefaultServerExpirationInterval); } } 21 | 22 | public TimeoutServiceSettingsFromConfiguration() { } 23 | 24 | int GetTimerInterval(string settingName, int defaultValue) { 25 | string intervalValueFromConfig = ServiceConfigUtils.GetAppSetting(settingName, defaultValue.ToString()); 26 | if(int.TryParse(intervalValueFromConfig, out int intervalValue)) 27 | return intervalValue; 28 | return -1; 29 | } 30 | } 31 | 32 | 33 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/PingService/TimeoutService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | 4 | namespace DevExpress.Web.OfficeAzureCommunication { 5 | abstract class TimeoutService { 6 | const string timerCacheKey = "DevExpressASPNETOfficeAzureDocumentServerServiceTimer"; 7 | 8 | bool active = false; 9 | 10 | protected abstract TimeoutServiceSettings Settings { get; } 11 | 12 | protected internal void StartInternal() { 13 | if(this.active) return; 14 | this.active = true; 15 | 16 | OnService(); 17 | } 18 | 19 | protected internal void StopInternal() { 20 | this.active = false; 21 | } 22 | 23 | void SetServiceTimer(int interval) { 24 | SetServiceTimer(TimeSpan.FromSeconds(interval)); 25 | } 26 | void SetServiceTimer(TimeSpan timeout) { 27 | if(!this.active) return; 28 | 29 | if(HttpRuntime.Cache[timerCacheKey] != null) 30 | return; 31 | 32 | HttpRuntime.Cache.Insert( 33 | timerCacheKey, 34 | string.Empty, 35 | null, 36 | System.Web.Caching.Cache.NoAbsoluteExpiration, 37 | timeout, 38 | System.Web.Caching.CacheItemPriority.NotRemovable, 39 | (key, value, reason) => OnService()); 40 | } 41 | 42 | void OnService() { 43 | if(!this.active) return; 44 | 45 | OnServiceCore(); 46 | 47 | SetServiceTimer(Settings.BroadcastInterval); 48 | } 49 | 50 | protected abstract void OnServiceCore(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DevExpress.Web.OfficeAzureCommunication")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DevExpress.Web.OfficeAzureCommunication")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("83d147d9-80c2-46ff-a8df-c92854f87cfd")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/RoutingTable/RoutingTableSerializer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | namespace DevExpress.Web.OfficeAzureCommunication { 5 | public static class RoutingTableSerializer { 6 | static string FilePath { get { return Path.Combine(Path.GetTempPath(), "ServerState.txt"); } } 7 | static void Serialize(RoutingTableStateDescriptor descriptor) { 8 | using(FileStream file = new FileStream(FilePath, FileMode.Create)) { 9 | var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 10 | formatter.Serialize(file, descriptor.Servers); 11 | file.Close(); 12 | } 13 | } 14 | static RoutingTableStateDescriptor Deserialize() { 15 | RoutingTableStateDescriptor descriptor = new RoutingTableStateDescriptor(); 16 | if(File.Exists(FilePath)) { 17 | using(FileStream file = new FileStream(FilePath, FileMode.Open, FileAccess.Read)) { 18 | if(file.Length > 0) { 19 | var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 20 | descriptor.Servers.AddRange((List)formatter.Deserialize(file)); 21 | } 22 | file.Close(); 23 | } 24 | } 25 | return descriptor; 26 | } 27 | public static void UpdateCache() { 28 | Serialize(new RoutingTableStateDescriptor(RoutingTable.GetWorkSessionServerInstances())); 29 | } 30 | public static void RestoreDataFromCache() { 31 | RoutingTableStateDescriptor descriptor = Deserialize(); 32 | RoutingTable.AddWorkSessionServers(descriptor.Servers); 33 | } 34 | } 35 | 36 | public class RoutingTableStateDescriptor { 37 | public List Servers { get; } 38 | public RoutingTableStateDescriptor() { 39 | Servers = new List(); 40 | } 41 | public RoutingTableStateDescriptor(List servers) : this() { 42 | Servers.AddRange(servers); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/RoutingTable/ServerListStateChangedController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace DevExpress.Web.OfficeAzureCommunication { 6 | class ServerListStateChangedController { 7 | StateChangedController stateChangedController; 8 | Action> serversAdded; 9 | Action> serversRemoved; 10 | 11 | public ServerListStateChangedController( 12 | Func getStateDelegate, 13 | Action> serversAdded, 14 | Action> serversRemoved) { 15 | 16 | this.serversAdded = serversAdded; 17 | this.serversRemoved = serversRemoved; 18 | this.stateChangedController = new StateChangedController(getStateDelegate, CheckStateChanged); 19 | } 20 | 21 | void CheckStateChanged(object stateBeforeChanges, object stateAfterChanges) { 22 | var serversBeforeChanges = (IEnumerable)stateBeforeChanges; 23 | var serversAfterChanges = (IEnumerable)stateAfterChanges; 24 | 25 | var added = serversAfterChanges.Except(serversBeforeChanges, new WorkSessionServerInfoComparer()); 26 | var removed = serversBeforeChanges.Except(serversAfterChanges, new WorkSessionServerInfoComparer()); 27 | 28 | if(added.Count() > 0) 29 | this.serversAdded(added); 30 | 31 | if(removed.Count() > 0) 32 | this.serversRemoved(removed); 33 | 34 | } 35 | 36 | public void BeginUpdate() { 37 | stateChangedController.BeginUpdate(); 38 | } 39 | public void EndUpdate() { 40 | stateChangedController.EndUpdate(); 41 | } 42 | } 43 | class StateChangedController { 44 | object stateBeforeChanges = null; 45 | object stateAfterChanges = null; 46 | 47 | Func getStateDelegate; 48 | Action checkStateChanged; 49 | 50 | public StateChangedController( 51 | Func getStateDelegate, 52 | Action checkStateChanged) { 53 | 54 | this.getStateDelegate = getStateDelegate; 55 | this.checkStateChanged = checkStateChanged; 56 | } 57 | 58 | int counter = 0; 59 | public void BeginUpdate() { 60 | counter++; 61 | if(counter == 1) 62 | stateBeforeChanges = getStateDelegate(); 63 | } 64 | public void EndUpdate() { 65 | counter--; 66 | if(counter == 0 && stateBeforeChanges != null) { 67 | stateAfterChanges = getStateDelegate(); 68 | checkStateChanged(stateBeforeChanges, stateAfterChanges); 69 | stateBeforeChanges = null; 70 | stateAfterChanges = null; 71 | } 72 | 73 | if(counter < 0) 74 | counter = 0; 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/RoutingTable/Settings.cs: -------------------------------------------------------------------------------- 1 | using DevExpress.Web.OfficeAzureCommunication.Utils; 2 | 3 | namespace DevExpress.Web.OfficeAzureCommunication { 4 | public static class RoleEnvironmentConfig { 5 | public static string DocumentServerRoleName { 6 | get { return ServiceConfigUtils.GetAppSetting(ConfigurationKeys.DocumentServerRoleName); } 7 | } 8 | public static string RoutingRoleName { 9 | get { return ServiceConfigUtils.GetAppSetting(ConfigurationKeys.RoutingServerRoleName); } 10 | } 11 | public static int DocumentServerPort { 12 | get { 13 | return int.Parse(ServiceConfigUtils.GetAppSetting(ConfigurationKeys.DocumentServerPort)); 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/RoutingTable/WorkSessionServerInfo/WorkSessionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace DevExpress.Web.OfficeAzureCommunication { 5 | [DataContract(Namespace = BroadcastNamespaces.DataContractNamespace)] 6 | [Serializable] 7 | public class WorkSessionInfo { 8 | [DataMember] 9 | public Guid WorkSessionID { get; set; } 10 | [DataMember] 11 | public string DocumentId { get; set; } 12 | [DataMember] 13 | public WorkSessionStatus Status { get; private set; } 14 | public long SenderTicks { get { return CreateTime.Ticks; } } 15 | public DateTime CreateTime { get; set; } 16 | public DateTime ProcessedTime { get; set; } 17 | 18 | public WorkSessionInfo(Guid workSessionID, string documentId) { 19 | WorkSessionID = workSessionID; 20 | DocumentId = documentId; 21 | } 22 | 23 | public void SetStatus(WorkSessionStatus status) { 24 | Status = status; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/Utils/CommandLineUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DevExpress.Web.OfficeAzureCommunication.Utils { 9 | public static class CommandLineUtils { 10 | public static void CmdExecute(string command) { 11 | ProcessStartInfo processInfo = new ProcessStartInfo("cmd.exe", "/c " + command); 12 | processInfo.CreateNoWindow = true; 13 | processInfo.UseShellExecute = false; 14 | processInfo.RedirectStandardError = true; 15 | processInfo.RedirectStandardOutput = true; 16 | Process process = Process.Start(processInfo); 17 | process.WaitForExit(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/Utils/ConfigurationKeys.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DevExpress.Web.OfficeAzureCommunication { 8 | public static class ConfigurationKeys { 9 | public const string DocumentServerRoleName = "DocumentServerRoleName"; 10 | public const string DocumentServerPort = "DocumentServerPort"; 11 | public const string RoutingServerRoleName = "RoutingServerRoleName"; 12 | public const string FarmConfigurationUpdateInterval = "FarmConfigurationUpdateInterval"; 13 | public const string ServerStatusBroadcastInterval = "ServerStatusBroadcastInterval"; 14 | public const string ServerStatusExpirationInterval = "ServerStatusExpirationInterval"; 15 | public const string HealthCheckPageUrl = "HealthCheckPageUrl"; 16 | public const string HealthCheckResponseMatch = "HealthCheckResponseMatch"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/Utils/NetUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DevExpress.Web.OfficeAzureCommunication.Utils { 10 | public static class NetUtils { 11 | public static string GetLocalIPAddress() { 12 | var host = Dns.GetHostEntry(Dns.GetHostName()); 13 | foreach(var ip in host.AddressList) { 14 | if(ip.AddressFamily == AddressFamily.InterNetwork) { 15 | return ip.ToString(); 16 | } 17 | } 18 | throw new Exception("Local IP Address Not Found!"); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/Utils/RoleInstanceUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.WindowsAzure.ServiceRuntime; 7 | 8 | namespace DevExpress.Web.OfficeAzureCommunication.Utils { 9 | public static class RoleInstanceUtils { 10 | public static IEnumerable GetRoleInstanceAdressList(string DocumentServerRoleName) { 11 | var role = FindRoleByName(DocumentServerRoleName); 12 | var addresses = GetRoleInstancesIP(role); 13 | return addresses; 14 | } 15 | 16 | private static Role FindRoleByName(string DocumentServerRoleName) { 17 | var queryLondonCustomers = from role in RoleEnvironment.Roles.Values 18 | where role.Name == DocumentServerRoleName 19 | select role; 20 | return queryLondonCustomers.First(); 21 | } 22 | 23 | private static IEnumerable GetRoleInstancesIP(Role role) { 24 | var adresses = from instance in role.Instances 25 | from endPoint in instance.InstanceEndpoints.Values 26 | select endPoint.IPEndpoint != null ? 27 | endPoint.IPEndpoint.Address.ToString() : 28 | endPoint.PublicIPEndpoint != null ? 29 | endPoint.PublicIPEndpoint.Address.ToString() : ""; 30 | return adresses.Distinct(); 31 | } 32 | 33 | public static Role GetRoleByInstanceID(string instanceID) { 34 | var roles = from allRoles in RoleEnvironment.Roles.Values 35 | from instance in allRoles.Instances 36 | where instance.Id == instanceID 37 | select instance.Role; 38 | if(roles.Count() > 0) 39 | return roles.First(); 40 | return null; 41 | } 42 | 43 | public static string GetCurrentRoleInstanceID() { 44 | return RoleEnvironment.CurrentRoleInstance.Id; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/Utils/ServiceConfigUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using Microsoft.Azure; 4 | using Microsoft.WindowsAzure; 5 | 6 | namespace DevExpress.Web.OfficeAzureCommunication.Utils { 7 | public static class ServiceConfigUtils { 8 | public static string GetAppSetting(string key) { 9 | return GetAppSetting(key, null); 10 | } 11 | public static string GetAppSetting(string key, string defaultValue) { 12 | string value = null; 13 | try { 14 | value = CloudConfigurationManager.GetSetting(key); 15 | } catch { } 16 | 17 | return value ?? defaultValue; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/WorkSessionMessenger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using DevExpress.Web.OfficeAzureCommunication.Utils; 8 | using Microsoft.WindowsAzure.ServiceRuntime; 9 | 10 | namespace DevExpress.Web.OfficeAzureCommunication { 11 | public static class WorkSessionMessenger { 12 | public static void SendMessage(MessageOperation operation, List registeredServers) { 13 | var message = CreateMessage(operation, registeredServers); 14 | InterRoleCommunicator.SendMessage(message); 15 | } 16 | 17 | public static void SendMessage(MessageOperation operation, Guid workSessionID, string documentID) { 18 | var message = CreateMessage(operation, workSessionID, documentID); 19 | InterRoleCommunicator.SendMessage(message); 20 | } 21 | 22 | static Message CreateMessage(MessageOperation operation, List registeredServers) { 23 | var message = new Message( 24 | RoleEnvironment.CurrentRoleInstance.Id, 25 | System.Environment.MachineName, 26 | NetUtils.GetLocalIPAddress(), 27 | operation, 28 | registeredServers 29 | ); 30 | return message; 31 | } 32 | 33 | static Message CreateMessage(MessageOperation operation, Guid workSessionID, string documentID) { 34 | Message message = CreateMessage(operation, new List()); 35 | message.Sender.WorkSessions.GetOrAdd(workSessionID, new WorkSessionInfo(workSessionID, documentID)); 36 | return message; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureCommunication/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureDocumentServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DevExpress.Web.OfficeAzureDocumentServer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DevExpress.Web.OfficeAzureDocumentServer")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b062579a-812b-4c54-84c0-f7df53cc8dd4")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/Configuration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using DevExpress.Web.OfficeAzureCommunication; 3 | using DevExpress.Web.OfficeAzureCommunication.Utils; 4 | 5 | namespace DevExpress.Web.OfficeAzureRoutingServer { 6 | public static class WebFarmConfiguration 7 | { 8 | private const string defaultFarmName = "ARRAffinity"; 9 | 10 | public static string FarmName { get { return defaultFarmName; } } 11 | 12 | public static Dictionary HealthCheckConfiguration { get { 13 | Dictionary configuration= new Dictionary(); 14 | configuration.Add("url", string.Format("http://localhost:{0}/{1}", RoleEnvironmentConfig.DocumentServerPort, 15 | ServiceConfigUtils.GetAppSetting(ConfigurationKeys.HealthCheckPageUrl))); 16 | configuration.Add("responseMatch", ServiceConfigUtils.GetAppSetting(ConfigurationKeys.HealthCheckResponseMatch)); 17 | return configuration; 18 | } 19 | } 20 | } 21 | 22 | public static class RoutingConfiguration { 23 | private const string defaultAffinityCookieName = "ARRAffinity"; 24 | private const string queryStringParameterName = "dxwsid"; 25 | private const string requestParamKeyName = "ASPxOfficeWorkSessionID"; 26 | 27 | public static string AffinityCookieName { get { return defaultAffinityCookieName; } } 28 | public static string QueryStringParameterName { get { return queryStringParameterName; } } 29 | public static string RequestParamKeyName { get { return requestParamKeyName; } } 30 | public static bool UseCookie { get { return true; } } 31 | 32 | } 33 | } -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/IISWebFarmConfiguration/ConfigurationElementUtils.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Web.Administration; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace DevExpress.Web.OfficeAzureRoutingServer { 7 | public static class ConfigurationElementUtils { 8 | public static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, Dictionary attributes) { 9 | foreach(ConfigurationElement element in collection) { 10 | if(!string.Equals(element.Schema.Name, elementTagName, StringComparison.OrdinalIgnoreCase)) 11 | continue; 12 | var satisfy = attributes.All(kvp => HasAttribute(element, kvp)); 13 | if(satisfy) 14 | return element; 15 | } 16 | return null; 17 | } 18 | public static bool HasAttribute(ConfigurationElement element, KeyValuePair attribute) { 19 | return HasAttribute(element, attribute.Key, attribute.Value); 20 | } 21 | public static bool HasAttribute(ConfigurationElement element, string attributeName, string attributeValue) { 22 | return string.Equals(attributeValue, 23 | GetAttributValue(element, attributeName), 24 | StringComparison.OrdinalIgnoreCase); 25 | } 26 | public static string GetAttributValue(ConfigurationElement element, string attributeName) { 27 | var attribute = element.Attributes.FirstOrDefault(attr => string.Equals(attr.Name, attributeName)); 28 | return (attribute != null) ? 29 | string.Concat(attribute.Value) : 30 | string.Empty; 31 | } 32 | public static void SetAttribute(ConfigurationElement element, Dictionary attributes) { 33 | foreach(var attribute in attributes) { 34 | element.SetAttributeValue(attribute.Key, attribute.Value); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/IISWebFarmConfiguration/ConfigurationManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace DevExpress.Web.OfficeAzureRoutingServer { 5 | public static class FarmConfigurationManager { 6 | static object locker = new object(); 7 | 8 | public static void SetUpFarm() { 9 | lock(locker) { 10 | try { 11 | IISWebFarmConfigurationUtils.SetUp(WebFarmConfiguration.FarmName); 12 | } catch { } 13 | } 14 | } 15 | 16 | public static void RegisterServer(string serverAddress, int port) { 17 | AddServer(serverAddress, port); 18 | } 19 | 20 | public static void UpdateServersRegistration(IEnumerable serverAddresses, int port) { 21 | AddNewServers(serverAddresses, port); 22 | RemoveOfflineServers(serverAddresses, port); 23 | } 24 | 25 | static void AddNewServers(IEnumerable serverAddresses, int port) { 26 | IEnumerable serversOnFarm = GetServersFromFarmConfiguration(); 27 | var newServers = serverAddresses.Except(serversOnFarm); 28 | AddServers(newServers, port); 29 | } 30 | 31 | public static void RemoveOfflineServers(IEnumerable serverAddresses, int port) { 32 | IEnumerable serversOnFarm = GetServersFromFarmConfiguration(); 33 | var offlineServers = serversOnFarm.Except(serverAddresses); 34 | RemoveServers(offlineServers); 35 | } 36 | 37 | static IEnumerable GetServersFromFarmConfiguration() { 38 | lock(locker) { 39 | var farmName = WebFarmConfiguration.FarmName; 40 | return IISWebFarmConfigurationUtils.GetServersFromConfiguration(farmName); 41 | } 42 | } 43 | 44 | public static void AddServers(IEnumerable serverAddresses, int port) { 45 | lock(locker) { 46 | var farmName = WebFarmConfiguration.FarmName; 47 | foreach(var serverAddress in serverAddresses) { 48 | IISWebFarmConfigurationUtils.AddServer(farmName, serverAddress, port); 49 | } 50 | } 51 | } 52 | 53 | public static void AddServer(string serverAddress, int port) { 54 | lock(locker) { 55 | var farmName = WebFarmConfiguration.FarmName; 56 | IISWebFarmConfigurationUtils.AddServer(farmName, serverAddress, port); 57 | } 58 | } 59 | 60 | public static void RemoveServers(IEnumerable servers) { 61 | lock(locker) { 62 | var farmName = WebFarmConfiguration.FarmName; 63 | IISWebFarmConfigurationUtils.RemoveServers(farmName, servers); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/IISWebFarmConfiguration/IISUrlRewriterConfigurationUtils.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Web.Administration; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace DevExpress.Web.OfficeAzureRoutingServer { 6 | public static class IISUrlRewriterConfigurationUtils 7 | { 8 | public static void CreateURLRewriteRule(string serverFarm, bool forceRecreate = true) 9 | { 10 | using (ServerManager manager = new ServerManager()) 11 | { 12 | ConfigurationElementCollection urlRewriterConfiguration = manager.GetApplicationHostConfiguration().GetSection("system.webServer/rewrite/globalRules").GetCollection(); 13 | string str = string.Format("ARR_{0}_loadbalance", serverFarm); 14 | 15 | var attributes = new Dictionary() { { "name", str } }; 16 | var urlRewriterRule = ConfigurationElementUtils.FindElement(urlRewriterConfiguration, "rule", attributes); 17 | 18 | if (urlRewriterRule != null) 19 | { 20 | if (forceRecreate) 21 | urlRewriterConfiguration.Remove(urlRewriterRule); 22 | else 23 | throw new InvalidOperationException("Cannot create rule with duplicate name"); 24 | } 25 | ConfigurationElement element = urlRewriterConfiguration.CreateElement("rule"); 26 | element["name"] = str; 27 | element["patternSyntax"] = "Wildcard"; 28 | element["stopProcessing"] = true; 29 | element["enabled"] = true; 30 | element.GetChildElement("match")["url"] = "*"; 31 | ConfigurationElement childElement = element.GetChildElement("action"); 32 | childElement["type"] = "Rewrite"; 33 | childElement["url"] = "http://" + serverFarm + "/{R:0}"; 34 | urlRewriterConfiguration.Add(element); 35 | manager.CommitChanges(); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/OfficeAzureRoutingServer.cs: -------------------------------------------------------------------------------- 1 | using DevExpress.Web.OfficeAzureCommunication; 2 | 3 | namespace DevExpress.Web.OfficeAzureRoutingServer { 4 | public static class OfficeAzureRoutingServer { 5 | public static void Init() { 6 | InterRoleCommunicator.Initialize(false); 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DevExpress.Web.OfficeAzureRoutingServer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DevExpress.Web.OfficeAzureRoutingServer")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("73108f28-6a18-46f4-884a-37decbfdf96a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/Routing/ARRHashHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | using System.Text; 3 | 4 | namespace DevExpress.Web.OfficeAzureRoutingServer { 5 | static class ARRHashHelper { 6 | public static string CalculateHash(string value) { 7 | int num2; 8 | SHA256 sha = SHA256.Create(); 9 | byte[] bytes = Encoding.Unicode.GetBytes(value.ToUpper()); 10 | byte[] buffer = sha.ComputeHash(bytes); 11 | string str = string.Empty; 12 | for(int i = 0; i < buffer.Length; i = num2 + 1) { 13 | str += buffer[i].ToString("X2"); 14 | num2 = i; 15 | } 16 | return str.ToLower(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/Routing/CustomHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Web; 4 | 5 | namespace DevExpress.Web.OfficeAzureRoutingServer { 6 | 7 | interface IRoutingModuleCustomHandler { 8 | bool PreccessRequest(HttpApplication application); 9 | } 10 | 11 | #if DEBUG 12 | partial class RoutingModuleBase : IHttpModule { 13 | static RoutingModuleBase() { 14 | RegisterCustomHandler(new RoutingModule_DiagnosticPage()); 15 | } 16 | } 17 | 18 | class RoutingModule_DiagnosticPage : IRoutingModuleCustomHandler { 19 | public bool PreccessRequest(HttpApplication application) { 20 | bool handled = false; 21 | HttpContext context = application.Context; 22 | bool requestToProcess = context.Request.FilePath.Contains("diagnostic.aspx"); 23 | 24 | if(requestToProcess) { 25 | string content = DevExpress.Web.OfficeAzureCommunication.Diagnostic.WorkSessionServerView.CreateDianosticPageHtml(System.Environment.MachineName, address => ARRHashHelper.CalculateHash(address)); 26 | context.Response.Write(content); 27 | context.Response.End(); 28 | handled = true; 29 | } 30 | return handled; 31 | } 32 | 33 | } 34 | #endif 35 | } 36 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/Routing/RoutingModule.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | 3 | namespace DevExpress.Web.OfficeAzureRoutingServer { 4 | 5 | public class RoutingModule : RoutingModuleBase { 6 | protected override string ExtractRoutingKeyFromRequest(HttpRequest request) { 7 | return RoutingKeyHelper.ExtractRoutingKeyFromRequest(request); 8 | } 9 | } 10 | 11 | public class RoutingKeyHelper { 12 | public static string ExtractRoutingKeyFromRequest(HttpRequest request) { 13 | string routingKey = string.Empty; 14 | if(!string.IsNullOrEmpty(request.QueryString[RoutingConfiguration.QueryStringParameterName])) { 15 | routingKey = request.QueryString[RoutingConfiguration.QueryStringParameterName]; 16 | } else if(!string.IsNullOrEmpty(request.Params[RoutingConfiguration.RequestParamKeyName])) { 17 | routingKey = request.Params[RoutingConfiguration.RequestParamKeyName]; 18 | } 19 | return routingKey; 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Azure-SessionAffinity-Starter/src/DevExpress.Web.OfficeAzureRoutingServer/Routing/RoutingModuleBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Web; 5 | using DevExpress.Web.OfficeAzureCommunication; 6 | 7 | namespace DevExpress.Web.OfficeAzureRoutingServer { 8 | 9 | public abstract partial class RoutingModuleBase : IHttpModule { 10 | 11 | public void Init(HttpApplication application) { 12 | application.BeginRequest += new EventHandler(Application_BeginRequest); 13 | } 14 | 15 | protected void Application_BeginRequest(object sender, EventArgs e) { 16 | HttpApplication application = (HttpApplication)sender; 17 | string workSessionID = ExtractRoutingKeyFromRequest(application.Request); 18 | 19 | bool handled = CustomProcessing(application); 20 | if(handled) return; 21 | DoRequestRouting(application, workSessionID); 22 | } 23 | 24 | protected abstract string ExtractRoutingKeyFromRequest(HttpRequest request); 25 | 26 | public void Dispose() { } 27 | 28 | static void DoRequestRouting(HttpApplication application, string workSessionID) { 29 | RoutingTable.EnsureServerIsPrepared(); 30 | 31 | WorkSessionServerInfo serverInfo = RoutingTable.GetWorkSessionServerInfoByWorkSessionID(workSessionID); 32 | if(serverInfo != null && serverInfo.Status != WorkSessionServerStatus.Online) { 33 | throw new Exception("WorkSession is not available"); 34 | } 35 | 36 | if(serverInfo == null && !HeaderCookieHelper.HasServerAffinity(application, RoutingConfiguration.AffinityCookieName)) 37 | serverInfo = RoutingTable.FindAvailableServerForNewWorkSession(); 38 | 39 | if(serverInfo != null && RoutingConfiguration.UseCookie) { 40 | FarmConfigurationManager.AddServer(serverInfo.HostServerIP, 8080); 41 | string newCookieValue = ARRHashHelper.CalculateHash(serverInfo.HostServerIP); 42 | HeaderCookieHelper.PatchHeaderCookieGUID(application, RoutingConfiguration.AffinityCookieName, newCookieValue); 43 | } 44 | } 45 | 46 | static List customHandlers = new List(); 47 | internal static void RegisterCustomHandler(IRoutingModuleCustomHandler customHandler) { 48 | if(!customHandlers.Contains(customHandler)) 49 | customHandlers.Add(customHandler); 50 | } 51 | static bool CustomProcessing(HttpApplication application){ 52 | bool handled = false; 53 | foreach(var customHandler in customHandlers) { 54 | handled = customHandler.PreccessRequest(application); 55 | if(handled) break; 56 | } 57 | return handled; 58 | } 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/Azure-SqlOfficeStateProvider-Starter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{CC5FD16D-436D-48AD-A40C-5A424C6E3E79}") = "Azure-SqlOfficeStateProvider-Starter", "Azure-SqlOfficeStateProvider-Starter\Azure-SqlOfficeStateProvider-Starter.ccproj", "{48AFB3B2-FC16-4DB5-8C75-4F010A2A59F2}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebServer", "WebServer\WebServer.csproj", "{F1AB2F87-2147-41FD-BEAB-CF168F8477E6}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevExpress.Web.SqlOfficeStateProvider", "..\..\SqlOfficeStateProvider\src\DevExpress.Web.SqlOfficeStateProvider.csproj", "{15DAB813-0130-44D2-8C22-A676BF4C5DD3}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {48AFB3B2-FC16-4DB5-8C75-4F010A2A59F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {48AFB3B2-FC16-4DB5-8C75-4F010A2A59F2}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {48AFB3B2-FC16-4DB5-8C75-4F010A2A59F2}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {48AFB3B2-FC16-4DB5-8C75-4F010A2A59F2}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {F1AB2F87-2147-41FD-BEAB-CF168F8477E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {F1AB2F87-2147-41FD-BEAB-CF168F8477E6}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {F1AB2F87-2147-41FD-BEAB-CF168F8477E6}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {F1AB2F87-2147-41FD-BEAB-CF168F8477E6}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(NestedProjects) = preSolution 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/Azure-SqlOfficeStateProvider-Starter/ServiceConfiguration.Cloud.cscfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/Azure-SqlOfficeStateProvider-Starter/ServiceConfiguration.Local.cscfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/Azure-SqlOfficeStateProvider-Starter/ServiceDefinition.csdef: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/Azure-SqlOfficeStateProvider-Starter/WebServerContent/diagnostics.wadcfgx: -------------------------------------------------------------------------------- 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 | false 40 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/App_Data/WorkDirectory/README.md: -------------------------------------------------------------------------------- 1 | Put your test office document here. -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Language="C#" %> 2 | 3 | 38 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebServer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WebServer")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f1ab2f87-2147-41fd-beab-cf168f8477e6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/RichEdit.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RichEdit.aspx.cs" Inherits="WebServer.RichEdit" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.ASPxRichEdit.v20.1, Version=20.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxRichEdit" TagPrefix="dx" %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/RichEdit.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace WebServer 9 | { 10 | public partial class RichEdit : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/RichEdit.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace WebServer { 11 | 12 | 13 | public partial class RichEdit { 14 | 15 | /// 16 | /// form1 control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 23 | 24 | /// 25 | /// ASPxRichEdit1 control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::DevExpress.Web.ASPxRichEdit.ASPxRichEdit ASPxRichEdit1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/Spreadsheet.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Spreadsheet.aspx.cs" Inherits="WebServer.Spreadsheet" %> 2 | 3 | <%@ Register Assembly="DevExpress.Web.ASPxSpreadsheet.v20.1, Version=20.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxSpreadsheet" TagPrefix="dx" %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/Spreadsheet.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace WebServer 9 | { 10 | public partial class Spreadsheet : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/Spreadsheet.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace WebServer { 11 | 12 | 13 | public partial class Spreadsheet { 14 | 15 | /// 16 | /// form1 control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 23 | 24 | /// 25 | /// ASPxSpreadsheet1 control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::DevExpress.Web.ASPxSpreadsheet.ASPxSpreadsheet ASPxSpreadsheet1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/WebRole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.WindowsAzure; 5 | using Microsoft.WindowsAzure.Diagnostics; 6 | using Microsoft.WindowsAzure.ServiceRuntime; 7 | 8 | namespace WebServer 9 | { 10 | public class WebRole : RoleEntryPoint 11 | { 12 | public override bool OnStart() 13 | { 14 | // For information on handling configuration changes 15 | // see the MSDN topic at https://go.microsoft.com/fwlink/?LinkId=166357. 16 | 17 | return base.OnStart(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Azure-SqlOfficeStateProvider-Starter/src/WebServer/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Developer Express Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RedisOfficeStateProvider/src/Diagnostics/RedisConnectionLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DevExpress.Web.RedisOfficeStateProvider.Diagnostics { 9 | 10 | public class RedisConnectionLogger : TextWriter { 11 | public override Encoding Encoding => Encoding.ASCII; 12 | 13 | event RedisConnectionLogEventHandler redisConnectionMessageReceived; 14 | public event RedisConnectionLogEventHandler RedisConnectionMessageReceived { 15 | add { redisConnectionMessageReceived += value; } 16 | remove { redisConnectionMessageReceived -= value; } 17 | } 18 | 19 | public override void WriteLine(string value) { 20 | base.WriteLine(value); 21 | RaiseMessageReceived(value); 22 | } 23 | public override void WriteLine(string format, object arg0) { 24 | base.WriteLine(format, arg0); 25 | RaiseMessageReceived(string.Format(format, arg0)); 26 | } 27 | public override void WriteLine(string format, object arg0, object arg1) { 28 | base.WriteLine(format, arg0, arg1); 29 | RaiseMessageReceived(string.Format(format, arg0, arg1)); 30 | } 31 | public override void WriteLine(string format, object arg0, object arg1, object arg2) { 32 | base.WriteLine(format, arg0, arg1, arg2); 33 | RaiseMessageReceived(string.Format(format, arg0, arg1, arg2)); 34 | } 35 | public override void Write(string format, params object[] arg) { 36 | base.Write(format, arg); 37 | RaiseMessageReceived(string.Format(format, arg)); 38 | } 39 | 40 | void RaiseMessageReceived(string logMessage){ 41 | redisConnectionMessageReceived?.Invoke(logMessage); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /RedisOfficeStateProvider/src/Exceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DevExpress.Web.RedisOfficeStateProvider { 4 | 5 | public class CannotCheckoutStateCheckedOutByAnotherProcessException : Exception { 6 | const string message = "Cannot check out a state that has already been checked out by another process."; 7 | public CannotCheckoutStateCheckedOutByAnotherProcessException() : base(message) { } 8 | } 9 | 10 | public class CannotAddStateCheckedOutByAnotherProcessException : Exception { 11 | const string message = "Cannot add a record for the state that has already been checked out by another process."; 12 | public CannotAddStateCheckedOutByAnotherProcessException() : base(message) { } 13 | } 14 | 15 | public class CannotRemoveStateCheckedOutByAnotherProcessException : Exception { 16 | const string message = "Cannot remove a record for the state that has already been checked out by another process."; 17 | public CannotRemoveStateCheckedOutByAnotherProcessException() : base(message) { } 18 | } 19 | 20 | public class CannotRemoveStateException : Exception { 21 | const string message = "Cannot remove a state record."; 22 | public CannotRemoveStateException(string field) : base(string.Format(message, field)) { } 23 | } 24 | 25 | public interface IDoNotRetryRedisOfficeException { } 26 | 27 | public class CannotAddWorkSessionThatAlreadyExistsException : Office.Internal.CannotAddWorkSessionThatAlreadyExistsException, IDoNotRetryRedisOfficeException { 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /RedisOfficeStateProvider/src/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DevExpress.Web.RedisOfficeStateProvider")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DevExpress.Web.RedisOfficeStateProvider")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("dba06103-f29c-400a-bd5c-d1bde1ec1ca4")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /RedisOfficeStateProvider/src/Provider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using DevExpress.Web.Office; 3 | 4 | namespace DevExpress.Web.RedisOfficeStateProvider { 5 | 6 | public class CustomStateProvidingEventArgs { 7 | public CustomStateProvidingEventArgs(string workSessionId) { 8 | WorkSessionId = workSessionId; 9 | } 10 | public string WorkSessionId { get; internal set; } 11 | public string WorkSessionState { get; set; } 12 | } 13 | 14 | public delegate void CustomStateProvidingEventHandler(CustomStateProvidingEventArgs args); 15 | 16 | public class RedisOfficeStateProvider : OfficeStateProviderBase { 17 | 18 | public RedisOfficeStateProvider(string connectionString) : base(new RedisOfficeStateStorageRemote(connectionString)) { } 19 | 20 | new RedisOfficeStateStorageRemote Storage { get { return (RedisOfficeStateStorageRemote)base.Storage; } } 21 | RedisOfficeStateStorageSettings Settings { get { return Storage.Settings; } } 22 | 23 | public int StateTimeout { get { return Settings.StateTTL; } set { Settings.StateTTL = value; } } 24 | public int StateLockTimeout { get { return Settings.LockerTTL; } set { Settings.LockerTTL = value; } } 25 | public bool TrackStateLastAccessTime { get { return Settings.TrackStateLastAccessTime; } set { Settings.TrackStateLastAccessTime = value; } } 26 | 27 | public event CustomStateProvidingEventHandler CustomStateProviding { 28 | add { Storage.CustomStateProviding += value; } 29 | remove { Storage.CustomStateProviding -= value; } 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /RedisOfficeStateProvider/src/RedisConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using StackExchange.Redis; 7 | using DevExpress.Web.RedisOfficeStateProvider.Diagnostics; 8 | 9 | namespace DevExpress.Web.RedisOfficeStateProvider { 10 | 11 | public class RedisConnection { 12 | ConnectionMultiplexer connectionMultiplexer; 13 | 14 | IDatabase database; 15 | public IDatabase Database { get { return database; } } 16 | 17 | public RedisConnection(string connectionString) { 18 | if (Diagnostics.DiagnosticEvents.ConnectionLogger == null) { 19 | connectionMultiplexer = ConnectionMultiplexer.Connect(connectionString); 20 | } else { 21 | connectionMultiplexer = ConnectionMultiplexer.Connect(connectionString, Diagnostics.DiagnosticEvents.ConnectionLogger); 22 | } 23 | 24 | database = connectionMultiplexer.GetDatabase(); 25 | } 26 | 27 | public object ScriptEvaluate(string script, string[] keyArgs, object[] valueArgs) { 28 | RedisKey[] redisKeyArgs = GetRedisKeys(keyArgs); 29 | RedisValue[] redisValueArgs = GetRedisValues(valueArgs); 30 | 31 | return database.ScriptEvaluate(script, redisKeyArgs, redisValueArgs); 32 | } 33 | 34 | private static RedisKey[] GetRedisKeys(string[] keyArgs) { 35 | RedisKey[] redisKeyArgs = new RedisKey[keyArgs.Length]; 36 | 37 | int i = 0; 38 | foreach (string key in keyArgs) { 39 | redisKeyArgs[i] = key; 40 | i++; 41 | } 42 | 43 | return redisKeyArgs; 44 | } 45 | 46 | private static RedisValue[] GetRedisValues(object[] valueArgs) { 47 | RedisValue[] redisValueArgs = new RedisValue[valueArgs.Length]; 48 | 49 | int i = 0; 50 | foreach (object val in valueArgs) { 51 | if (val.GetType() == typeof(byte[])) 52 | redisValueArgs[i] = (byte[])val; 53 | else 54 | redisValueArgs[i] = val.ToString(); 55 | i++; 56 | } 57 | 58 | return redisValueArgs; 59 | } 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /RedisOfficeStateProvider/src/TryRepeater.cs: -------------------------------------------------------------------------------- 1 | using DevExpress.Web.RedisOfficeStateProvider.Diagnostics; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | 6 | namespace DevExpress.Web.RedisOfficeStateProvider { 7 | 8 | public static class TryRepeater { 9 | 10 | public static int TryCount { get; set; } 11 | public static int TryInterval { get; set; } 12 | 13 | static TryRepeater() { 14 | TryCount = 10; 15 | TryInterval = 1000; 16 | } 17 | 18 | public static object Do(Func task) { 19 | for (int tryIndex = 0; tryIndex < TryCount; tryIndex++) { 20 | bool lastTry = tryIndex == TryCount - 1; 21 | try { 22 | return task(); 23 | } catch (Exception e) { 24 | DiagnosticEvents.OnRedisOperationTryRepeaterTryException(e); 25 | if (lastTry || e is IDoNotRetryRedisOfficeException) 26 | throw e; 27 | Thread.Sleep(TryInterval); 28 | } 29 | } 30 | return null; 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /RedisOfficeStateProvider/src/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /SqlOfficeStateProvider/src/DevExpress.Web.SQLOfficeStateProvider.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {15DAB813-0130-44D2-8C22-A676BF4C5DD3} 8 | Library 9 | Properties 10 | DevExpress.Web.SqlOfficeStateProvider 11 | DevExpress.Web.SqlOfficeStateProvider 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | False 42 | 43 | False 44 | 45 | 46 | False 47 | 48 | False 49 | 50 | 51 | False 52 | 53 | False 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /SqlOfficeStateProvider/src/Exceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DevExpress.Web.SqlOfficeStateProvider { 4 | 5 | public class CannotCheckoutStateCheckedOutByAnotherProcessException : Exception { 6 | const string message = "Cannot check out a state that has already been checked out by another process."; 7 | public CannotCheckoutStateCheckedOutByAnotherProcessException() : base(message) { } 8 | } 9 | 10 | public class CannotAddStateCheckedOutByAnotherProcessException : Exception { 11 | const string message = "Cannot add a record for the state that has already been checked out by another process."; 12 | public CannotAddStateCheckedOutByAnotherProcessException() : base(message) { } 13 | } 14 | 15 | public class CannotRemoveStateCheckedOutByAnotherProcessException : Exception { 16 | const string message = "Cannot remove a record for the state that has already been checked out by another process."; 17 | public CannotRemoveStateCheckedOutByAnotherProcessException() : base(message) { } 18 | } 19 | 20 | public class CannotRemoveStateException : Exception { 21 | const string message = "Cannot remove a state record."; 22 | public CannotRemoveStateException(string field) : base(string.Format(message, field)) { } 23 | } 24 | 25 | public interface IDoNotRetryRedisOfficeException { } 26 | 27 | public class CannotAddWorkSessionThatAlreadyExistsException : Office.Internal.CannotAddWorkSessionThatAlreadyExistsException, IDoNotRetryRedisOfficeException { 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /SqlOfficeStateProvider/src/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DevExpress.Web.SqlOfficeStateProvider")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DevExpress.Web.SqlOfficeStateProvider")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("15dab813-0130-44d2-8c22-a676bf4c5dd3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SqlOfficeStateProvider/src/Provider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using DevExpress.Web.Office; 3 | 4 | namespace DevExpress.Web.SqlOfficeStateProvider { 5 | 6 | public class SqlOfficeStateProvider : OfficeStateProviderBase { 7 | public SqlOfficeStateProvider(string connectionString) : base(new SqlOfficeStateStorageRemote(connectionString)) { 8 | CommandTimeout = 600; 9 | } 10 | 11 | public static int CommandTimeout { get; set; } 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /SqlOfficeStateProvider/src/Storage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Data.SqlClient; 4 | using System.Data.SqlTypes; 5 | using DevExpress.Web.Office; 6 | 7 | namespace DevExpress.Web.SqlOfficeStateProvider { 8 | 9 | public class SqlOfficeStateStorageRemote : IOfficeStateStorageRemote { 10 | 11 | protected string ConnectionString { get; private set; } 12 | 13 | public SqlOfficeStateStorageRemote(string connectionString) { 14 | ConnectionString = connectionString; 15 | } 16 | 17 | protected virtual string LockerId { get { return OfficeStateProviderBase.GlobalLockerId; } } 18 | 19 | public bool AddCheckedOut(string workSessionId, string documentId) { 20 | return (bool)TryRepeater.Do(() => SqlImplementation.AddCheckedOut(ConnectionString, workSessionId, documentId.ToLower(), LockerId)); 21 | } 22 | 23 | public bool CheckIn(string workSessionId, string documentId, string workSessionState) { 24 | return (bool)TryRepeater.Do(() => SqlImplementation.CheckIn(ConnectionString, workSessionId, documentId.ToLower(), workSessionState, LockerId)); 25 | } 26 | 27 | public string FindWorkSessionId(string documentId) { 28 | return (string)TryRepeater.Do(() => SqlImplementation.FindWorkSessionId(ConnectionString, documentId.ToLower())); 29 | } 30 | 31 | public bool HasWorkSessionId(string workSessionId) { 32 | return (bool)TryRepeater.Do(() => SqlImplementation.HasWorkSessionId(ConnectionString, workSessionId)); 33 | } 34 | 35 | public void Remove(string workSessionId) { 36 | TryRepeater.Do(() => SqlImplementation.Remove(ConnectionString, workSessionId, LockerId)); 37 | } 38 | 39 | public bool CheckOut(string workSessionId, out string workSessionState) { 40 | string workSessionStateFromSql = null; 41 | var success = (bool)TryRepeater.Do(() => SqlImplementation.CheckOut(ConnectionString, workSessionId, LockerId, out workSessionStateFromSql)); 42 | workSessionState = workSessionStateFromSql; 43 | return success; 44 | } 45 | 46 | public void UndoCheckOut(string workSessionId) { 47 | TryRepeater.Do(() => SqlImplementation.UndoCheckOut(ConnectionString, workSessionId, LockerId)); 48 | } 49 | 50 | public void Set(string key, string value) { 51 | SqlImplementation.Set(ConnectionString, key, value); 52 | } 53 | public string Get(string key) { 54 | return SqlImplementation.Get(ConnectionString, key); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /SqlOfficeStateProvider/src/TryRepeater.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace DevExpress.Web.SqlOfficeStateProvider { 5 | 6 | public static class TryRepeater { 7 | 8 | public static int TryCount { get; set; } 9 | public static int TryInterval { get; set; } 10 | 11 | static TryRepeater() { 12 | TryCount = 10; 13 | TryInterval = 1000; 14 | } 15 | 16 | public static object Do(Func task) { 17 | for (int tryIndex = 0; tryIndex < TryCount; tryIndex++) { 18 | bool lastTry = tryIndex == TryCount - 1; 19 | try { 20 | return task(); 21 | } catch (Exception e) { 22 | if (lastTry || e is IDoNotRetryRedisOfficeException) 23 | throw e; 24 | Thread.Sleep(TryInterval); 25 | } 26 | } 27 | return null; 28 | } 29 | } 30 | 31 | } 32 | --------------------------------------------------------------------------------