Consuming the POST request data from EMIE for Internet Explorer 11
Everyone should know by now that come January 12, 2016 Microsoft will provide limited support for browser versions earlier than 11. That means Enterprise customers should really consider upgrading to version 11. The above link will show you the support versions.
I'm assuming you are well on your way to setting up your group policy objects to push out the following policies:
This post will focus on how to better consume what goes in text box below…. It is the policy above. If you don't see any of these options make sure you've installed the latest Internet Explorer onto the server or retrieve the templates from here.
Enterprise Mode for Internet Explorer will send a POST request to pretty much anything that can accept it. Most examples show a simple POST and reference to a web server. In this case you just need to look up the entry in the IIS log file and voila there you have it.
My problem is that, even with a handy tool such as the old-school Log Parser, while you can get the results, it isn't a nice format. I'd rather store the data inside of a database.
Follow these steps in any order you want… It is the end result that really matters….
Step One – Configure SQL Server
I'm using SQL Server 2012, but any recent one should work without a problem. You should ask your DBA if you are uncertain as to managing your SQL Server. We need to create a database, table, and stored procedure
Database Creation Script
USE [master]
GO
/****** Object: Database [EMReporting] Script Date: 11/26/2014 2:54:09 PM ******/
CREATE DATABASE [EMReporting]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'EMReporting',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\EMReporting.mdf' ,
SIZE = 4096KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'EMReporting_log',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\EMReporting_log.ldf' ,
SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
ALTER DATABASE [EMReporting] SET COMPATIBILITY_LEVEL = 110
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [EMReporting].[dbo].[sp_fulltext_database] @action = 'enable'
end
GO
ALTER DATABASE [EMReporting] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [EMReporting] SET ANSI_NULLS OFF
GO
ALTER DATABASE [EMReporting] SET ANSI_PADDING OFF
GO
ALTER DATABASE [EMReporting] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [EMReporting] SET ARITHABORT OFF
GO
ALTER DATABASE [EMReporting] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [EMReporting] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE [EMReporting] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [EMReporting] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [EMReporting] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [EMReporting] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [EMReporting] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [EMReporting] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [EMReporting] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [EMReporting] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [EMReporting] SET DISABLE_BROKER
GO
ALTER DATABASE [EMReporting] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [EMReporting] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [EMReporting] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [EMReporting] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [EMReporting] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [EMReporting] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [EMReporting] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [EMReporting] SET RECOVERY FULL
GO
ALTER DATABASE [EMReporting] SET MULTI_USER
GO
ALTER DATABASE [EMReporting] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [EMReporting] SET DB_CHAINING OFF
GO
ALTER DATABASE [EMReporting] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
GO
ALTER DATABASE [EMReporting] SET TARGET_RECOVERY_TIME = 0 SECONDS
GO
ALTER DATABASE [EMReporting] SET READ_WRITE
GO
Table Creation Script
USE [EMReporting]
GO
/****** Object: Table [dbo].[EMIntervention] Script Date: 11/26/2014 2:54:52 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[EMIntervention](
[Id] [int] IDENTITY(1,1) NOT NULL,
[status] [nchar](3) NULL,
[referrer] [nvarchar](max) NULL,
[username] [nvarchar](50) NULL,
[ipaddress] [nvarchar](50) NULL,
[timestamp] [datetime] NULL,
CONSTRAINT [PK_EMIntervention] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Stored Procedure Creation Script
USE [EMReporting]
GO
/****** Object: StoredProcedure [dbo].[InsertIntoTable] Script Date: 11/26/2014 2:55:17 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[InsertIntoTable]
(
@status nchar(3) = NULL,
@referrer nvarchar(MAX) = NULL,
@username nvarchar(50) = NULL,
@ipaddress nvarchar(50) = NULL,
@timestamp datetime
)
AS
SET NOCOUNT OFF;
INSERT INTO [EMIntervention] ([status], [referrer], [username], [ipaddress], [timestamp])
VALUES (@status, @referrer, @username, @ipaddress, @timestamp);
GO
Step Two – Configure IIS and push below code to web server
IIS Configuration
You should be able to get away with using mostly default settings when you create a new web site. Just ensure these key three things:
1) Disable all authentication (Features View of the site) except for Windows Authentication. Keep it enabled.
2) Ensure the application pool supports the 4. NET Framework.
3) Create firewall exception if you are using a non-default port in the binding. Above I'm pointing to port 8088.
Web Application
The below was written with Visual Studio 2012 (Update 4).
1) Create an empty ASP.Net Web application.
2) Add a new WebForm (mine is called Post.aspx). In the code behind, this is what I wrote inside of the partial class…
1: public struct DataBlock
2: {
3: public DateTime timestamp { get; set; }
4: public string referrer { get; set; }
5: public string user { get; set; }
6: public string ipaddress { get; set; }
7: public string status { get; set; }
8: }
9:
10: protected string GetIPAddress()
11: {
12: System.Web.HttpContext context = System.Web.HttpContext.Current;
13: string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
14:
15: if (!string.IsNullOrEmpty(ipAddress))
16: {
17: string[] addresses = ipAddress.Split(',');
18: if (addresses.Length != 0)
19: {
20: return addresses[0];
21: }
22: }
23:
24: return context.Request.ServerVariables["REMOTE_ADDR"];
25: }
26:
27:
28: protected void Page_Load(object sender, EventArgs e)
29: {
30: DataBlock datablock = new DataBlock();
31:
32: datablock.timestamp = HttpContext.Current.Timestamp;
33: datablock.referrer = Request.Form["URL"];
34: datablock.status = Request.Form["EnterpriseMode"];
35: datablock.user = Request.LogonUserIdentity.Name;
36: datablock.ipaddress = GetIPAddress();
37:
38: WriteToSqlServer(datablock);
39: }
40:
41: private void WriteToSqlServer(DataBlock datablock)
42: {
43: string strConnection = ConfigurationManager.ConnectionStrings["EMReportingConnectionString"].ConnectionString;
44: using (SqlConnection connection = new SqlConnection(strConnection))
45: {
46: connection.Open();
47: using (SqlCommand command = new SqlCommand())
48: {
49: command.Connection = connection;
50: command.CommandType = CommandType.StoredProcedure;
51: command.CommandText = "dbo.InsertIntoTable";
52: command.Parameters.AddWithValue("@status", datablock.status);
53: command.Parameters.AddWithValue("@referrer", datablock.referrer);
54: command.Parameters.AddWithValue("@username", datablock.user);
55: command.Parameters.AddWithValue("@ipaddress", datablock.ipaddress);
56: command.Parameters.AddWithValue("@timestamp", datablock.timestamp);
57: command.ExecuteNonQuery();
58: }
59: }
60: }
Here's a breakdown:
Lines 1-8: I'm defining a structure for easier usage when passing as a parameter.
Line 10-25: It is a helper function that returns the client IP. You may want to modify it as you see fit. I'm not using a load balancer in my testing.
Lines 28-39: It is retrieving information about the request such as IP Address, timestamp, the user name (this is why we have windows authentication enabled) and two interesting ones: URL and EnterpriseMode. You can see these two items in the POST body. Below is a screenshot of a Fiddler Inspector called "TextView" from when a user turns off Enterprise Mode for a given site.
This information is really useful because the IT Admin can keep track of what sites individual users enabled/disabled (On/Off) Enterprise Mode against. The idea is to ultimately consolidate these findings into the Enterprise Mode Site List. That second policy definition further up in this post (https://SERVER01:8088/sites.xml) OR fix the sites you missed during the initial inventory process.
Lines 41-60: This code calls a stored procedure that writes the data neatly to a table… It assumes you have a stored procedure called "dbo.Insert". See Step One – Configure SQL Server.
3) Make sure that your project's web.config is pointing to the database. I'm using SQL Authentication since I defined a user that has access to the particular database/table. Here is what I am using inside of my web.config file.
1: <configuration>
2: <connectionStrings>
3: <add name="EMReportingConnectionString" connectionString="Data Source=sqlserver01;Initial Catalog=EMReporting;user id=EMUser;Password=[EnterPasswordHere]"
4: providerName="System.Data.SqlClient" />
5: </connectionStrings>
6: <system.web>
7: <compilation debug="true" targetFramework="4.5" />
8: <httpRuntime targetFramework="4.5" />
9: </system.web>
10:
11: </configuration>
4. Deploy the application. I used the built in "Publish" mechanism from within Visual Studio. You just need to make sure the development and target machines have at least Web Deploy 3.5 installed.
End Result
If the code (Step Two) compiled and was deployed properly AND you've successfully created the database, table, and stored procedure (Step One) AND there is a group policy defining where to POST the end user action, you can now focus on the client.
When a client goes to a site and say it looks bad and decided to enable Enterprise Mode via Tools –> Enterprise Mode, EMIE will send a POST to your ASPX page which in turn sends the results via stored procedure into a SQL Table.
You go to the SQL Server and take a look and this is what you get:
The sample project and SQL scripts can be downloaded from here.