Unable to run Ajax Minifier as post-build in Visual Studio - visual-studio-2010

I've set up my post build config as demonstrated at http://www.asp.net/ajaxlibrary/ajaxminquickstart.ashx
I'm getting the following error though:
The "JsSourceFiles" parameter is not supported by the "AjaxMin" task.
Verify the parameter exists on the task, and it is a settable public instance property.
My configuration settings......
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<Target Name="AfterBuild">
<ItemGroup>
<JS Include="**\*.js" Exclude="**\*.min.js" />
</ItemGroup>
<ItemGroup>
<CSS Include="**\*.css" Exclude="**\*.min.css" />
</ItemGroup>
<AjaxMin
JsSourceFiles="#(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js"
CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css" />
</Target>
I had a look at the AjaxMinTask.dll with reflector and noted that the publicly exposed properties do not match the ones in my config. There is an array of ITaskItem called SourceFiles though so I edited my configuration to match.
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<Target Name="AfterBuild">
<ItemGroup>
<JS Include="**\*.js" Exclude="**\*.min.js" />
</ItemGroup>
<ItemGroup>
<CSS Include="**\*.css" Exclude="**\*.min.css" />
</ItemGroup>
<AjaxMin
SourceFiles="#(JS);#(CSS)" SourceExtensionPattern="\.js$;\.css$" TargetExtension=".min.js;.min.css"/>
</Target>
I now get the error:
The "SourceFiles" parameter is not supported by the "AjaxMin" task.
Verify the parameter exists on the task, and it is a settable public instance property.
I'm scratching my head now. Surely it should be easier than this?
I'm running Visual Studio 2010 Ultimate on a Windows 7 64 bit installation.

I wouldn't recommend minifying during AfterBuild. Many build systems make the assumption that the source code is readonly and/or unchanging when the build is being executed, and that would include the .min.js files.
Instead, you can hook into the "CopyWebApplication" target and Visual Studio 2010's website deployment engine (WPP / Web Publishing Pipeline) to accomplish the same thing without .min.js files at all.
Have a look at my response on this question:
Concatenate and minify JavaScript on the fly OR at build time - ASP.NET MVC
To answer your question directly however, the "SourceFiles" property no longer exists. Some older blog posts weren't updated and now have the old information. Try placing "Js" in front of the properties - ie/ JsSourceFiles="#(JS)".
Latest version - http://ajaxmin.codeplex.com/
Documentation - http://ajaxmin.codeplex.com/wikipage?title=AjaxMinTask

Related

Visual Studio not respecting msbuild schema

Using Visual Studio 2017, I am trying to conditionally include a project based on the Configuration. I have added a Choose/When in the csproj of the project in question, instead of directly adding a condition on the project reference due to the problem with MSBUILD/Visual Studio integration (see the remark in this)
However, the build order is not respected when building through visual studio (the solution has been closed and reopened to make sure the Configuration is set).
Has anybody been through this problem?
The choose/when looks like the following:
<Choose>
<When Condition="'$(Configuration)' == 'MyConfiguration'">
<ItemGroup>
<ProjectReference Include="..\Project\MyProject.sqlproj">
<Name>MyProject</Name>
<Project>{ece60b8e-84ad-4c4d-94d3-97a1fb1a5d91}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<ProjectReference Include="..\Project\MyProject2.sqlproj">
<Name>MyProject2</Name>
<Project>{ece70c8e-84ad-4c4d-94d3-97a1fb1a5d93}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
</Otherwise>
</Choose>
However, the build order is not respected when building through visual studio
I have created a sample with your code snippet, but it works fine on my side. Since there is no build log, I would like provide you some troubleshooting to help you find the reason for this issue.
First, I noticed that you reference different projects from the same project folder ..\Project\.., Could you confirm that is correct? Have you move the project file MyProject.sqlproj and MyProject2.sqlproj to the same folder Project? If not, please make sure the path of ProjectReference is correct, following is my code snippet:
<Choose>
<When Condition="'$(Configuration)' == 'Test'">
<ItemGroup>
<ProjectReference Include="..\MyProject\MyProject.sqlproj">
<Name>MyProject</Name>
<Project>{529deb62-9f35-4594-8627-203b19d7cb6d}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<ProjectReference Include="..\MyProject2\MyProject2.sqlproj">
<Name>MyProject2</Name>
<Project>{a6db4708-27d6-40b2-824e-f469372622d9}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
</Otherwise>
</Choose>
Second, make sure the configuration for all projects are the same, for example, my configuration for all projects are Test:
With above condition project reference, the project MyProject.sqlproj only build when configuration is Test, otherwise, the project MyProject2.sqlproj will be built:
If above not help you, please share me the build log and what have you done, I will keep follow. Hope this helps.

Error Viewing Project Properties In .NET Core 2.0

Any time I view a project's properties, in Visual Studio, I get the following error:
An error occurred trying to load the page.
COM object that has been separated from its underlying RCW cannot be used.
This error message displays in project properties when I click on Application, Build, or Build Events. It is happening on .NET Core applications only, and even displays on a brand new project. I have a coworker that is having the exact same problem as well. It also seems to be happening on .NET Core 1.1 apps.
Project File:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
</Project>
Running Visual Studio 2017 (Version 12.3.5) and Resharper 2017.2.1
Have both x86 and x64 runtime and SDK installed
It turns out this is happening because of a Veracode Visual Studio extension that I am using. If anyone else has this problem, I recommend disabling third party VS extensions, until you find one that might be causing it.
Somebody else reported this exact issue, using a different third party extension:

How do I do Web.config Transformations with Visual Studio Website Projects?

It doesn't seem to be possible to change the Build Configuration of Visual Studio 2010 Website Projects (as opposed to Visual Studio Web Applications), and changing the Build Configuration is a key part of enabling Web.config transformations (it's not possible to change the configuration to anything except Debug).
How do I get Web.config transformations to work with Visual Studio 2010 Website projects if it's not possible to change the Build Configuration?
I'd prefer not to use entire an Web Application Project solution out of box.
My solution is to use the XmlTransform task defined in Microsoft.Web.Publishing.Tasks.dll directly (this task is the core of WebConfigTransformation)
This way it is flexible enough and does exactly what you expect it to do.
For example here is the WebSiteTransformator.csproj I'm using for transforming web.config.
Here also is an example of flexibility that is impossible to reach with original WebConfigTransformation: it takes web.Template.config, applies web.$(Configuration).config over it and writes web.config. This allows us to add web.config itself into ignore list in source control. It is still valid csproj to be referenced by website:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<OutputType>Library</OutputType>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<OutputPath>$(TEMP)\TransformWebConfig\bin</OutputPath>
<BaseIntermediateOutputPath>$(TEMP)\TransformWebConfig\obj\</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
<WebFolderName>$(SolutionDir)\MyWebSite\</WebFolderName>
</PropertyGroup>
<ItemGroup>
<Compile Include="Dummy.cs" />
</ItemGroup>
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll"/>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="BeforeBuild">
<TransformXml Source="$(WebFolderName)Web.Template.config"
Transform="$(WebFolderName)Web.$(Configuration).config"
Destination="$(WebFolderName)Web.config" />
</Target>
</Project>
I found a pretty good blog post describing a solution to this here:
http://andrewtwest.com/2010/02/25/using-web-config-transformations-in-web-site-projects/
In short: create an empty project (as long as it is not another website project) in your solution that contains the website. The empty project will give you access to msbuild through its project file, which will allow you to perform transforms on your website web.config.
I used a slightly alternative approach. Still a bit of a hack, but I think a lot more straightforward. This worked for me, but obviously there are a lot of different configurations available so I can't guarantee it'll work for everyone. This revolves around the way that a website is first packaged up in to your AppData folder before being published...
Manually add a Web.Release.config file to the website and add the necessary transforms - obviously there's no 'Add Config Transform' option for websites, hence having to do this manually. Example Web.Release.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="MySetting" value="NewValue" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
</system.web>
</configuration>
Inside the website.publishproj file, ensure the configuration is set to Release:
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
Add the following to the very bottom of website.publishproj (just before </Project>):
<Target Name="AfterBuild">
<MakeDir Directories="$(PackageArchiveRootDir)\..\CSAutoParameterize\original" />
<TransformXml Source="Web.config" Transform="Web.$(ConfigurationName).config" Destination="$(PackageArchiveRootDir)\..\CSAutoParameterize\original\Web.config" StackTrace="false" />
</Target>
Create a publish profile in VS 2017 and then right click on the .pubxml profile in App_Data\PublishProfiles and select Add Config Transform.
See https://social.msdn.microsoft.com/Forums/vstudio/en-US/31f41991-abb2-41de-ad0b-c1379cc7c806/vs-2013-express-for-web-webconfig-transforms?forum=visualstudiogeneral&prof=required
As mentioned in Andriy's comment above, Solution wide build events definitely seems like a cleaner way to do this.
I am adding this as a separate answer, as it gets a little lost in the comment, but IMHO is the best answer. Props to Andriy K and Sayed Ibrahim.
If you would prefer not to need a Web.Template.config, I used this:
<PropertyGroup>
<_tempSourceFile>$([System.IO.Path]::GetTempFileName())</_tempSourceFile>
<_tempTransformFile>$([System.IO.Path]::GetTempFileName())</_tempTransformFile>
</PropertyGroup>
<Copy SourceFiles="$(ProjectDir)Web.config" DestinationFiles="$(_tempSourceFile)"/>
<Copy SourceFiles="$(ProjectDir)Web.$(Configuration).config" DestinationFiles="$(_tempTransformFile)"/>
<TransformXml Source="$(_tempSourceFile)"
Transform="$(_tempTransformFile)"
Destination="$(ProjectDir)Web.config"
StackTrace="false" />
Adapted from an answer here.

Conditionally embed ASP.NET MVC2 Views as resources during build in Visual Studio 2010

I have a ASP.NET MVC2 project in VS2010 that can be deployed in two modes: standalone or plugin. In standalone mode, the views should live outside the compiled assembly as .aspx files (the default setup). In plugin mode, the views are switched (currently by hand) to embedded resources and the entire assembly is dropped into a host project folder.
Currently, this requires the developer to go through each view and switch it from Build Action: "Content" to "Embedded Resource" and vice versa. I would like to create a new solution configuration to automatically grab all .aspx files and build them as resources.
This SO post seems like the solution, but I would prefer not to have to edit the .csproj every single time I add a new view to the project. Is there a way to use a wild cards or some other batch/global conditionally statement to change resources from content to embedded?
Well, sometimes I should experiment before I post.
I modified my .csproj file and just went ahead and tried a wild card:
Views\*\*.aspx
...and it worked great. I posted a snippet of my reconfigured project file below. One thing to note: adding a new view puts it in the "always content" category at the top of the snippet below. You can either live with having .aspx files deployed even when the views are embedded as resources (not an issue for me) or you can move them from the first ItemGroup below to the Otherwise section each time by hand.
<ItemGroup> <-- Always included as content
<Content Include="Global.asax" />
<Content Include="Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</Content>
<Content Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</Content>
</ItemGroup>
<Choose> <--- Only added to assembly in "Plugin Mode"
<When Condition=" '$(Configuration)'=='Plugin' ">
<ItemGroup>
<EmbeddedResource Include="Views\*\*.aspx">
</EmbeddedResource>
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Content Include="Views\Comment\Create.aspx" />
<Content Include="Views\Record\Create.aspx" />
</ItemGroup>
</Otherwise>
</Choose>

Include Files using Wildcard into a folder in Visual Studio

I am using
<ItemGroup>
<EmbeddedResource Include="..\..\resources\hbm\*.hbm.xml" />
</ItemGroup>
to include a bunch of xml files into my C# project. Works fine.
But, I don't want them in the "root level" of my project, I would rather see them in a subfolder in my project.
For example, this file is included into a Mapping folder in Visual Studio:
<ItemGroup>
<EmbeddedResource Include="Mapping\User.hbm.xml" />
</ItemGroup>
That's what I want for my *.hbm.xml files.
I can't figure out how to do it and still keep my wildcard *.hbm.xml part and also keep the actual files in a different directory.
I've looked at MSDN's doc on MSBUILD and items, but no luck.
Perhaps this has changed in MSBuild since the original answer was posted, but it is possible to use both wildcards and links at the same time. For example, I use the following block in a C# project to import data files into a test library.
<ItemGroup>
<None Include="..\SOMENAME.Tests\data\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>data\%(RecursiveDir)%(Filename)%(Extension)</Link>
</None>
</ItemGroup>
The only disadvantage I've seen so far is that MSBuild recreates the folder names on the file system (ie $(ProjectPath)\data\somesubfolder) which is a little annoying but not a huge issue.
As a test, I also tried the OP's request of embedding resources, using the following snippet, and again this seemed to work fine - dotPeek showed the resources were present in the compiled assembly in addition to being present in the Solution Explorer.
<ItemGroup>
<EmbeddedResource Include="..\SOMENAME.Tests\data\**\*.*">
<Link>resources\%(RecursiveDir)%(Filename)%(Extension)</Link>
</EmbeddedResource>
</ItemGroup>
(This was using Visual Studio 2013 and still works as of VS2019)
Update 08Jun2021: The above syntax works is fine for old style csproj files, but if you are using the new SDK format, the syntax is a little different, albeit simpler.
The OP's original question of wildcard embedding can be accomplished with the following
<ItemGroup>
<EmbeddedResource Include="data\**\*.*" />
</ItemGroup>
And to have wildcard file copies for changed or missing files.
<ItemGroup>
<None Update="data\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
I think you can't use links and wildcard at the same time.
You could use this notation to link to include User.hbm.xml file in Mapping folder in Visual Studio :
<ItemGroup>
<EmbeddedResource Include="..\..\resources\hbm\User.hbm.xml">
<Link>Mapping\User.hbm.xml</Link>
</EmbeddedResource>
</ItemGroup>
But you can't do that
<ItemGroup>
<EmbeddedResource Include="..\..\resources\hbm\**\*.hbm.xml">
<Link>%(RecursiveDir)\%(Filename)%(Extension)</Link>
</EmbeddedResource>
</ItemGroup>
I have been able to create the logical name based on some regex (for only one folder depth). The root namespace I want is Agility.BmsData.Create and and example of the final name of the resource could be Agility.BmsData.Create.tables.mytable.sql where the file is in a folder tables\mytable.sql
<ItemGroup>
<EmbeddedResource Include="..\..\AgilityDatabase\Create\**\*.sql" >
<!-- see https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-well-known-item-metadata?view=vs-2022 -->
<!-- https://learn.microsoft.com/en-us/visualstudio/msbuild/property-functions?view=vs-2022 -->
<LogicalName>
Agility.BmsData.Create.$(
[System.Text.RegularExpressions.Regex]::Match("%(Directory)", "(?<=\\)[^\\]+(?=[\\]*$)")
).%(Filename)%(Extension)
</LogicalName>
</EmbeddedResource>
</ItemGroup>
It is also possible to customise the Link attribute of the EmbeddedResource element but the value needs to be suitably encoded for embedding in an xml attribute.
Following on from the above example, I have sql files located in the database project on a relative path to the current project of ..\..\AgilityDatabase\Create\ and I want to mimic the file structure (and resource names) in my other project. I can use the following MsBuild command $([System.Text.RegularExpressions.Regex]::Match("%(Directory)", "(?<=\\AgilityDatabase\\Create\\).+$"))\%(Filename)%(Extension)
So my Item group becomes:
<EmbeddedResource Include="..\..\AgilityDatabase\Create\**\*.sql"
Link="Create\$([System.Text.RegularExpressions.Regex]::Match("%(Directory)", "(?<=\\AgilityDatabase\\Create\\).+$"))\%(Filename)%(Extension)">
</EmbeddedResource>

Resources