Build Date for MVC or Visual Studio project

Shamelessly stolen from here

Project, create new folder Resources

Project, Properties: Build Events, Pre-Build event command line

echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"

Build your Project

Project, Resources: Create Default Resources File

..Add Resource, Existing File, …\Resources\BuildDate.txt

To read the build date, e.g. in a controller

protected override IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state)

ViewBag.BuildDate = Properties.Resources.BuildDate;



Azure DNS / HTTPS and FastHosts email

How to configure a domain name, https and email for your Azure web app

I tried (oh how i tried) to use a LetsEncrypt HTTPS certificate for my Azure-hosted web site by following Troy Hunt’s blog post

(all right, I gave it an hour…)

Then I looked more closely at the Azure portal and it turns out you can buy your domain and HTTPS certificate from there. It originally comes from GoDaddy and my domain plus certificate cost £50 ish (and a lot of clicking around).

How to buy a Top Level Domain from Microsoft Azure?

You have to go to Basic (more expensive) hosting to support https. On the plus side, now I can run my new site thru asafaweb without feeling bad…

And I also get an “Advanced DNS” page.

Now I want to send email from so I signed up for a fasthosts email account (£3/month).

To use this I have to “prove ownership”. This means 2 things

* Add some MX records
* Add a TXT record

I had a bit of trouble with the advanced DNS settings, but what they finally looked like was..

sql isnumeric(2,000.00)=1 but isfloat(2,000.00) errors Error converting data type varchar to float.

select isnumeric('20,000.000') returns 1
select convert(float, '20,000.000') raises an error Error converting data type varchar to float.

You can’t write a isfloat() function, because try-catch is a side effect.

Here’s a snippet to walk thru your data to find duff values

declare c cursor for
select chillirecipedetailid, amount_or from tblAbRecipes
open c
declare @id int, @val nvarchar(100)
fetch next from c into @id, @val
while @@FETCH_STATUS=0
 begin try
 declare @f float
 set @f = convert(float,@val)
 end try
 begin catch
 print 'duff value at ' + convert(nvarchar(20),@id) + ': ' + @val
 end catch;
 fetch next from c into @id, @val
close c
deallocate c

select isnumeric('20,000.000')
select convert(float, '20,000.000')


How to check a file exists in transact sql using xp_FileExists


exec sp_configure 'show advanced options',1
exec sp_configure 'xp_cmdshell', 1;

drop function sp_FileExists

if object_id('sp_FileExists') is null
 declare @sql nvarchar(2000)
 set @sql='
 create function dbo.sp_FileExists(@fn nvarchar(1000)) returns bit as
 declare @result int
 exec master.dbo.xp_fileexist @fn, @result output
 if @result = 1 return 1
 return 0 
 exec @sql

select DocumentId, 'd:\MyStaffFile_Files\media\' + DocumentPath 
,case when DocumentPath is null then 'no path'
 when dbo.sp_FileExists('d:\MyStaffFile_Files\media\' + DocumentPath) = 1 then 'exists'
 else 'does not exist'
from Documents

How to do a complete path directory listing with transact sql, xp_dirtree and a recursive common table expression

--How to Use xp_dirtree to List All Files in a Folder
--Recursive Directory Listing in Transact-SQL:
--enable extended procs

--enable extended procs (if you have permission! if not, you're stuffed)
EXEC sp_configure 'show advanced options', 1
EXEC sp_configure 'xp_cmdshell', 1

IF OBJECT_ID('tempdb..#DirectoryTree') IS NOT NULL
 DROP TABLE #DirectoryTree;

CREATE TABLE #DirectoryTree (
 fileId int IDENTITY(1,1)
 ,fullPath nvarchar(2000)
 ,subdirectory nvarchar(max)
 ,depth int
 ,isfile bit);

INSERT #DirectoryTree (subdirectory,depth,isfile)
EXEC master.sys.xp_dirtree 'C:\Projects\MyStaffFile2\SomeTestData',0,1;

;with fileparents(fileid, subdirectory, parentid, isfile) as (
 select c.fileid, c.subdirectory, (select max(p.fileId) from #DirectoryTree p where p.depth=c.depth-1 and p.fileId<c.fileId) parentId , c.isfile
 from #DirectoryTree c
),DirListing (fileid,subdirectory, isfile) as(
 select fileid, subdirectory + '' subdirectory, isfile from fileparents where parentid is null
 union all
 select f.fileid, d.subdirectory +'\' + f.subdirectory subdirectory, f.isfile
 from DirListing d join fileparents f on f.parentid=d.fileid
select l.subdirectory, 'file not in documents table' from DirListing l
left outer join Documents d on l.subdirectory=d.DocumentPath where d.DocumentId is null
--do something useful with this listing

--turn extended procs back off
EXEC sp_configure 'xp_cmdshell', 0

Delete all tables from a SQL database using Transact SQL Cursors

If you have a SQL2016 database but only SQL 2008R2 SSMS then you can’t delete tables with extreme prejudice using the DEL key, you get an error something like “index out of range”.

However this SQL will do the same job.

Just remember, it’s your foot…

From an idea from Richard…

declare @sql nvarchar(2048)
declare @tn nvarchar(200)

declare tablecursor cursor
select name from sys.tables
open tablecursor
fetch next from tablecursor into @tn
while @@FETCH_STATUS=0
print @tn
declare fkcursor cursor
‘ALTER TABLE [‘ + OBJECT_SCHEMA_NAME(parent_object_id) +
‘].[‘ + OBJECT_NAME(parent_object_id) +
‘] DROP CONSTRAINT [‘ + name + ‘]’
FROM sys.foreign_keys
WHERE referenced_object_id = object_id(@tn)
open fkcursor
fetch next from fkcursor into @sql
while @@fetch_status = 0
print @sql
fetch next from fkcursor into @sql
close fkcursor;
deallocate fkcursor

set @sql = ‘drop table ‘ + @tn

fetch next from tablecursor into @tn


Visual Studio 2017: Program in Invalid State: disable javascript debugging

With VS2017 and an project, you may get “Cannot start program, it’s in an invalid state”. This may be related to “enable javascript debugging for (chrome and ie)”.

Try restarting Chrome, IE or Edge.

Try turning off javascript debugging: in the quick launch bar type “javascript debugging” and enter. This takes you to Tools-Options-Debugging-General. Find “enable javascript debugging for (chrome and ie)” and untick it.



SQL rows to concatenated string

How to turn a list of (e.g.) countries into a concatenated string (e.g. France, New Zealand, California)

There’s a comprehensive post about different methods at : the method I’ve used is “Scalar UDF with t-SQL update extension”

ALTER function [dbo].[GetCountriesOfOrigin](@productId int) returns 
 declare @result varchar(max) 
 set @result = '' 
 select @result = @result + c.CountryOfOrigin + ', ' from tblProductCountry pc 
 inner join tblCountryOfOrigin c on pc.CountryOfOriginID=c.CountryOfOriginID 
 where pc.ProductID=@productId 
 order by c.CountryOfOrigin
 set @result = ltrim(rtrim(@result))
 if right(@result,1)=',' set @result=left(@result, len(@result)-1) --damn LEN! ignores trailing spaces
 if len(@result)=0 set @result=null
 return @result

Enable data audit and tracking

This sql script will add system versioning to all your tables in your existing SQL 2016 database.
For example table [Stuff] will have a [StuffHistory] table where all old values are logged.
As we have existing data, we have to do each table in four SQL statements and I don’t think we can make the columns HIDDEN.

 Set all tables in this database as SYSTEM VERSIONED TEMPORAL TABLES
 Version 1.1
 Nick Ajderian
Enable data audit and tracking
Convert existing table to temporal table
*/ /* create table stuff6(stuffid int identity primary key, body nvarchar(200)) update stuff6 set body=body+'x' insert into stuff6(body) values('hello ') select * from stuff6 select * from stuff6history */ declare @sql1 nvarchar(1024),@sql3 nvarchar(1024),@sql4 nvarchar(1024), @sql2 nvarchar(1024) declare @sqlx nvarchar(1024) set @sql1='ALTER TABLE TABLE_NAME ADD SysStartTime datetime2(0) not null DEFAULT SYSUTCDATETIME() , SysEndTime datetime2(0) not null DEFAULT CONVERT(datetime2 (0), ''9999-12-31 23:59:59.99999999'') ' set @sql2='UPDATE TABLE_NAME SET SysStartTime = ''19000101 00:00:00.0000000'', SysEndTime = ''99991231 23:59:59.9999999'' ' set @sql3='ALTER TABLE TABLE_NAME ADD PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime);' set @sql4='ALTER TABLE TABLE_NAME SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.TABLE_NAMEHistory))' --GENERATED ALWAYS AS ROW START HIDDEN CONSTRAINT DF_SysStart --GENERATED ALWAYS AS ROW END HIDDEN CONSTRAINT DF_SysEnd declare @tn nvarchar(200) declare c cursor for select name from sys.tables where not ( name like '%History' ) and not exists( select * from sys.tables tt where'history' ) and name not in ('temp_NHSPatients','Diagnosis','EinsteinData','tbl_DiagnosisImport','tbl_OverwriteCCGs_KH','tbl_OverwriteCCGs_KH2') order by name open c fetch next from c into @tn while @@FETCH_STATUS=0 begin print 'Adding temporal fields to ' + @tn set @sqlx = replace(@sql1,'TABLE_NAME', @tn) exec (@sqlx) set @sqlx = replace(@sql2,'TABLE_NAME', @tn) exec (@sqlx) set @sqlx = replace(@sql3,'TABLE_NAME', @tn) exec (@sqlx) set @sqlx = replace(@sql4,'TABLE_NAME', @tn) exec (@sqlx) fetch next from c into @tn end close c deallocate c