Wednesday, 30 October 2013

How to enable Kerberos Delegation in Google Chrome

* Using Registry Key

Set/Add this string registry key

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome]
Name: AuthNegotiateDelegateWhitelist
Value: *

* Using Command Line param

--auth-negotiate-delegate-whitelist=*

Delegation can be restricted to servers in the specific domain

*.mydomain.com

I’ve tested it with IIS + SQL Server and double hop delegation works fine.

You can read more about Google Chrome command line params here.

Tuesday, 22 October 2013

Remote debugging IIS Web Application from Visual Studio

Setup your debug environment as described in Remote debugging from Visual Studio post.

When you click ‘Attach’ select w3wp.exe process. If you’re running Application Pools with multiple version of .Net you might see more than one process so make sure you select the correct one.

DelegConfig Kerberos Delegation Configuration Reporting Tool by Brian Murphy-Booth

DelegConfig is an ASP.Net application to test Kerberos/Delegation configuration on your IIS & SQL Server. Useful for testing double hop authentication issues.

IIS Windows Authentication/Delegation issue with C# Parallel Tasks

When you use double-hop authentication (WebBrowser->IIS->SQL Server) code executed on the webserver inside Parallel.Invoke() or Task.Factory.StartNew() is no longer executed as authenticated user (domain\username) but is being changed to (domain\iisservername$). You can see it in Environment.UserName when debuging. So if you're executing any SQL queries as Tasks you might get permission denied errors.

The way to fix it is to pass custom TaskScheduler from CurrentSynchronizationContext

Parallel.Invoke(
  new ParallelOptions()
  {
    TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
  },
  () => { /*do something here;*/ },
);
 
Task.Factory.StartNew(
  () => { /*do something here;*/ }, 
  CancellationToken.None, 
  TaskCreationOptions.None,
  TaskScheduler.FromCurrentSynchronizationContext()
);

This is a good article about SynchronizationContext It's All About the SynchronizationContext

Thursday, 17 October 2013

SQL Copy data in batches

-- SOURCE TABLE
DECLARE @Table1 TABLE
(
  AsOf DATETIME,
  Company VARCHAR(50),
  Name VARCHAR(50)
)
 
INSERT INTO @Table1
SELECT '20130101','Company1','John'
UNION SELECT '20130102','Company2','Tom'
UNION SELECT '20130101','Company3','Peter'
UNION SELECT '20130102','Company4','Ian'
 
-- DESTINATION TABLE
DECLARE @Table2 TABLE
(
  AsOf DATETIME,
  Company VARCHAR(50),
  Name VARCHAR(50)
)
 
-- BATCH TABLE
DECLARE @Batches TABLE
(
  AsOf DATETIME
)
 
INSERT INTO @Batches
SELECT DISTINCT AsOf FROM @Table1
 
-- COPY IN BATCHES
DECLARE @AsOf DATETIME
WHILE (Exists(SELECT 1 FROM @Batches))
BEGIN TRY  
  BEGIN TRAN   
    SELECT @AsOf = MIN(AsOf) FROM @Batches
    PRINT CONVERT(VARCHAR(20),GETDATE(),20) + ',' + 'Copying data for: '+convert(VARCHAR(8),@AsOf,112)
 
    INSERT INTO @Table2 (
      AsOf,
      Company,
      Name
    )
    SELECT
      AsOf,
      Company,
      Name
    FROM @Table1
    WHERE AsOf = @AsOf
 
    DELETE FROM @Batches WHERE AsOf = @AsOf
  COMMIT TRAN 
END TRY
BEGIN CATCH 
  ROLLBACK
END CATCH
 
-- SHOW RESULTS
SELECT * FROM @Table2

Monday, 14 October 2013

C# Convert double to decimal

This is a workaround to Convert.ToDecimal(Double) limitation of 15 significant digits by using ‘R’ Round-trip Format Specifier.

Convert.ToDecimal Method (Double)
“The
Decimal value returned by this method contains a maximum of 15 significant digits. If the value parameter contains more than 15 significant digits, it is rounded using rounding to nearest. The following example illustrates how the Convert.ToDecimal(Double) method uses rounding to nearest to return a Decimal value with 15 significant digits.”

decimal.Parse(dbl.ToString("R"))
[Test]
public void ConvertDoubleToDecimal()
{
  Compare(1.00000000000006d,  1.00000000000006M);
  Compare(1.00000000000004d,  1.00000000000004M);
  Compare(1.000000000000066d, 1.000000000000066M);
  Compare(1.000000000000044d, 1.000000000000044M);
}
 
private void Compare(double dbl, decimal dec)
{
  Convert.ToDecimal("0.d0d.");
  var d1 = Convert.ToDecimal(dbl);
  var d2 = new Decimal(dbl);
  var d3 = decimal.Parse(dbl.ToString("R"));
  Console.WriteLine(@"
DOUBLE : {0:R}
CONVERT: {1} {2}
NEW  : {3} {4}
'R'  : {5} {6}", 
      dbl, 
      d1, d1.Equals(dec) ? "OK" : "FAILED",
      d2, d2.Equals(dec) ? "OK" : "FAILED", 
      d3, d3.Equals(dec) ? "OK" : "FAILED");
}
DOUBLE : 1.00000000000006
CONVERT: 1.00000000000006 OK
NEW    : 1.00000000000006 OK
'R'    : 1.00000000000006 OK
 
DOUBLE : 1.00000000000004
CONVERT: 1.00000000000004 OK
NEW    : 1.00000000000004 OK
'R'    : 1.00000000000004 OK
 
DOUBLE : 1.000000000000066
CONVERT: 1.00000000000007 FAILED
NEW    : 1.00000000000007 FAILED
'R'    : 1.000000000000066 OK
 
DOUBLE : 1.000000000000044
CONVERT: 1.00000000000004 FAILED
NEW    : 1.00000000000004 FAILED
'R'    : 1.000000000000044 OK