So i am trying to build a Multi Project template and when i set it up the folder structure is coming out incorrectly (Not how microsoft does it when creating projects) and it's messing things up like the Packages folder and References folder.
This is current Structure:
Solution Folder
-Solution File
-Folder (Solution Name)
--Packages
--References
--Project1 Folder
--Project2 Folder
I am wanting it to have the same structure that .NET does automatically:
Solution Folder
-Solution File
-References Folder
-Packages Folder
-Project1 Folder
-Project2 Folder
Here is my vstemplate:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="ProjectGroup">
<TemplateData>
<Name>ASP Solution Template</Name>
<Description>This is the Solution Template for ASP Applications</Description>
<Icon>__TemplateIcon.ico</Icon>
<ProjectType>CSharp</ProjectType>
</TemplateData>
<TemplateContent BuildOnLoad="true">
<ProjectCollection>
<SolutionFolder Name="References">
</SolutionFolder>
<SolutionFolder Name="packages">
</SolutionFolder>
<ProjectTemplateLink ProjectName="$safeprojectname$">
ASPTemplate\MyTemplate.vstemplate
</ProjectTemplateLink>
<ProjectTemplateLink ProjectName="$safeprojectname$.ClassLibrary">
ClassLibrary\MyTemplate.vstemplate
</ProjectTemplateLink>
</ProjectCollection>
</TemplateContent>
</VSTemplate>
Take a look at dotnet new custom templates. I had the same problem and this was a nice easy solution.
https://learn.microsoft.com/en-us/dotnet/core/tutorials/create-custom-template
Create your solution and put your files and/or projects where you like, I'll call the solution MySolution
Add folders, projects, whatever you like
Create a folder at the top level by the solution called .template.config
Create a json file in that .template.config called template.json
The template.json attributes can be found here https://learn.microsoft.com/en-us/dotnet/core/tools/custom-templates
Example template.json:
{
"$schema": "http://json.schemastore.org/template",
"author": "Your goodself",
"classifications": [ "C#", "Awesome", "etc" ],
"identity": "MySolution",
"name": "Empty MySolution",
"shortName": "mysolution",
"sourceName": "MySolution",
"tags": {
"language": "C#"
},
}
sourceName is important, that is used to name your project new project and rename everything.
To see what templates you already have do:
dotnet new -l
To add your new template the above do:
dotnet new -i <fully qualified solution folder>
eg. dotnet new -i c:\dev\MySolution
You should then see your name in a:
dotnet new -l
That's it, ready to use!
Go to a fresh folder and type:
dotnet new mysolution -n MySolutionFromTemplate
You will then see all the folders, files and everything named as expected
Finally if you want to delete the template do:
dotnet new -u c:\dev\MySolution
NOTE: You will probably need this in your nuget repo. There are instructions how to do this here https://learn.microsoft.com/en-us/dotnet/core/tutorials/create-custom-template
I don't think it's possible to add solution folders in the parent solution folder with vstemplates.
However, you could try adding a wizard to your template that enables you to run custom code when a user creates a project from a template.
Follow the instructions here and here, but basically you do something like this:
Implement the IWizard interface in a ClassLibrary-project and use EnvDTE80 to create the folders:
public class MyWizard : IWizard
{
public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
// Pseudo-code
var dte = (DTE2)automationObject;
var solution = (Solution2)dte.Solution;
solution.AddSolutionFolder("References");
}
// Default implementations of IWizard here (return true's and do nothing's)
}
Modify your vstemplate to use the wizard:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="ProjectGroup">
<TemplateData />
<TemplateContent BuildOnLoad="true" /> <!-- Remove the SolutionFolder elements -->
<WizardExtension>
<Assembly>CustomWizard, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=fa3902f409bb6a3b</Assembly>
<FullClassName>CustomWizard.MyWizard</FullClassName>
</WizardExtension>
</VSTemplate>
Then the code should be running when you create a project with your new template.
Hope this helps you somehow.
Related
I would like to be able to create a custom override to add a VcpkgConfiguration Property based on our current configuration.
We have a C++ project that uses Premake and vcpkg. We have found vcpkg to conflict with other projects that include their own versions of similar libraries, so we cannot use the global integration that it provides. Instead we have added it as a sub-module to our project and linked it through premake with a custom override:
p.override(p.vstudio.vc2010, "importExtensionTargets", function(base, prj)
p.push('<ImportGroup Label="ExtensionTargets">')
p.callArray(p.vstudio.vc2010.elements.importExtensionTargets, prj)
p.pop('</ImportGroup>')
p.push('<ImportGroup Label="ExtensionTargets">')
p.w('<Import Project="$(SolutionDir)External/vcpkg/scripts/buildsystems/msbuild/vcpkg.targets"/>')
p.pop('</ImportGroup>')
end)
Unfortunately we do not use the regular "Debug" or "Release" configurations in our project, so vcpkg by default does not link correctly. To get past that problem, we modified the vcpkg.targets file to recognize our configuration in a local branch. This is not ideal, as it forces us to rebase our branch off vcpkg in order to update it, and could potentially conflict if that file is ever modified in their repo.
The targets file allows you to set the VcpkgConfiguration property before including the target, which is what we would like to do.
Basically what we would like is to be able to call a command through the filters like this:
filter {"configurations:<SomeConfiguration>"}
VcpkgConfig "Debug"
Which would add this inside the propertygroup
<VcpkgConfiguration>Debug</VcpkgConfiguration>
How can we accomplish this?
The problem seems to be that importExtensionTargets is per project but you want this per configuration.
You can try to register your key word
api.register {
name= "VcpkgConfig",
scope = "config",
kind = "string",
}
then in your custom function
-- loop over all configurations
for _, cfgName in ipairs(prj.configurations) do
-- find config
local cfg = project.findClosestMatch(prj, cfgName)
if cfg.VcpkgConfig then
p.push('<ImportGroup Label="ExtensionTargets">')
p.push('<VcpkgConfiguration>'.. cfg.VcpkgConfig .. '</VcpkgConfiguration>')
p.w('<Import Project="$(SolutionDir)External/vcpkg/scripts/buildsystems/msbuild/vcpkg.targets"/>')
p.pop('</ImportGroup>')
end
Not tested.
Would this work ?
I have several questions on my ASP.NET MVC CORE 2.2 project.
The main goal is very simple, i want to update my stylesheet and then deploy this result. I have a Site.less, site.css, site.min.css, site.min.css.gz that i want to update with a css class style, a bundleconfig.json with my input css, javascript files to be bundled and a compilerconfig.json that has Site.less as an input and site.css as output. I also have BuildBundlerMinifier installed on my project (NuGet).
Questions:
1- What file should i update when adding some new style: Site.less, site.css or both?
2- What are the steps to minify and bundle before i publish my app?
bundleconfig.json:
[
{
"outputFileName": "wwwroot/css/bundle.min.css",
// An array of relative input file paths. Globbing patterns supported
"inputFiles": [
(...)
"wwwroot/css/Site.min.css"
]
},
(...)
// Optionally specify minification options
"minify": {
"enabled": true,
"renameLocals": true
},
// Optionally generate .map file
"sourceMap": false
}
]
compilerconfig.json
[
{
"inputFile": "wwwroot/css/Site.less",
"outputFile": "wwwroot/css/site.css"
}
]
When i rebuild my project in my Output window (Visual Studio 2017) i have the following messages.
Cleaning output from bundleconfig.json,
Done cleaning output file from bundleconfig.json, Begin processing bundleconfig.json, Minified wwwroot/css/bundle.min.css, Done processing bundleconfig.json
Thank you.
My first question is answered.
I have installed an extension in Visual Studio 2017 (Tools -> Extensions and Updates) named Web Compiler. When i make an update in my less file, the css file and min.css are auto generated (min.css.gz is not and don't know why). The files that the code is auto generated are water marked with Generated keyword.
To produce the auto generated files you only need to rebuild the project.
This works with other files but in my case i am only using this ones.
EDIT
My second question is also answered.
I have installed another extension: Bundler & Minifier
To produce bundle you need to have those config json files i have posted in my first post and then open Task Runner Explorer and double click on wwwroot/css/bundle.min.css (inside StyleSheets menu) and the bundle file will be auto generated.
How do I specify the default file to use for a bower component so that it will be injected properly by grunt-bower-install?
I am working with datejs and they have different files depending on your localization. The file I'm wanting to include is not in the root of bower_components/datejs directory so I get the error:
datejs was not injected in your file.
Please go take a look in
"app/bower_components/datejs" for the file you need, then manually
include it in your file.
I'm trying my hardest to avoid hardcoding datejs into my index file and don't really want to move "date-en-US.js" file into the root of the datejs directory either.
This is the structure of the datejs bower component.
bower_components
└── datejs
└── build
└── ...
└── date-en-US.js
└── ...
└── src
└── test
And just in case this helps, this is the .bower.json file that is located in the datejs bower component path:
{
"name": "datejs",
"homepage": "https://github.com/datejs/Datejs",
"_release": "7bdddb55d6",
"_resolution": {
"type": "branch",
"branch": "master",
"commit": "7bdddb55d69719e42c358c3a2b7df706ff3090f8"
},
"_source": "git://github.com/datejs/Datejs.git",
"_target": "*",
"_originalSource": "datejs",
"_direct": true
}
A little late to the party but you can override the main property of a repo to define whatever file you want to inject into your app. To do this you need to use the overrides property in YOUR bower.json.
Try this:
{
"name": "name",
"version": "x.x.x",
"dependencies": {
"datejs": "x.x.x"
},
"overrides": {
"datejs": {
"main": "build/date-en-US.js"
}
}
}
I too was frustrated by this a few times. What I found in my cases was that "grunt bower-install" requires a "main" entry in the .bower.json. It's a string or array of strings that point to the relevant JS and/or CSS files that should be installed.
In your case I do not see the "main" and would suggest you create one that contains the desired datejs files. I would suggest the source files if you intend to use grunt for minification/etc. You can look at other successful components to see examples of the "main" entry.
I suspect that some components do not supply the entry because they have no single usage pattern (i.e. you can mix and match the files you require), but this is just speculation on my part.
Try adding this in your grunt file:
'bower-install': {
fileTypes: {
fileExtension: {
detect: {
typeOfBowerFile: /-en-US.js/
}
}
}
}
I didn't try this out, and my regex might be off. But accoriding to the grunt-bower-install readme, it states See [wiredep's](https://github.com/stephenplusplus/wiredep) readme for more options of customization and there it shows using the above configuration.
Essentially - grunt-bower-install doesn't know what to look for. This option appears to tell it that info.
I have a few gradle war tasks in my build file, and I would like to change the webAppDirName per war task. I tried this:
task myWarTask(type: War) {
ext.webAppDirName = 'src/anotherfolder/webapp' // also tried just webAppDirName
version ""
destinationDir = file("$buildDir/libs")
baseName = 'myWarName'
classpath = configurations.myWarConfiguration
}
But this is still pulling in the contents of src/main/webapp instead of src/anotherfolder/webapp
Can I configure the webAppDirName on a per war file basis like this?
There is just one webAppDirName property per project, and the War plugin automatically adds a corresponding from to each War task. So the main problem is how to undo that from. I think the following should work:
apply plugin: "war"
webAppDirName = "non/existing/dir"
task myWarTask(type: War) {
from "src/anotherfolder/webapp"
...
}
An alternative is to only use the War task type, but not the War plugin. You'll have to configure a few more task properties then, and will lose a few features, mostly related to provided configurations and publishing of the War. Of course you can make up for this with explicit configuration (if necessary). If you are interested in the details, have a look at the source code for the War plugin.
PS: webAppDirName is not an extra property (ext.), but a convention property added by the War plugin. Extra properties are only meant for ad-hoc use in build scripts. You'd use ext. when writing an extra property, but omit it when reading the property.
task myWarTask(type: War) {
from 'src/anotherfolder/webapp'
version ""
destinationDir = file("$buildDir/libs")
baseName = 'myWarName'
classpath = configurations.myWarConfiguration
}
Is it possible to put resource files (.resx) within subfolders inside App_GlobalResources?
For example:
/App_GlobalResources/someresources/myfile.resx
/App_GlobalResources/someresources/myfile.fr-fr.resx
/App_GlobalResources/othereresources/otherfile.resx
/App_GlobalResources/othereresources/otherfile.fr-fr.resx
Or, are all the .resx files placed directly inside App_GlobalResources?
If it is possible to use subfolders, how do you programmatically access resources within subfolders?
Technically, yes it is possible but there are some pitfalls. First, let me show you an example. Suppose my App_GlobalResources folder looks like so:
/App_GlobalResources
/Test
TestSubresource.resx
TestResource.resx
Each resource file has a single entry called "TestString". I added each resource file using the Visual Studio menu so it created a class for me. By default, all classes added to the App_GlobalResources folder will have the same namespace of Resource. So, if I want to use the class generator and I want Test in the namespace, I need to go into the TestSubresource.Designer.cs file and manually change the namespace. Once I do that, I can do the following:
var rootResource = Resources.TestResource.TestString;
var subResource = Resources.Test.TestSubResource.TestString;
I can also reference them using GetGlobalResourceObject:
var rootResource = GetGlobalResourceObject( "TestResource", "TestString" );
var subResource1 = GetGlobalResourceObject( "TestSubresource", "TestString" );
Notice that I still use the "TestSubresource" as the means to reference the resources in that file even though it is in a subfolder. Now, one of the catches, is that all the files must be unique across all folders in App_GlobalResources or your project will throw a runtime error. If I add a resource named "TestResource.resx" to /Test, it will throw the following runtime error:
The resource file '/App_GlobalResources/TestResource.resx' cannot be
used, as it conflicts with another file with the same name.).
This is true even if I change the namespace on the new resource.
So, in conclusion, yes it is possible, but you increase the odds of getting a runtime error because of two identically named resource files in different parts of the App_GlobalResources folder structure which is allowed by the file system but not by .NET.
It's possible. At least, I managed to do it.
Within a web site I added the App_GlobalResources folder. Inside it I created another folder "MyFolder" and placed MyResource.resx file inside. Resx file contained one pair MyKey1 - MyValue1.
Using the GetResource method of the following class I successfully extracted "MyValue1" for name="MyKey1"
static class Class1 {
static Assembly FindGlobalResAssembly() {
foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
if(asm.FullName.StartsWith("App_GlobalResources."))
return asm;
}
return null;
}
public static object GetResource(string name) {
Assembly asm = FindGlobalResAssembly();
if(asm == null)
return null;
return new ResourceManager("Resources.MyResource", asm).GetObject(name);
}
}
This approach works in Medium trust also.
It seems that folders make no difference when accessing resources from code.