Matt Ward

LibMan support in Visual Studio for Mac

The Library Manager addin provides Microsoft Library Manager (LibMan) support for Visual Studio for Mac. LibMan provides a way to install third-party client-side JavaScript libraries for ASP.NET Core and ASP.NET projects.

Features

  • Add Client-Side Library dialog
  • Restore client-side libraries
  • Deleting client-side libraries
  • Automatic client-side library restore on saving libman.json file

Full text editor support is not currently available. The following text editor quick actions are not supported:

  • Uninstall a client-side library
  • Check for client-side library updates

Supports

  • Visual Studio Mac 8.1 or later.
  • ASP.NET Core and ASP.NET projects

Add Client-Side Library Dialog

To open the Add Client-Side Library dialog, right click the project, or a folder, and select Add – Client-Side Library.

Add - Client-Side Library menu

Add Client-Side Library dialog

The library provider can be selected from the Provider list.

Typing in the Library text field will search the library provider and show a list of matching libraries.

Add Client-Side Library dialog completion list

Pressing tab or return will insert the selected library from the completion list into the Library text field.

You can then choose to include all the client-side library files or a selection of those files.

Add Client-Side Library dialog select files

The Target Location indicates where the client-side library files will be installed.

Clicking the Install button will create a libman.json file and install the client-side library into your project.

jQuery installed into project

More detailed information about the client-side library installation is available by clicking the status bar or by selecting View – Pads – Library Manager Output.

Library Manager Output window

Adding a libman.json file

To add a libman.json file without using the Add Client-Side Library dialog, right click the ASP.NET project and select Manage Client-Side Libraries.

Manage Client-Side Libraries menu

This will create a libman.json file and open it in the text editor.

libman.json file in text editor

Restoring Client-Side Libraries

To restore the client-side libraries you can right click the libman.json file in the Solution window and select Restore Client-Side Libraries.

Restore Client-Side Libraries menu

Information about the restore operation is available from the Library Manager Output window.

Alternatively saving the libman.json file in the text editor will run a restore.

Restore errors are displayed in the Errors window and in the libman.json file if it is open in the text editor.

LibMan restore error

Deleting Client-Side Libraries

To remove the client-side libraries you can right click the libman.json file in the Solution window and select Clean Client-Side Libraries.

Clean Client-Side Libraries menu

This will delete the client-side libraries from the project.

Library Manager Addin Installation

The Library Manager addin is available from the Visual Studio for Mac extensions repository. To install the addin:

  • From the main menu, open the Extensions Manager dialog.
  • Select the Gallery tab.
  • Expand IDE extensions.
  • Select the Library Manager addin
  • Click the Refresh button if the addin is not visible.
  • Click Install… to install the addin.
  • Restart Visual Studio for Mac.

Links

NuGet Support in Visual Studio for Mac 8.1

Changes

  • NuGet 5.0 support
  • Fixed PackageReference metadata not added for development dependencies
  • Fixed DotNetCliToolReferences not being restored
  • Fixed Multiplatform Library build error with Android projects

More information on all the new features and changes in Visual Studio for Mac 8.1 can be found in the release notes.

NuGet 5.0 support

NuGet 5.0.2.5988 is now included with Visual Studio for Mac 8.1.

Bug Fixes

Fixed PackageReference metadata not added for development dependencies

Installing a NuGet package that is a development dependency, such as GitInfo, would not add the PrivateAssets nor the IncludeAssets metadata to the PackageReference. This is now supported and mirrors the behaviour of ‘dotnet add package’ and Visual Studio on Windows.

Fixed DotNetCliToolReferences not being restored

DotNetCliToolReferences are available in the package dependency graph but are treated as separate projects in this graph. Since these did not map to an existing project in the solution they were not added to the full dependency graph which resulted in these tools not being restored.

DotNetCliToolReferences are only restored when the entire solution is restored. Restoring a single project only restores the project itself not the dotnet cli tool project referenced by the project.

MSBuild supports restoring DotNetCliToolReferences in any project type that uses PackageReferences so Visual Studio for Mac also supports this.

Fixed Multiplatform Library build error with Android projects

When generating a Portable Class Library (PCL) assembly from the intersection of project assemblies the ApiIntersect build task would throw an exception since it could not resolve the Mono.Android assembly. This problem has been fixed in a more recent NuGet.Build.Packaging where the failure to resolve has been converted to a warning.

1
2
3
4
5
6
7
8
9
10
System.Exception: Could not resolve Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065
    at ApiIntersect.FrameworkAssemblyResolver.Resolve (Mono.Cecil.AssemblyNameReference name, Mono.Cecil.ReaderParameters parameters) [0x0001b] in <aac3e0d5bcd4473a96e385115da49b96>:0
    at ApiIntersect.FrameworkAssemblyResolver.Resolve (Mono.Cecil.AssemblyNameReference name) [0x00000] in <aac3e0d5bcd4473a96e385115da49b96>:0
    at ICSharpCode.Decompiler.Ast.Transforms.IntroduceUsingDeclarations.Run (ICSharpCode.NRefactory.CSharp.AstNode compilationUnit) [0x00142] in <37b5ad8a7a94479fbc5b574a8fc6281a>:0
    at ICSharpCode.Decompiler.Ast.Transforms.TransformationPipeline.RunTransformationsUntil (ICSharpCode.NRefactory.CSharp.AstNode node, System.Predicate`1[T] abortCondition, ICSharpCode.Decompiler.DecompilerContext context) [0x0002c] in <37b5ad8a7a94479fbc5b574a8fc6281a>:0
    at ICSharpCode.Decompiler.Ast.AstBuilder.RunTransformations (System.Predicate`1[T] transformAbortCondition) [0x00000] in <37b5ad8a7a94479fbc5b574a8fc6281a>:0
    at ICSharpCode.Decompiler.Ast.AstBuilder.RunTransformations () [0x00000] in <37b5ad8a7a94479fbc5b574a8fc6281a>:0
    at ApiIntersect.MainClass.DumpTypes (System.Collections.Generic.List`1[T] types, System.String baseDir) [0x000a7] in <aac3e0d5bcd4473a96e385115da49b96>:0
    at ApiIntersect.MainClass.Process (System.Collections.Generic.List`1[T] intersections, System.Collections.Generic.List`1[T] exclusions, Mono.Cecil.ReaderParameters readerParameters, System.String outputPath) [0x00319] in <aac3e0d5bcd4473a96e385115da49b96>:0
    at ApiIntersect.MainClass.Main (System.String[] args) [0x0039f] in <aac3e0d5bcd4473a96e385115da49b96>:0

An updated NuGet.Build.Packaging has not been published to nuget.org so only new projects created with Visual Studio for Mac will get the NuGet package containing the fix.

NuGet PowerShell Core Console in Visual Studio for Mac 8.0

The NuGet extensions addin now includes a PowerShell Core based NuGet Package Manager console for Visual Studio for Mac 8.0.

NuGet Package Manager Console window

A NuGet PowerShell console has been available with the NuGet extensions addin since Xamarin Studio 5.0. Previously it used Pash, a cross-platform, open source reimplementation of PowerShell. Pash is no longer being actively developer on after Microsoft released PowerShell Core. The PowerShell support in Pash was incomplete, so whilst the NuGet commands, such as Install-Package, were supported, more complicated commands, such as those provided by Entity Framework Core, were not supported. Moving to PowerShell Core provides full PowerShell support, and with a partial implementation of the Visual Studio EnvDTE API, Entity Framework Core commands are now supported.

The NuGet extensions addin runs a .NET Core console application that hosts PowerShell Core. Communication between the addin running in Visual Studio for Mac and the console application is through the StreamJsonRpc library.

New Features

The following lists the new features compared with the Pash based PowerShell console.

  • PowerShell Core based NuGet Package Manager Console
    • Full PowerShell support
    • Get-Help now supported
  • Support for Entity Framework Core NuGet commands
  • Tab completion
  • Support for stopping the executing command
  • Opening the NuGet package source configuration page from the console

Limitations

  • Visual Studio EnvDTE API implementation is incomplete

The Visual Studio EnvDTE API is partially implemented. Whilst Entity Framework Core is supported other PowerShell scripts included with NuGet packages may not work.

  • Password protected NuGet package sources not supported in the following PowerShell commands:

    • Find-Package
    • Get-Package

Note that the other NuGet PowerShell commands are supported.

The NuGet extensions addin will not send usernames and passwords to the PowerShell Core host console application. .NET Core also does not support decrypting passwords stored in the NuGet.Config file.

The Find-Package and Get-Package commands all run completely within PowerShell hosted in the .NET Core console application.

The other commands work since they run partially within Visual for Mac where actions involving password protected NuGet package sources are supported.

  • Requires .NET Core 2.1 SDK to be installed

Opening the NuGet Package Manager Console window

From the View menu, select Pads, then select NuGet Package Manager Console.

View - Pages - NuGet Package Manager Console menu

 Entity Framework Core Support

The PowerShell commands provided by the Microsoft.EntityFrameworkCore.Tools NuGet package are supported in .NET Core projects.

  • Add-Migration
  • Drop-Database
  • Get-DbContext
  • Remove-Migration
  • Scaffold-DbContext
  • Script-Migration
  • Update-Database

Package Manager Console - Entity Framework Core Add-Migration and Update-Database commands

Note that the Entity Framework Core commands are not currently supported in projects that target the .NET Framework. This is because the PowerShell commands attempt to directly run ef.exe that is included in the NuGet package instead of using the .NET Core ef.dll which is used with projects that target .NET Core.

Tab Completion

Pressing tab in the console window will try to auto-complete the command being typed in.

Tab completion - Install-Package Newtonsoft.Json

Tab completion - Install-Package Newtonsoft.Json -Version

If there is only one match on pressing tab then the text will be inserted.

If there are multiple possible matches then a window will be displayed allowing an item to be selected by pressing Tab, Enter or Return. Typing with this completion list window open will filter the items in the list.

Stopping the PowerShell command being run

When a PowerShell command is being run the Stop button is enabled. The Stop button is the last button on the top right of the NuGet Package Console window.

Package Manager Console stop button

Clicking this button will attempt to stop the PowerShell command being run.

Package Manager Console pipeline stopped

Opening the NuGet Package Console configuration page

At the top of the NuGet Package Console window there is a cog icon after the list of package sources.

Package Manager Console configure sources cog icon

Clicking this cog icon will open the NuGet Package Sources configuration page which is also available from Preferences – NuGet – Sources.

Installation

The NuGet extensions addin is available from the Visual Studio for Mac extensions repository. To install the addin:

  • From the main menu, open the Extensions Manager dialog.
  • Select the Gallery tab.
  • Expand IDE extensions.
  • Select NuGet Package Management Extensions 0.18 or later.
  • Click the Refresh button if the addin is not visible.
  • Click Install… to install the addin.
  • Restart Visual Studio for Mac.

NuGet Support in Visual Studio for Mac 8.0

Changes

  • Fixed build action not available after installing package into a PackageReference project
  • Fixed NuGet extension api install events not raised for PackageReference projects

More information on all the new features and changes in Visual Studio for Mac 8.0 can be found in the release notes.

Bug Fixes

Fixed build action not available on installing package into a PackageReference project

After installing the Xamarin.GooglePlayServices.Basement NuGet package, into a project that used PackageReferences, the GoogleServicesJson build action, defined by this NuGet package, was not available in the list of build actions when you right clicked a file in the Solution window. The build action was available after the solution was closed and re-opened.

Installing a NuGet package into a project that used PackageReferences would not re-evaluate the project’s MSBuild information. This resulted in any custom AvailableItemNames not being available to be used as a build action in the Solution window. The build actions for a project were cached so these are now cleared to ensure the latest items are available after an re-evaluation.

Fixed NuGet extension api install events not raised for PackageReference projects

The NuGet extension API has a PackageReferenceAdded event and a PackageReferenceRemoved. These were being raised if a project had a packages.config file but not if the project used PackageReferences.

NuGet Support in Visual Studio for Mac 7.8

Changes

  • NuGet package diagnostics displayed in Solution window
  • Support restoring multi-target framework projects
  • Display summary of NuGet restore errors in Package Console
  • Fixed wrong version of Microsoft.AspNetCore.App being restored
  • Fixed Paket restore not working with SDK style projects
  • Fixed NuGet restore ignoring build targets

More information on all the new features and changes in Visual Studio for Mac 7.8 can be found in the release notes.

NuGet package diagnostics displayed in Solution window

NuGet package diagnostic warnings are now shown in the Solution window.

NuGet package diagnostic warnings in Solution Window

The diagnostic warnings are shown underneath the NuGet package with a warning icon. Hovering over the warning icon will show a tooltip.

NuGet package diagnostic warning tooltip in Solution Window

Support restoring multi-target framework projects

Projects that have multiple target frameworks now have all frameworks restored.

Multi-target framework project restored in Solution window

Previously only the first target framework would be restored.

Conditional PackageReferences defined in the project file are also now respected when restoring the project. Previously the conditions on the PackageReferences would be ignored.

Conditional PackageReferences restored in Solution window

Visual Studio for Mac now uses the GenerateRestoreGraphFile MSBuild target to determine package dependencies. Previously this information was obtained from the project information held in memory. This fixes several NuGet restore bugs in Visual Studio for Mac.

Display summary of NuGet restore errors in Package Console

Creating an xUnit .NET Core test project named ‘xunit’ fails to restore since there is a package reference cycle between the project and the xunit NuGet package. Whilst this reference cycle is reported it is hidden in the Package Console output and all you would see was a message indicating that the restore had failed. Now the error information is shown at the end of the Package Console as a summary of the failures to make it easier to see the problem.

Now for the xunit project you will see the following at the end of the Package Console output:

Cycle detected.
  xunit -> xunit (>= 2.3.1).
Restore failed.

Bug Fixes

Fixed wrong version of Microsoft.AspNetCore.App being restored

With an ASP.NET Core 2.1 project, that had included a PackageReference for Microsoft.AspNetCore.App version 2.1.5, Visual Studio for Mac would incorrectly restore Microsoft.AspNetCore.App version 2.1.1.

Using the GenerateRestoreGraphFile MSBuild target to determine package reference information when restoring has fixed this problem.

Fixed Paket restore not working with SDK style projects

When Paket is used with an SDK style project it injects PackageReferences via the PaketRestore target from the Paket.Restore.targets file. Visual Studio for Mac was not using MSBuild to get the package reference information so PackageReferences defined by Paket were not being restored or made available.

Fixed NuGet restore ignoring build targets

OrchardCore would fail to restore when opened in Visual Studio for Mac. OrchardCore defines the PackageReference versions in a separate MSBuild .props file and has a custom MSBuild target to define these versions. This custom MSBuild target is now supported since Visual Studio for Mac uses the GenerateRestoreGraphFile MSBuild target to determine package references when restoring.

Task Runner Explorer in Visual Studio for Mac

The Task Runner Explorer addin provides a Task Runner Explorer window, similar to the one in Visual Studio on Windows, which can be used to run tasks with Cake, Gulp, Grunt, NPM and TypeScript.

Task Runner Explorer Window

Features

  • Task Runner Explorer Window
    • View tasks
    • Run tasks
    • View task output
    • Run and cancel long running tasks, such as tcs watch
    • Configure tasks to run when specific IDE events occur
      • Before Build
      • After Build
      • Clean
      • Project Opened
      • Solution Opened
  • Task Runners
    • Cake
    • Gulp
    • Grunt
    • NPM
    • TypeScript

Supports

  • Visual Studio Mac 7.5 or later.

Task Runner Explorer

To open the Task Runner Explorer window, from the View menu select Pads, then select Task Runner Explorer.

View Task Runner Explorer menu

The Task Runner Explorer will look for files supported by a task runner in the solution directory and the project directory. It will also look at all files that have been added to a project or that have been added to a solution folder.

Task Runner Explorer TypeScript and NPM tasks

The top left of the Task Runner Explorer shows a list of projects or the solution that have tasks available. This can be used to filter the tasks shown in the Task Runner Explorer window.

Currently changes made to tasks will not be detected automatically. To refresh the task information you can click the Refresh button available at the top left of the Task Runner Explorer window.

Running a Task

To run a task you can double click it or right click and select Run.

Task Runner Explorer Run menu

Output from the task is shown on the right hand side of the Task Runner Explorer window.

NPM update running

NPM update completed

A long running task, such as tcs watch, will run until the solution is closed, or the Stop button, available on the right hand side of the Task Runner Explorer window, is clicked.

Binding Tasks to IDE Events

Tasks can be configured to run when the following IDE events occur:

  • After Build
  • Before Build
  • Clean
  • Project or Solution Opened

If the task runner file is in a project directory then the build and clean events are associated with the project. If the task runner file is in a solution directory then the build events are associated with the solution.

To configure a task, right click it, select Bindings and then select the event.

Task Runner Explorer Bindings menu

The binding will be displayed in the Bindings tab and will also be shown as checked when the context menu for the task is opened.

Task Runner Explorer Before Build binding added

To remove the binding you can right click the task, select Bindings and select the event again to uncheck it. Alternatively you can right click it in the Bindings tab and select Remove.

The order in which the tasks are run for a particular IDE event can be changed by right clicking the binding in the Bindings tab and selecting Move Up or Move Down.

Task Runner Explorer binding Move Up and Down menus

The binding information is typically saved in a file in the same directory as the corresponding task runner file, however this depends on how the task runner is implemented.

Disabling Automatic Running of Tasks

In preferences there is a Task Runner Explorer section which shows a check box that can be used to enable or disable the automatic running of tasks on opening a project or solution, and when building or cleaning.

Preferences - Automatically run tasks option

Cake Task Runner

The Cake task runner supports running tasks defined in a build.cake file.

Cake Task Runner

This is based on the Cake Task Runner for Visual Studio.

Gulp Task Runner

The Gulp task runner supports running tasks defined in a gulpfile.js file.

Gulp Task Runner

Gulp needs to be installed separately.

Grunt Task Runner

The Grunt task runner supports running tasks defined in a Gruntfile.js file.

Grunt Task Runner

Grunt needs to be installed separately.

NPM Task Runner

The NPM task runner supports running tasks defined in a package.json file.

NPM task runner

The NPM task runner is a port of Mads Kristensen’s NPM Task Runner.

The NPM task runner supports running with the verbose NPM option defined. If a task is selected then a button will be displayed on the left hand side of the Task Runner Explorer window. If this is selected then npm will be passed the -d argument when it is run.

NPM task runner Verbose button

NPM needs to be installed separately.

TypeScript Task Runner

The TypeScript task runner supports running tcs build and tcs watch if a tsconfig.json file is found.

TypeScript task runner

TypeScript tcs watch output

The TypeScript task runner will try to use tsc that is distributed with the Web Tools extension that is included in Visual Studio for Mac. If the Web Tools extension is not installed then the task runner will fall back to running tsc directly.

Installation

There are two addins to be installed:

The Task Runner is the main addin. This will be used by other task runner addins and provides the main task runner API and services.

The Task Runners Bundle addin contains the Cake, Gulp, Grunt, NPM and TypeScript task runners. These are currently included together as a single addin instead of being distributed separately.

Download both of the above .mpack files. Install the Task Runner addin first since the Task Runners Bundle addin depends on it. To install an addin’s .mpack file, open the Extensions Manager by selecting Extensions… from the main menu. Click the Install from file button. Select the .mpack file and then click the Open button. After installing both the addins restart Visual Studio for Mac.

These addins are not currently available from the main Visual Studio for Mac extensions server.

Source Code

NuGet Support in Visual Studio for Mac 7.7

Changes

  • NuGet 4.8 support
  • Support PackageReferences without a Version
  • Fixed NuGet sdk resolver not being found in Mono 5.16
  • Fixed null reference exception in package compatiblity check
  • Fixed Update menu enabled when project has no PackageReferences
  • Fixed updating a NuGet package changing a reference’s ItemGroup
  • Fixed updating a NuGet package changing a fully qualified reference hint path to a relative path

More information on all the new features and changes in Visual Studio for Mac 7.7 can be found in the release notes.

NuGet 4.8 support

NuGet 4.8.0.5385 is now included with Visual Studio for Mac 7.7.2.

Support PackageReferences without a Version

Visual Studio for Mac did not support projects that used PackageReferences without specifying a version.

<ItemGroup>
    <PackageReference Include="Newtonsoft.Json" />
</ItemGroup>

The version may be defined elsewhere in another MSBuild file, such as the Directory.props file, or by the .NET Core SDK, as with the Microsoft.AspNetCore.App PackageReference in ASP.NET Core projects. By default a PackageReference without a version will restore the lowest available version for the NuGet package.

However in Visual Studio for Mac there were several problems with PackageReferences that did not specify a version.

Opening a project with a PackageReference without a Version would result in an ArgumentNullException being logged and the Add Packages dialog could not be opened.

If the PackageReference, in a non-SDK project, had no Version then it was not displayed in the Packages folder and a null reference exception was logged. The Solution window would try to find the package to check if it was installed which is not possible with a missing version and NuGet’s VersionFolderPathResolver would throw a null reference exception.

If a PackageReference had no Version then a null reference exception was logged when checking for updates. A null version is now handled.

Right clicking the package in the Packages folder would log a null reference exception if a non-SDK style project was used and it had a PackageReference without a version. This is now handled and the menu label will show “Version None”.

Bug Fixes

Fixed NuGet sdk resolver not being found in Mono 5.16

More recent versions of MSBuild, such as MSBuild 16.0.40 which is included with Mono 5.16.0.173, allow the sdk resolver to use a manifest.xml file to define the assembly where the resolver can be found:

<SdkResolver>
  <Path>..\..\Microsoft.Build.NuGetSdkResolver.dll</Path>
</SdkResolver>

This manifest file not supported and resulted in the NuGet sdk resolver not being loaded. Any projects that use an MSBuild sdk from a NuGet package no longer worked and would result in an ‘Invalid configuration mapping’ error shown in the Solution window. The sdk resolution in Visual Studio for Mac has now been updated based on the latest MSBuild source code.

Fixed null reference exception in compatiblity check

Changing the target framework of a project that uses a packages.config file will result in a package compatiblity check being run. If the project had both a PackageReference and a packages.config file the package compatiblity check would fail with a null reference exception. Visual Studio for Mac was treating the project as though it was using a packages.config file, when it should have been treated as a PackageReference project. This resulted in a null reference exception being thrown when checking for package compatiblity.

Fixed Update menu enabled when project has no PackageReferences

The Update menu was enabled if the project used PackageReferences but had none in the project. Without any PackageReferences in the project there is no packages to update. The check to determine if the Update menu should be enabled has been changed to make sure the project has PackageReferences in the project file, not just imported PackageReferences. The Update NuGet Packages menu, which is used to update packages for the solution, has also been changed to have the same behaviour.

Fixed updating a NuGet package changing a reference’s ItemGroup

On updating a NuGet package the Reference item will now be modified in place in the project file.

On updating a NuGet package in a project that used a packages.config the old NuGet package is uninstalled and the new one is installed. This removes the old references and adds new references. If the references are in an ItemGroup with a condition then the new reference may be added into a different ItemGroup if there are other ItemGroups with references. To prevent this from happening the changes to made to references are cached and not applied to the project until all the NuGet actions have all been run. This allows a NuGet package update which would remove a reference and then add a new reference to be converted into an update of the original Reference in the project, changing just its HintPath, so its location in the project file is not changed.

This was fixed in Visual Studio for Mac 7.7.3.

Fixed updating a NuGet package changing a fully qualified reference hint path to a relative path

Updating a NuGet package, where the project, which uses a packages.config file, had been modified so the original reference had a fully qualified hint path, would result in a relative path used for the hint path when the reference was updated.

Now if the original hint path was full path then if the hint path for the reference is changed it is saved using a full path. This is different behaviour to how Visual Studio on Windows works, which will always add a relative hint path for the reference.

This was fixed in Visual Studio for Mac 7.7.3.

Proxy Testing a Mac Application with Apache

Here we look at using Apache as a proxy server in order to test that a Mac client application, such as Safari or Visual Studio for Mac, can make web requests through a proxy. Enabling Basic and NTLM proxy authentication with Apache will be covered, as well as using the Apache as a proxy without any authentication.

Apache will run on a separate Windows machine. Using a separate machine allows us to check that the Mac client application is not bypassing the proxy and making direct web requests to any server. This check can be done by configuring the local firewall to block all direct connections out from the Mac machine but allow connections from the machine running Apache.

Apache Proxy – No authentication

Unzip Apache and extract the files to c:\Apache24\ which is the default ServerRoot configured in the conf\httpd.conf file.

Define SRVROOT "/Apache24"

In the httpd.config file configure the port to be used by the Apache server if required. By default port 80 is used. Here we will be using port 8888.

Listen 8888
ServerName localhost:8888

mod_proxy, mod_proxy_connect and mod_proxy_http should be loaded. Edit the http.conf file and ensure these modules are loaded.

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Add a VirtualHost and Proxy section to the httpd.conf file.

<VirtualHost *>
     ProxyRequests On

    <Proxy *>
        Require all granted
    </Proxy>
</VirtualHost>

To run Apache, open a command prompt, change into the Apache24\bin directory, then run httpd.exe

cd c:\Apache24\bin
httpd.exe

On running Apache for the first time you will see a Windows Firewall dialog.

Windows Firewall alert for Apache

Allow Apache to access both the private and public networks.

Configuring the Mac to use Apache as its proxy server can be done by opening System Preferences – Network. For the active network select the Advanced button and open the Proxies tab. Enter the machine IP address where Apache is running and its port into the Web Proxy (HTTP) and Secure Web Proxy (HTTPS) sections, and ensure both of these are checked.

Mac web proxy settings

Finally click OK and Apply to enable the proxy settings.

Now http and https requests should be sent through Apache. A simple way to test this is to open Safari and view a web page. In the C:\Apache24\logs\access.log file you should see entries for the sites accessed.

192.168.1.100 - - [28/Oct/2018:12:18:47 +0000] "GET http://neverssl.com/ HTTP/1.1" 200 1183
192.168.1.100 - - [28/Oct/2018:12:18:47 +0000] "GET http://neverssl.com/favicon.ico HTTP/1.1" 200 124
192.168.1.100 - - [28/Oct/2018:12:18:41 +0000] "CONNECT www.nuget.org:443 HTTP/1.1" 200 -

Apache Proxy – Basic authentication

To enable Basic authentication change the Proxy section in the httpd.conf file as shown below.

<VirtualHost *>
     ProxyRequests On

    <Proxy *>
        AuthType Basic
        AuthName "Authentication required"
        AuthBasicProvider file
        AuthUserFile proxy-password.file
        Require valid-user
    </Proxy>
</VirtualHost>

Here we will be using htpasswd.exe to create a file to store the username and password required to authenticate against the proxy server. htpasswd.exe is in the Apache bin directory. Run the following to generate the proxy-password.file, replacing user with the username to be used with the proxy.

htpasswd.exe -c proxy-password.file user

Enter the password when prompted.

Copy the proxy-password.file to the Apache server’s root directory c:\Apache24

To make it easier to see the basic auth header being sent you may want to enable forensic logging in Apache. To do this add a LoadModule to the httpd.conf file.

LoadModule log_forensic_module modules/mod_log_forensic.so

Define the path to the forensic log file using an IfModule.

<IfModule log_forensic_module> 
    ForensicLog "logs/forensic.log"
</IfModule> 

Run httpd.exe from the Apache24\bin directory.

When connecting through the proxy for the first time the Mac will show a dialog asking for credentials.

Mac proxy authentication required dialog

Clicking the System Preferences button will show open a dialog where you can enter the credentials for the proxy.

Mac proxy authentication required - credentials dialog

Entering the credentials will result in the Mac’s key chain being updated with the credentials associated with the proxy’s address.

Proxy credentials stored in Mac key chain

If you open the Mac’s Network settings you will see the Web Proxy and Secure Web Proxy settings now have a username and password associated with them.

Username and password associated with proxy in network settings

In the Apache access.log you should see the requests being made and a Proxy authentication 407 status code.

192.168.1.100 - - [28/Oct/2018:12:44:47 +0000] "CONNECT www.nuget.org:443 HTTP/1.1" 407 415
192.168.1.100 - - [28/Oct/2018:12:44:53 +0000] "GET http://neverssl.com/ HTTP/1.1" 407 415

In the forensic.log file you should see the basic proxy authorization header being used by the Mac.

GET http%3a//neverssl.com/ HTTP/1.1|Host:neverssl.com|Connection:keep-alive|Proxy-Connection:keep-alive|Upgrade-Insecure-Requests:1|Proxy-Authorization:Basic MTox|Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8|User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15|Accept-Language:en-gb|DNT:1|Accept-Encoding:gzip, deflate
CONNECT www.nuget.org%3a443 HTTP/1.1|Host:www.nuget.org%3a443|User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15|Connection:keep-alive|Proxy-Authorization:Basic MTox|Proxy-Connection:keep-alive

Apache Proxy – NTLM authentication

In order to enable NTLM authentication the NTLM authentication module needs to be downloaded. Download Mod Auth NTLM for Apache 2.4.x x64 – mod_authn_ntml.zip, extract the files and copy the mod_auth_ntlm.so file to the Apache24\modules directory.

Add a LoadModule to the httpd.conf file for the mod_authn_ntlm.so file.

LoadModule auth_ntlm_module modules/mod_authn_ntlm.so

Change the VirtualHost Proxy section as shown below:

<VirtualHost *>
    ProxyRequests On

    <Proxy *>
        AuthType SSPI
        AuthName "Auth required"
        NTLMAuth On
        NTLMAuthoritative On

        <RequireAll>
            <RequireAny>
                Require valid-user
            </RequireAny>

            <RequireNone>
                Require user "ANONYMOUS LOGON"
                Require user "NT AUTHORITY\ANONYMOUS LOGON"
            </RequireNone>
        </RequireAll>
    </Proxy>
</VirtualHost>

The username and password used to authenticate against the proxy needs to match an account on the Windows machine. As with basic authentication, the Mac will prompt for credentials if they do not match what is stored in the key chain for the proxy.

Run httpd.exe and then use Safari to open a web site to check web requests are being sent through the proxy. You should see the Windows account being used to authenticate in Apache’s access.log.

192.168.1.100 - - [28/Oct/2018:13:09:19 +0000] "GET http://neverssl.com/ HTTP/1.1" 407 415
192.168.1.100 - windows\\useraccount [28/Oct/2018:13:09:19 +0000] "GET http://neverssl.com/ HTTP/1.1" 304 -
192.168.1.100 - - [28/Oct/2018:13:09:38 +0000] "CONNECT www.nuget.org:443 HTTP/1.1" 407 415
192.168.1.100 - windows\\useraccount [28/Oct/2018:13:09:12 +0000] "CONNECT www.nuget.org:443 HTTP/1.1" 200 -

The forensic log should show that the NTLM header is being used by the Mac.

CONNECT www.nuget.org%3a443 HTTP/1.1|Host:www.nuget.org%3a443|User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15|Connection:keep-alive|Proxy-Authorization:NTLM T...|Proxy-Connection:keep-alive
GET http%3a//neverssl.com/ HTTP/1.1|Host:neverssl.com|Proxy-Connection:keep-alive|Proxy-Authorization:NTLM T...|If-Modified-Since:Thu, 14 Jun 2018 00%3a16%3a40 GMT|Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8|Accept-Language:en-gb|Accept-Encoding:gzip, deflate|Content-Length:0|User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15|Connection:keep-alive|Upgrade-Insecure-Requests:1|DNT:1

Proxy Testing a Mac Application with Fiddler

Here we look at using Fiddler as a proxy server in order to test a Mac client application, such as Safari or Visual Studio for Mac, can make web requests through the proxy. Enabling Basic proxy authentication with Fiddler will be covered, as well as using the Fiddler as a proxy without any authentication.

Fiddler will run on a separate Windows machine. Using a separate machine allows us to check that the Mac client application is not bypassing the proxy and making direct web requests to any server. This check can be done by configuring the local firewall to block all direct connections out from the Mac machine but allow connections from the machine running Fiddler.

  • Mac High Sierra 10.13
  • Fiddler 5.0 on Windows

Fiddler Proxy – No authentication

To enable the Mac to use Fiddler as its proxy first configure Fiddler to allow remote connections. This can be done by open the Tools menu, selecting Options, opening the Connections tab, and checking Allow remote computers to connect.

Fiddler allow remote connections

Configuring the Mac to use Fiddler as its proxy server can be done by opening System Preferences – Network. For the active network select the Advanced button and open the Proxies tab. Enter the Fiddler’s machine IP address and port into the Web Proxy (HTTP) and Secure Web Proxy (HTTPS) sections, and ensure both of these are checked.

Mac web proxy settings

Finally click OK and Apply to enable the proxy settings.

Now http and https requests should be sent through Fiddler. A simple way to test this is to open Safari and open a web page.

Fiddler https request recorded

Fiddler Proxy – Basic authentication

To enable Basic proxy authentication in Fiddler open the Rules menu and ensure that Require Proxy Authentication is checked.

Fiddler require proxy authentication option

This will result in Fiddler requiring Basic authentication with a username ‘1’ and a password ‘1’.

Unfortunately it seems that the native Mac networking API does not work with Fiddler for https requests but will work for non-secure http requests. Opening a web page in Safari will cause the Mac to prompt for the proxy credentials.

Mac proxy authentication required dialog

Clicking the System Preferences button will show open a dialog where you can enter the credentials for the proxy.

Mac proxy authentication required - credentials dialog

Entering the credentials will result in the Mac’s key chain being updated with the credentials associated with the proxy’s address.

Proxy credentials stored in Mac key chain

If you open the Mac’s Network settings you will see the Web Proxy and Secure Web Proxy settings now have a username and password associated with them.

Username and password associated with proxy in network settings

Safari will display an error page when accessing a web page over https when the Mac is configured to use Fiddler’s basic authentation proxy.

Safari 310 proxy error

It seems that for a https request the Mac sends the request with two keep alive headers:

  • Connection: keep-alive
  • Proxy-Connection: keep-alive

Fiddler responds with a 407 proxy authentication required response and a close header.

  • Connection: close

Fiddler https request denied

Since the keep-alive is not being honoured by Fiddler the web request sent from the Mac fails and an kCFErrorDomainCFNetwork 310 error occurs. This maps to the kCFErrorHTTPSProxyConnectionFailure status code.

Other applications that do not use the native Mac networking API, such as the Google Chrome web browser, will work with Fiddler and will prompt for credentials.

Unfortunately you currently cannot use Fiddler with basic proxy authentication enabled to test a Mac application making https requests. As an alternative you can use another proxy server, such as Apache.

.NET Core Support in Visual Studio for Mac 7.6

Changes

  • NuGet SDK resolver now used to find NuGet SDK packages
  • Fixed Synchronous operation cancelled message on stopping debugging
  • Fixed debugger hanging when debugging unit tests
  • Fixed command line arguments not used with a new project
  • Fixed hang when discovering unit tests
  • Allow loading of SDK style projects without a main PropertyGroup
  • Fixed TargetFramework not being updated in project
  • Fixed .xaml.cs code completion in new Xamarin.Forms .NET Standard project
  • Fixed default build action for new HTML file
  • Fixed SDK version not being parsed from Sdk attribute
  • Fixed null reference on opening .NET Core project with sdk version
  • Fixed editor errors when .NET Standard assembly referenced in Xamarin.iOS project

More information on all the new features and changes in Visual Studio for Mac 7.6 can be found in the release notes.

NuGet SDK resolver now used to find NuGet SDK packages

Visual Studio for Mac now has support for the NuGet SDK resolver. The NuGet SDK resolver will download and install SDKs for SDK style projects if these SDKs are missing.

<Project Sdk="My.Custom.Sdk/2.3.4">
  ...
</Project>

The SDK resolution is done in the background when the project is opened and there is currently no visual indication that this is happening.

The NuGet library assemblies are not available to the remote MSBuild host used by Visual Studio for Mac so the NuGet SDK resolver was previously failing to load. The NuGet SDK resolver supports a MSBUILD_NUGET_PATH environment variable which is now set by Visual Studio for Mac to point to the directory containing the NuGet assemblies that are included with the IDE.

Bug Fixes

Fixed synchronous operation cancelled message on stopping debugging

Stopping the .NET Core debugger would sometimes result in a dialog being displayed indicating that the debugger operation failed.

Debugger operation failed - Synchronous operation cancelled - dialog

Fixed debugger hanging when debugging unit tests

The .NET Core debugger would sometimes hang Visual Studio for Mac when debugging unit tests. The problem was that if the breakpoint was placed on an invalid line then the .NET Core debugger would send back the adjusted breakpoint location. Visual Studio for Mac would then send back an incorrect breakpoint line back to the .NET Core debugger, which again resulted in the debugger sending back a corrected line. This would repeat resulting in the IDE and debugger getting stuck in a loop.

Fixed command line arguments not used with a new project

Creating a new .NET Core console project, editing the project run configuration to use extra command line arguments, or to not use the external console, then building and running the project would result in the project run configuration not being used. No extra arguments would be passed to the console project, and the external console would still be used. This could be fixed by closing and re-opening the solution.

The problem was that when the project is re-evaluated, after it is created, its run configurations are cleared. The solution’s startup run configuration would still be using the original project run configuration that was no longer used. Changes made to the project run configuration then had no affect. Closing and re-opening the solution fixed this since the run configuration defined in the .csproj.user file is re-used when the project is re-evaluated on reloading so both the solution run configuration and the project run configuration refer to the same configuration. To fix this, on re-evaluating the project, if the solution’s run configuration refers to a project run configuration that has been removed then the solution’s startup configuration is refreshed.

Note that there is a similar problem with multiple solution run configurations that can occur which is not addressed by this fix.

Fixed hang when discovering unit tests

Opening a solution containing a .NET Core test project would sometimes result in the IDE hanging when discovering tests. On running kill -QUIT pid the IDE log would show a background thread and the UI thread both awaiting test discovery to complete:

var discoveredTests = await VsTestDiscoveryAdapter.Instance.DiscoverTestsAsync (Project);

VsTestProjectTestSuite/<OnCreateTests>d__12.MoveNext
in MonoDevelop.UnitTesting.VsTest/VsTestProjectTestSuite.cs:95

Allow loading of SDK style projects without a main PropertyGroup

On loading an SDK style project that did not have a main PropertyGroup Visual Studio for Mac would show the error message “Error while trying to load project: Object reference not set to an instance of an object”.

A project may define MSBuild properties in a Directory.Build.props file instead of having this in the main project file. It is then possible for the main project file to have no main property group.

Directory.Build.props:

<Project>
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>
</Project>

MainProject.csproj:

<Project Sdk="Microsoft.NET.Sdk">
</Project>

Visual Studio for Mac now handles the missing main PropertyGroup.

Fixed TargetFramework not being updated in project

Changing a .NET Core project’s target framework to a different version in Project Options, then re-opening Project Options and changing the target framework version back again, would result in the target framework not being updated in the project. The problem was the original target framework the project had on opening was cached and the changing back to the same target framework version was being ignored resulting in the project file not being updated.

Fixed .xaml.cs code completion in new Xamarin.Forms .NET Standard project

Creating a new Xamarin.Forms .NET Standard project, then modifing the .xaml to add new named UI items, would result in no code completion in the .xaml.cs file for these new items until the solution was closed and re-opened. The problem was that the .xaml and .xaml.cs files were being removed from the file information held in memory when the project was re-evaluated. On re-evaluation, after the NuGet restore is first run for the project, the old MSBuild items for the .xaml and .xaml.cs file have the wrong metadata, so they need to be removed, whilst new MSBuild items with the updated metadata need to be added. The removal was done after adding the updated files and, since they had the same filename, the new updated files were being removed. The removal is now done before adding the updated files to avoid the files being removed incorrectly.

Fixed default build action for new HTML file

Adding a new .html file to the wwwroot folder of an ASP.NET Core project would add the file as a None item instead of a Content item. This would result in the .html file not being used when publishing the project. When ‘dotnet publish’ was used the publish directory would not contain the .html file.

ASP.NET Core projects have different build actions for files based on where they are added. A .html file in the root directory would be a None item by default, whilst a .html file in the wwwroot directory would be a Content item by default. To fix this the default build action for a file is determined by the file wildcard information available from the .NET Core SDK.

Fixed SDK version not being parsed from Sdk attribute

The Sdk attribute would have its forward slash / replaced with a backslash \ which meant Visual Studio for Mac was creating an SdkReference with the wrong name, for example:

Microsoft.NET.Sdk.Razor\2.1.0-preview2-final

Instead of having Microsoft.NET.Sdk.Razor as the name with the version being separate.

Fixed null reference on opening .NET Core project with SDK version

Opening a SDK style project that used a Sdk attribute with a version would show an error message “Error while trying to load project: Object reference not set to an instance of an object”. The problem was that an SdkResolver can return null from its Resolve method. These null results were added to a list and then an attempt was made to log the result warnings on a null result.

<Project Sdk="Microsoft.NET.Sdk.Razor/2.1.0-preview2-final">

Fixed editor errors when .NET Standard assembly referenced in Xamarin.iOS project

When a Xamarin.iOS project used an assembly that was compiled for .NET Standard, such as the assembly in the System.Collections.Immutable NuGet package, the netstandard assembly was not made available for code completion. This then resulted in the text editor showing errors even though the project could be compiled succesfully. The errors displayed were similar to:

  The type 'ValueType' is defined in an assembly that is not
  referenced. You must add a reference to assembly 'netstandard,
  Version=2.0.0.0, Culture=neutral, PublicKeytoken=cc7b1dffcd2ddd51'.

Now a check is made to determine if an assembly is referencing netstandard and if so the facade assemblies, which for Xamarin.iOS will include the netstandard.dll, are made available for code completion. Previously only a check was made for the project having an assembly referencing System.Runtime before including the facade assemblies.