Which Version of TypeScript does Visual Studio use?

April 14, 2016

I really love TypeScript.

I started out with version 0.8 in VS 2010 because of a (mostly) client-side web project. I always tried to avoid JavaScript because I prefer programming languages that compile, and I found that finally TypeScript was the way to go.

Projects live on, and VS 2013 got installed on the PC, along with (manually installed) TypeScript 1.4. Now colleagues are already on VS 2015, and we need to have the same TypeScript compiler. So which version of TypeScript does Visual Studio use?

ts2013

No indication that version 1.4 is installed

As far as I’m aware, VS 2013 does not provide the means to display the currently used TypeScript version. Answers to a related question on SO suggest to

  • open cmd and run tsc -v
  • use VS Command Prompt and run tsc -v
  • open the Package Manager Console and run tsc -v

but the always result in the message

Unknown option ‘v’

What’s going on here?

TypeScript is installed under C:\Program Files\Microsoft SDKs\TypeScript (or C:\Program Files (x86)\Microsoft SDKs\TypeScript on 64-bit Windows). To my surprise, I found 3 versions installed: 0.8.0.0, 1.0, 1.4, but the list of installed software in Programs and Features only listed 0.8.0.0 (“TypeScript for Microsoft VS 2012”) and 1.4.

Where did TypeScript version 1.0 come from? Apparently it got installed while applying VS2013 Update 5, judging from the directory timestamps. Oops: It might also have been installed with VS2013, and some timestamps updated during upgrade.

Different versions, different help message

This is the output if you run tsc from the directory 0.8.0.0:

Syntax:   tsc [options] [file ..]

Examples: tsc hello.ts
          tsc --out foo.js foo.ts
          tsc @args.txt

Options:
  -c, --comments  Emit comments to output
  --declarations  Generates corresponding .d.ts file
  -e, --exec      Execute the script after compilation
  -h, --help      Print this message
  --module KIND   Specify module code generation: "commonjs" (default) or "amd"
  --nolib         Do not include a default lib.d.ts with global declarations
  --out FILE      Concatenate and emit output to single file
  --target VER    Specify ECMAScript target version: "ES3" (default), or "ES5"
  @<file>         Insert command line options and files from a file.

Note that there is no '-v' option!

This is the output of tsc run from directory 1.0:

Version 1.0.3.0
Syntax:   tsc [options] [file ..]

Examples: tsc hello.ts
          tsc --out foo.js foo.ts
          tsc @args.txt

Options:
  --codepage NUMBER             Specify the codepage to use when opening source
files.
  -d, --declaration             Generates corresponding .d.ts file.
  -h, --help                    Print this message.
  --mapRoot LOCATION            Specifies the location where debugger should loc
ate map files instead of generated locations.
  -m KIND, --module KIND        Specify module code generation: 'commonjs' or 'a
md'
  --noImplicitAny               Warn on expressions and declarations with an imp
lied 'any' type.
  --out FILE                    Concatenate and emit output to single file.
  --outDir DIRECTORY            Redirect output structure to the directory.
  --removeComments              Do not emit comments to output.
  --sourcemap                   Generates corresponding .map file.
  --sourceRoot LOCATION         Specifies the location where debugger should loc
ate TypeScript files instead of source locations.
  -t VERSION, --target VERSION  Specify ECMAScript target version: 'ES3' (defaul
t), or 'ES5'
  -v, --version                 Print the compiler's version: 1.0.3.0
  @<file>                       Insert command line options and files from a fil
e.

tsc -v results in

Version 1.0.3.0

This is the output of tsc run from directory 1.4:

Version 1.4.0.0
Syntax:   tsc [options] [file ...]

Examples: tsc hello.ts
          tsc --out file.js file.ts
          tsc @args.txt

Options:
 -d, --declaration                 Generates corresponding '.d.ts' file.
 -h, --help                        Print this message.
 --mapRoot LOCATION                Specifies the location where debugger should
locate map files instead of generated locations.
 -m KIND, --module KIND            Specify module code generation: 'commonjs' or
 'amd'
 --noEmitOnError                   Do not emit outputs if any type checking erro
rs were reported.
 --noImplicitAny                   Warn on expressions and declarations with an
implied 'any' type.
 --out FILE                        Concatenate and emit output to single file.
 --outDir DIRECTORY                Redirect output structure to the directory.
 --preserveConstEnums              Do not erase const enum declarations in gener
ated code.
 --removeComments                  Do not emit comments to output.
 --sourceMap                       Generates corresponding '.map' file.
 --sourceRoot LOCATION             Specifies the location where debugger should
locate TypeScript files instead of source locations.
 --suppressImplicitAnyIndexErrors  Suppress noImplicitAny errors for indexing ob
jects lacking index signatures.
 -t VERSION, --target VERSION      Specify ECMAScript target version: 'ES3' (def
ault), 'ES5', or 'ES6' (experimental)
 -v, --version                     Print the compiler's version.
 -w, --watch                       Watch input files.
 @<file>                           Insert command line options and files from a
file.

tsc -v results in

message TS6029: Version 1.4.0.0

Due to whatever installation magic the installers perform, the PATH environment variable contains the directories related to TypeScript in this order:

C:\Program Files\Microsoft SDKs\TypeScript\0.8.0.0\;
C:\Program Files\Microsoft SDKs\TypeScript\1.0\;
C:\Program Files\Microsoft SDKs\TypeScript\1.4\;

which explains why the oldest version of TypeScript is called when invoked from command line.

This sequence is the same in Visual Studio Command Prompt (2010), which is OK due to compatibility. But the Developer Command prompt for VS2013 prepends version 1.0, resulting in

C:\Program Files\Microsoft SDKs\TypeScript\1.0\;
C:\Program Files\Microsoft SDKs\TypeScript\0.8.0.0\;
C:\Program Files\Microsoft SDKs\TypeScript\1.0\;
C:\Program Files\Microsoft SDKs\TypeScript\1.4\;

This is because the VsDevCmd.bat – which initializes all VS-related paths and environment variables – checks for version 1.0, but no higher version:

@rem Add path to TypeScript Compiler
@if exist "%ProgramFiles%\Microsoft SDKs\TypeScript\1.0" set PATH=%ProgramFiles%\Microsoft SDKs\TypeScript\1.0;%PATH%
@if exist "%ProgramFiles(x86)%\Microsoft SDKs\TypeScript\1.0" set PATH=%ProgramFiles(x86)%\Microsoft SDKs\TypeScript\1.0;%PATH%

And my project?

And just in case you’re wondering which version of TypeScript your project is using, open its .csproj file in a text editor and search for TypeScript:

    <TypeScriptToolsVersion>1.4</TypeScriptToolsVersion>

Blogger Allen Conway had similar experience regarding this question.


Upgrading ASP.Net MVC3 to Visual Studio 2013

April 7, 2016

I migrated an ASP.Net MVC 3 application from VS 2010 to VS 2013, adding a reference to version 3 of System.Web.Mvc, and never experienced problems as compilation of C# code was still working, and I mainly coded in TypeScript (manually updated to version 1.4).

Only when I had to edit Razor views (.cshtml), I noticed the red squiggles in the IDE. But hey, it still compiled.

Now I had a look into this problem, and found various lots of questions on the internets:

As it turns out, different versions of Visual Studio are compatible only with specific versions of ASP.Net MVC.

From the MSDN articles on Visual Studio 2013 Compatibility and Porting, Migrating, and Upgrading Visual Studio Projects (2015) we can extract the following compatibility matrix:

Visual Studio .Net Framework MVC Version
2010 SP1 4 2, 3
2012 4.5, 4.5.1 3, 4
2013 4.5, 4.5.1 4, 5(*)
2015 4.5, 4.5.1 4, 5(*)

(*) MVC 5 can be installed using NuGet Package Manager.

Next, I tried to follow this upgrade instruction, but failed because ASP.Net MVC 4 is no longer available on nuget.

So here is my personal upgrade guide from VS2010 to VS2013/MVC5:

  • In your web application project, set the Target framework from “.Net Framework 4” to “.Net Framework 4.5”, otherwise you won’t find the current MVC package on nuget.
  • If other projects in your solution also depend on System.Web.Mvc, you need to re-target these projects as well
  • Open the NuGet Manager for Solution, locate the current MVC package (currently 5.2.3), and install it in all projects that reference MVC
  • Since we are already in NuGet, it might be a good idea to reference other 3rd party libraries from NuGet as well (NewtonSoft.JSON in my case, probably also jQuery depending on your support for legacy browsers)

If you compile now, the aspnetcompiler will complain about invalid assembly version numbers in your web.config files.

To resolve this, create a new ASP.Net MVC project from scratch, and compare the root web.config and Views\web.config files

old web.config:

<system.web>
  <compilation debug="true" targetFramework="4.0">
    <assemblies>
      <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add assembly="System.Web.Mvc, Version=3.0.0.1, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
      <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.1" />
    </dependentAssembly>

new web.config:

<appSettings>
  <add key="webpages:Version" value="3.0.0.0"/>
  <add key="webpages:Enabled" value="false"/>
  <add key="PreserveLoginUrl" value="true"/>
</appSettings>
<system.web>
  <compilation debug="true" targetFramework="4.5">
    <assemblies>
      <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add assembly="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add assembly="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add assembly="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add assembly="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </assemblies>
  </compilation>
  <pages controlRenderingCompatibilityVersion="4.0">
<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35"/>
      <bindingRedirect oldVersion="1.0.0.0-1.5.2.14234" newVersion="1.5.2.14234"/>
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
      <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
      <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
      <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
    </dependentAssembly>
  </assemblyBinding>
</runtime>

old Views\web.config:

<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
    <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<system.web.webPages.razor>
  <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.1, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

new Views\web.config:

<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
    <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<system.web.webPages.razor>
  <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<appSettings>
  <add key="webpages:Enabled" value="false" />
  <add key="webpages:Version" value="3.0.0.0" />
</appSettings>
<system.web>
  <compilation>
    <assemblies>
      <add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    </assemblies>
  </compilation>
</system.web>

That’s it.


Remove Unused References with Visual Studio 2013

December 3, 2014

My favorite reference removal tool, Reference Assistant, only target Visual Studio 10 (2010) and 11 (2012), according to the description.

To install it in VS 2013, you need to follow the tips given on the Q&A tab of the assistant’s page on the Visual Studio Gallery:

So, the manifest file in this extension has a typo, which is why it wont install in VS2013. Change the vsix file to .zip, unzip it, edit the manifest file for the installationtargets from “[11.0,12.0)” to “[11.0,12.0]” and save it. Select all the files and zip it up. Rename the zip file to .vsix again and install.

If you follow those instructions literally,

  • rename the .vsix to .zip
  • unzip the .zip
  • edit the extension.vsixmanifest file
  • replace every instance of
InstallationTarget Version="[11.0,12.0)"

with

InstallationTarget Version="[11.0,12.0]"
  • save the file
  • zip all files
  • rename the .zip to .vsix

then the modified vsix can be installed in VS2013.

When I first tried it (by not following exactly), I simply dragged the .vsixmanifest file out of the .zip, edited it, and then moved it back into the .zip using Windows Explorer, I actually received the error message reported in the Q&A:

Microsoft.VisualStudio.ExtensionManager.InvalidExtensionPackageException:
The file is not a valid VSIX package.
---> System.IO.FileFormatException: File contains corrupted data.

Good to have the tool in the latest version of VS as well 😉


Fixing “The type ‘System.Web.Mvc.***’ is defined in an assembly that is not referenced.”

November 19, 2014

In Visual Studio 2010, I tried to compile an ASP.Net MVC 3 project that I have been working on for months, and suddenly received the error messages

The type ‘System.Web.Mvc.IAuthorizationFilter’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Web.Mvc, Version=3.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35’.

The type ‘System.Web.Mvc.FilterAttribute’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Web.Mvc, Version=3.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35’.

Turns out that by installing Visual Studio 2013 (or one its product updates) switches from 3.0.0.0 to 3.0.0.1, as a quick glance in the .csproj reveals:

<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, 
    PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />

versus

<Reference Include="System.Web.Mvc, Version=3.0.0.1, Culture=neutral, 
    PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />

By removing the reference and re-adding it, the solution compiled again successfully.


Custom XSD Validation in Visual Studio 2013

November 6, 2014

We developed an XSD schema, and wanted to create valid .cshtml markup using Visual Studio.

Based on tips found on the internet, I managed to get this working on VS2010 (sorry, didn’t write about it 😉 ), but for VS2013, the solution seems to be different again.

Here’s how I managed to get custom XSD validation in VS2013:

  • Put a copy of your XSD in the directory
C:\Program Files[ (x86)]\Microsoft Visual Studio 12.0\Common7\Packages\schemas\html
  • Open regedit.exe and navigate to the key
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0_Config\Packages\{1B437D20-F8FE-11D2-A6AE-00104BCC7269}\Schemas

This reg key holds all schemas for the VS “package” Visual Studio HTM Editor Package”.

The value of “File” is the relative path to the .xsd, in our case “html\my.xsd”.

  • Add a string named “Friendly Name”

The value of “Friendly Name” is the name to be displayed in the validation settings.

  • Add a DWord named IsBrowseable

Not sure whether this is required, but HTML5 and XHTML5 also have it. Set its value to 1.

Alternatively, you can also create a .reg file, set the values according to your environment, and import using regedit:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0_Config\Packages\{1B437D20-F8FE-11D2-A6AE-00104BCC7269}\Schemas\http://tempuri.org/my.xsd]
"File"="html\\my.xsd"
"Friendly Name"="My Schema"
"IsBrowseable"=dword:00000001

Start Visual Studio 2013, and navigate to Tools, Options, Text Editor, HTML (Web Forms). Or simply type “valid” in the search box of the Options dialog.

You will find your entry “My Schema” in the dropdown list “Target when no doctype found:”.

If you only want to edit files confirming to your schema, then select it here.

Otherwise, close the dialog, and right-click the toolbar (right below the menu bar) and check the item “HTML Source Editing”. Now the toolbar will also contain the Target Schema selection dropdown.

BUT: If you open a .cshtml by double-clicking, the source will be displayed, but the Target Schema dropdown is inactive!

The reason is that, whoever invented this whole thing, there is a difference between “HTML Editor” and “HTML (Web Forms) Editor”!

Right-click the .cshtml file, and select “Open With…”. In my installation, HTML Editor is the default for .cshtm, but you can set the Web Forms editor as default using the, uhm, “Set as Default” button.

So now, either way you open the .cshtml in the “HTML (Web Forms) Editor”, the Target Schema selection dropdown is now active, and your custom schema can be selected for validation.

Unfortunately, Razor does not seem to be supported in the Web Forms Editor (high-lighting etc), so you need to choose between Razor-enabled unvalidated or Razor-disabled validated editing. Really?

Sources: SO, AngularJS, MSDN Social.


Calling xsd.exe in VS 2013 Build Event

July 24, 2014

While working on an XML project, I wanted to call xsd.exe on an .xsd file during the build process, and found this solution on SO, which works for VS 2010.

For VS 2013, the solution did not work anymore, especially on systems that had no prior version of VS installed, since xsd.exe hides in a different location.

A comment to the answer illustrated how to query the registry correctly on x64 systems.

So my modified pre-build event looks like this:

call "$(ProjectDir)GenerateFromVSPrompt.cmd"
  "$(ProjectDir)"
  "$([MSBuild]::GetRegistryValueFromView(
    'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1A',
    'InstallationFolder', null, RegistryView.Registry64, RegistryView.Registry32)
    )bin\NETFX 4.5.1 Tools\xsd.exe"

all in 1 line.

If you use TFS as source control, you know that generated files need to be checked out before they can be overwritten.

I already wrote about TFS and code generation, and used the vcvarsall.bat then.

However, since we just need the path to tf.exe, and use the same VS version, we can just open a VS Command Prompt, run

where tf

and get the answer

C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\TF.exe

for VS 2013.

So our batch file GenerateFromVSPrompt.cmd looks like this:

set tf="C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\TF.exe"
%tf% checkout %1MyXsdClasses.cs
call %1XSDBuilder.cmd %1 %2
%tf% checkin /comment:"build event" /noprompt %1MyXsdClasses.cs
exit 0

In case tf.exe cannot check in the file because it did not change during code generation, it will return with exit code 1 which in turn will cause the build process to issue a build error and break. So we use exit 0 to clear the error condition

Finally, my version of XSDBuilder.cmd is based on an SO answer, but stripped down to only what is necessary, since I only have 2 XSD files, AND they need to be processed together:

pushd %1
%2 MyXsd1.xsd MyXsd2.xsd /c /n:My.Project.Xsd
popd

and, as I write, I really should merge both .cmd files into one … 😉

The build event is now executed correctly from VS, the VS Command Prompt, and on the build server.


Using Linked Files in ASP.Net Applications

March 24, 2014

One of the web applications I maintain still runs on ASP.Net 3.5. A specific feature required that there also be a .Net 4 version of the application, so I thought about how to share the source code for both .Net versions.

Essentially, this can be achieved by creating a new solution and new projects and having the projects link to the original source files. That’s ok so far and it works fine.

However, when it comes to the ASP.Net application itself, things do not work straight forward:

My build process invokes both aspnet_compiler and aspnet_merge where aspnet_compiler requires all markup files to be present in the project directory, as it seems to ignore the contents of the .csproj file.

So how do I get the markup files into the linking project without manually copying the files? The process should be performed automatically, so that any changes in the original source are propagated to the linking project.

Luckily I found this article Using Linked Files in ASP.Net Applications, which unfortunately has been removed recently. In principle, you need to specify new build targets that invoke the file copy for the linked files. While the original solution only covered copying “content” files, I extended it to also copy “compile” files:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="CopyLinkedContentFiles">
    <Copy Condition=" '%(Content.Link)' != '' " 
                SourceFiles="%(Content.Identity)" 
                DestinationFiles="$(OutputPath)\..\%(Content.Link)" 
                SkipUnchangedFiles="true" />
    <Message Text="Copying linked file %(Content.Link)" />
  </Target>
  <Target Name="CopyLinkedCompileFiles">
    <Copy Condition=" '%(Compile.Link)' != '' " 
                SourceFiles="%(Compile.Identity)" 
                DestinationFiles="$(OutputPath)\..\%(Compile.Link)" 
                SkipUnchangedFiles="true" />
    <Message Text="Copying linked file %(Compile.Link)" />
  </Target>
  <PropertyGroup>
    <BuildDependsOn>
      CopyLinkedContentFiles;
      CopyLinkedCompileFiles;
      $(BuildDependsOn);
    </BuildDependsOn>
  </PropertyGroup>

Save the file as CopyLinks.targets in your project directory. Then edit the .csproj file to add the line

  <Import Project="$(MSBuildProjectDirectory)\CopyLinks.targets" />

(find other <Import> sections and insert there).

As you build your  project, the linked files will now be copied to the respective location in the project linked the original files.

The complete targets file can be downloaded here.