Setting the version number for .NET Core projects - asp.net-core

What are the options for setting a project version with .NET Core / ASP.NET Core projects?
Found so far:
Set the version property in project.json. Source: DNX Overview, Working with DNX projects. This seems to set the AssemblyVersion, AssemblyFileVersion and AssemblyInformationalVersion unless overridden by an attribute (see next point).
Setting the AssemblyVersion, AssemblyFileVersion, AssemblyInformationalVersion attributes also seems to work and override the version property specified in project.json.
For example, including 'version':'4.1.1-*' in project.json and setting [assembly:AssemblyFileVersion("4.3.5.0")] in a .cs file will result in AssemblyVersion=4.1.1.0, AssemblyInformationalVersion=4.1.1.0 and AssemblyFileVersion=4.3.5.0
Is setting the version number via attributes, e.g. AssemblyFileVersion, still supported?
Have I missed something - are there other ways?
Context
The scenario I'm looking at is sharing a single version number between multiple related projects. Some of the projects are using .NET Core (project.json), others are using the full .NET Framework (.csproj). All are logically part of a single system and versioned together.
The strategy we used up until now is having a SharedAssemblyInfo.cs file at the root of our solution with the AssemblyVersion and AssemblyFileVersion attributes. The projects include a link to the file.
I'm looking for ways to achieve the same result with .NET Core projects, i.e. have a single file to modify.

You can create a Directory.Build.props file in the root/parent folder of your projects and set the version information there.
However, now you can add a new property to every project in one step by defining it in a single file called Directory.Build.props in the root folder that contains your source. When MSBuild runs, Microsoft.Common.props searches your directory structure for the Directory.Build.props file (and Microsoft.Common.targets looks for Directory.Build.targets). If it finds one, it imports the property. Directory.Build.props is a user-defined file that provides customizations to projects under a directory.
For example:
<Project>
<PropertyGroup>
<Version>0.0.0.0</Version>
<FileVersion>0.0.0.0</FileVersion>
<InformationalVersion>0.0.0.0.myversion</InformationalVersion>
</PropertyGroup>
</Project>

Another option for setting version info when calling build or publish is to use the undocumented /p option.
dotnet command internally passes these flags to MSBuild.
Example:
dotnet publish ./MyProject.csproj /p:Version="1.2.3" /p:InformationalVersion="1.2.3-qa"
See here for more information: https://github.com/dotnet/docs/issues/7568

Not sure if this helps, but you can set version suffixes at publish time. Our versions are usually datetime driven, so that developers don't have to remember to update them.
If your json has something like "1.0-*"
"dotnet publish --version-suffix 2016.01.02" will make it "1.0-2016.01.02".
It's important to stick to "semvar" standards, or else you'll get errors. Dotnet publish will tell you.

Why not just change the value in the project.json file. Using CakeBuild you could do something like this (optimizations probably possible)
Task("Bump").Does(() => {
var files = GetFiles(config.SrcDir + "**/project.json");
foreach(var file in files)
{
Information("Processing: {0}", file);
var path = file.ToString();
var trg = new StringBuilder();
var regExVersion = new System.Text.RegularExpressions.Regex("\"version\":(\\s)?\"0.0.0-\\*\",");
using (var src = System.IO.File.OpenRead(path))
{
using (var reader = new StreamReader(src))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if(line == null)
continue;
line = regExVersion.Replace(line, string.Format("\"version\": \"{0}\",", config.SemVer));
trg.AppendLine(line);
}
}
}
System.IO.File.WriteAllText(path, trg.ToString());
}
});
Then if you have e.g. a UnitTest project that takes a dependency on the project, use "*" for dependency resolution.
Also, do the bump before doing dotnet restore. My order is as follows:
Task("Default")
.IsDependentOn("InitOutDir")
.IsDependentOn("Bump")
.IsDependentOn("Restore")
.IsDependentOn("Build")
.IsDependentOn("UnitTest");
Task("CI")
.IsDependentOn("Default")
.IsDependentOn("Pack");
Link to full build script: https://github.com/danielwertheim/Ensure.That/blob/3a278f05d940d9994f0fde9266c6f2c41900a884/build.cake
The actual values, e.g. the version is coming from importing a separate build.config file, in the build script:
#load "./buildconfig.cake"
var config = BuildConfig.Create(Context, BuildSystem);
The config file looks like this (taken from https://github.com/danielwertheim/Ensure.That/blob/3a278f05d940d9994f0fde9266c6f2c41900a884/buildconfig.cake):
public class BuildConfig
{
private const string Version = "5.0.0";
public readonly string SrcDir = "./src/";
public readonly string OutDir = "./build/";
public string Target { get; private set; }
public string Branch { get; private set; }
public string SemVer { get; private set; }
public string BuildProfile { get; private set; }
public bool IsTeamCityBuild { get; private set; }
public static BuildConfig Create(
ICakeContext context,
BuildSystem buildSystem)
{
if (context == null)
throw new ArgumentNullException("context");
var target = context.Argument("target", "Default");
var branch = context.Argument("branch", string.Empty);
var branchIsRelease = branch.ToLower() == "release";
var buildRevision = context.Argument("buildrevision", "0");
return new BuildConfig
{
Target = target,
Branch = branch,
SemVer = Version + (branchIsRelease ? string.Empty : "-b" + buildRevision),
BuildProfile = context.Argument("configuration", "Release"),
IsTeamCityBuild = buildSystem.TeamCity.IsRunningOnTeamCity
};
}
}

If you still want to have the Solution Level SharedVersionInfo.cs you can do it by adding these lines to your project.json file:
"buildOptions": {
"compile": {
"includeFiles": [
"../../SharedVersionInfo.cs"
]
}
}
Your relative path may vary, of course.

use external version.txt file with version, and prebuild step to publish this version in projects

Related

Project Doesn't Build After Installed Sitecore TDS

After setting up Sitecore TDS, my project will not build. I'm new to Visual Studio and also new to working with Sitecore. It seems that it cannot find a particular setting, but a Google search is not coming up with anything:
Severity Code Description Project Path File Line Suppression State
Error The "AnalyzeProject" task failed unexpectedly.
System.MissingFieldException: Field not found: 'HedgehogDevelopment.SitecoreProject.Tasks.SitecoreDeployInfo.ParsedItem'.
at HedgehogDevelopment.SitecoreProject.Analysis.TemplateStructure.Validate(Dictionary`2 projectItems, XDocument scprojDocument)
at HedgehogDevelopment.SitecoreProject.Tasks.ProjectAnalysis.AnalysisEngine.<>c__DisplayClass4_1.<GetReport>b__0()
at HedgehogDevelopment.SitecoreProject.Tasks.ProjectAnalysis.ExecutionTimer.Time(Action action)
at HedgehogDevelopment.SitecoreProject.Tasks.ProjectAnalysis.AnalysisEngine.GetReport(Dictionary`2 projectItems, XDocument scprojDocument)
at HedgehogDevelopment.SitecoreProject.Tasks.AnalyzeProject.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() B2B.Core C:\Program Files (x86)\MSBuild\HedgehogDevelopment\SitecoreProject\v9.0 C:\Program Files (x86)\MSBuild\HedgehogDevelopment\SitecoreProject\v9.0\HedgehogDevelopment.SitecoreProject.targets 144
Apparently my project does still build and will run, but that error pops up each time regardless.
This can happen when you have TDS validations enabled and are missing some DLLs.
In this directory:
C:\Program Files (x86)\MSBuild\HedgehogDevelopment\SitecoreProject\v9.0\
Add the following DLLs:
Microsoft.Web.Infrastructure.dll
TDSWebDeploy.Services.Contracts.dll
If you have TDS installed, you may be able to source those DLLs from somewhere in your C:\Program Files (x86)\MSBuild\HedgehogDevelopment directory. If not, someone else on your team may have them.
You can also try disabling and enabling validations by right clicking your TDS project --> Properties --> Validations tab.
I have seen this issue on numerous occasions across numerous dev boxes. We have opened support tickets regarding it, but no conclusions were drawn.
The specific error is that the HedgehogDevelopment.SitecoreProject.Tasks.SitecoreDeployInfo.ParsedItem field is missing on an object. The fact that ParsedItem is mentioned implies that some form of parsing may be occurring, and that it didn't work as expected. This is conjecture, but if parsing is occurring, it would be worth ensuring that your serialized item files are accessible to the user/group that is performing this parsing.
Here is the code that is failing:
public override IEnumerable<Problem> Validate(Dictionary<Guid, SitecoreDeployInfo> projectItems, XDocument scprojDocument)
{
List<Problem> problems = new List<Problem>();
foreach (KeyValuePair<Guid, SitecoreDeployInfo> projectItem in projectItems)
{
// ** Presumably, it's failing here **
string item = projectItem.Value.ParsedItem.Properties["template"];
if (string.IsNullOrEmpty(item))
{
continue;
}
Guid guid = new Guid(item);
if (guid == TemplateStructure.TEMPLATE)
{
problems.AddRange(this.ValidateTemplate(projectItems, projectItem.Value.Item));
}
else if (guid != TemplateStructure.TEMPLATE_SECTION)
{
if (guid != TemplateStructure.TEMPLATE_FIELD)
{
continue;
}
problems.AddRange(this.ValidateField(projectItems, projectItem.Value.Item));
}
else
{
problems.AddRange(this.ValidateSection(projectItems, projectItem.Value.Item));
}
}
problems.RemoveAll((Problem r) => r == null);
return problems;
}
Here is the definition for SitecoreDeployInfo:
using HedgehogDevelopment.SitecoreCommon.Data.Items;
using System;
namespace HedgehogDevelopment.SitecoreProject.Tasks
{
public class SitecoreDeployInfo
{
public IItem ParsedItem;
public SitecoreItem Item;
public SitecoreDeployInfo()
{
}
}
}

Path to static file under wwwroot in Razor Pages

What are the differences between these 3 methods used to get the path to the image stored under wwwroot? Seems like all work the same in my case, but would like to understand if there are any other case specific differences between them or benefits of using one over another.
I use this path to subsequently load the image into Bitmap MyBitmap variable for further processing. Would like it to be environment resilient whatever it is finally deployed to Windows, Linux or container; locally or in the cloud.
Using Razor Pages with ASP.NET Core 3.0.
public class QRCodeModel : PageModel
{
private readonly IHostEnvironment hostingEnvironment;
public QRCodeModel(IHostEnvironment environment)
{
this.hostingEnvironment = environment;
}
public void OnGet()
{
string TempPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "img", "Image1.png");
string TempPath1 = Path.Combine(Environment.CurrentDirectory, "wwwroot", "img", "Image1.png");
string TempPath2 = Path.Combine(hostingEnvironment.ContentRootPath, "wwwroot", "img", "Image1.png");
}
}
There is another option:
string TempPath4 = Path.Combine(hostingEnvironment.WebRootPath, "img", "Image1.png");
WebRootPath returns the path to the wwwroot folder.
This is recommended over using the first two options as they may not return the location that you want: Best way to get application folder path

CSS Intellisense not working for MVC 4 project in Visual Studio 2012 Ultimate

Have created a brand new Visual Studio 2012 Ultimate SP2 MVC4 project but unable to get CSS class selector intellisense to work?
When I type <p class="m" .... I should get the class "myClass" appearing in intellisense dropdown but nothing happens.
The file I have listed below is: \Views\Shared\_Layout.cshtml
Any Ideas ?
Edit: Have re-installed VS2012 on brand new windows 7 system (running on Mac OSX parallels 8) and still acting in the same way. Also seems the same for MVC 3 projects.
Extensions installed:
Try adding Web Essentials 2012 extension for Visual Studio 2012: http://visualstudiogallery.msdn.microsoft.com/07d54d12-7133-4e15-becb-6f451ea3bea6?SRC=VSIDE
And/Or
Try adding Microsoft Web Developer Tools extension.
I have both of these and using your same example the intellisense works like a charm.
I tried all the above mentioned remedies and suggestions. None of these worked in my environment. According to Microsoft (Under Microsoft connect's bug id 781048), they have not implemented CSS class intellisense for MVC/Razor files but are working on including this in a future release.
I have a 10 minute webcast example of extending VS2012 intellisense that adds one solution that will add intellisense to your VS2012 environment: a Visual Studio Intellisense Extension
The webcast uses MEF to extend Visual Studio to add an intellisense completion source that scans the currently loaded project for CSS class names to add as an intellisense completion set. Here is the css completion source class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.Utilities;
using EnvDTE;
using System.Text.RegularExpressions;
using System.Configuration;
using System.Collections.Specialized;
namespace CssClassIntellisense
{
internal class cssClassList
{
public string cssFileName { get; set; } //Intellisense Statement Completion Tab Name
public HashSet<string> cssClasses { get; set; }
}
internal class CssClassCompletionSource : ICompletionSource
{
private CssClassCompletionSourceProvider m_sourceProvider;
private ITextBuffer m_textBuffer;
private List<Completion> m_compList;
private Project m_proj;
private string m_pattern = #"(?<=\.)[A-Za-z0-9_-]+(?=\ {|{|,|\ )";
private bool m_isDisposed;
//constructor
public CssClassCompletionSource(CssClassCompletionSourceProvider sourceProvider, ITextBuffer textBuffer, Project proj)
{
m_sourceProvider = sourceProvider;
m_textBuffer = textBuffer;
m_proj = proj;
}
public void AugmentCompletionSession(ICompletionSession session, IList<CompletionSet> completionSets)
{
ITextSnapshot snapshot = session.TextView.TextSnapshot;
SnapshotPoint currentPoint = (SnapshotPoint)session.GetTriggerPoint(snapshot);
if (TargetAttribute.Inside(currentPoint))
{
var hash = new List<cssClassList>();
//read any .css project file to get a distinct list of class names
if (m_proj != null)
foreach (ProjectItem _item in m_proj.ProjectItems)
{
getCssFiles(_item, hash);
}
//Scan Current Editor's text buffer for any inline css class names
cssClassList cssclasslist = ScanTextForCssClassName(
"Inline", snapshot.GetText());
//If file had any css class names add to hash of files with css class names
if (cssclasslist != null)
hash.Add(cssclasslist);
var _tokenSpanAtPosition = FindTokenSpanAtPosition(session.GetTriggerPoint(m_textBuffer), session);
foreach (cssClassList _cssClassList in hash)
{
m_compList = new List<Completion>();
foreach (string str in _cssClassList.cssClasses.OrderBy(x => x)) //alphabetic sort
m_compList.Add(new Completion(str, str, str, null, null));
completionSets.Add(new CompletionSet(
_cssClassList.cssFileName, //the non-localized title of the tab
_cssClassList.cssFileName, //the display title of the tab
_tokenSpanAtPosition,
m_compList,
null));
}
}
}
private ITrackingSpan FindTokenSpanAtPosition(ITrackingPoint point, ICompletionSession session)
{
SnapshotPoint currentPoint = (session.TextView.Caret.Position.BufferPosition) - 1;
ITextStructureNavigator navigator = m_sourceProvider.NavigatorService.GetTextStructureNavigator(m_textBuffer);
TextExtent extent = navigator.GetExtentOfWord(currentPoint);
return currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive);
}
private void getCssFiles(ProjectItem proj, List<cssClassList> hash)
{
foreach (ProjectItem _item in proj.ProjectItems)
{
if (_item.Name.EndsWith(".css") &&
!_item.Name.EndsWith(".min.css"))
{
//Scan File's text contents for css class names
cssClassList cssclasslist = ScanTextForCssClassName(
_item.Name.Substring(0, _item.Name.IndexOf(".")),
System.IO.File.ReadAllText(_item.get_FileNames(0))
);
//If file had any css class names add to hash of files with css class names
if (cssclasslist != null)
hash.Add(cssclasslist);
}
//recursively scan any subdirectory project files
if (_item.ProjectItems.Count > 0)
getCssFiles(_item, hash);
}
}
private cssClassList ScanTextForCssClassName(string FileName, string TextToScan)
{
Regex rEx = new Regex(m_pattern);
MatchCollection matches = rEx.Matches(TextToScan);
cssClassList cssclasslist = null;
if (matches.Count > 0)
{
//create css class file object to hold the list css class name that exists in this file
cssclasslist = new cssClassList();
cssclasslist.cssFileName = FileName;
cssclasslist.cssClasses = new HashSet<string>();
}
foreach (Match match in matches)
{
//creat a unique list of css class names
if (!cssclasslist.cssClasses.Contains(match.Value))
cssclasslist.cssClasses.Add(match.Value);
}
return cssclasslist;
}
public void Dispose()
{
if (!m_isDisposed)
{
GC.SuppressFinalize(this);
m_isDisposed = true;
}
}
}
}
As an FYI, you can also address this issue using Resharper. But that is a 3rd party product that needs to be purchased for Visual Studio
Is it just CSS intellisense that's failed or has it completely stopped throughout Visual Studio?
I had a similar issue that effected the whole of my Visual Studio 2012. It was a while back but I remember deleting a folder from my appdata. Take a look at this link, hopefully it will help:
http://www.haneycodes.net/visual-studio-2012-intellisense-not-working-solved/
You are not going to get intellisense for CSS in VS2012 for Razor views. There is a workaround to use intellisense. Just create one test view(.aspx) using ASPX view engine and include your css file there. Now intellisense will work in new aspx view. All you have to do is copy paste the css class from aspx to Razor view(.cshtml or .vbhtml). I hope this helps.

Different project settings for user Intellij Idea

How can I do different project settings for users in the same project. I have a project with some .properties file like email.properties which contains user-specific settings.I need something like user-specific enviroment settings, something like this: email..properties, and variable contains in OS enviroment or, maybe, in project file
Here's how I've done this in some projects. I create a System Property to the path of the property file. The path is outside of the project so the properties file is never committed. But to help others who are running the project for the first time, I commit a template properties file with default options.
In intellij, I start the project with a different -D option than my coworkers do and the startup options don't get committed (because we don't commit the .idea folder).
As a result a do the same: at first I created properties folder in propject root, add there file env.properties which contains current environment name (or user can add it as JVM start paramenter -Denv=<env name>. I add static class and method Properties getProperty(String fileName) which receive property file name as parameter and return all records in file as java.util.Properties.
public static Properties loadProperties(String fileName)
{
Properties properties = null;
if (propertiesMap.containsKey(fileName)) {
properties = (Properties)properties.get(fileName);
} else {
String environment = getEnvironment();
try {
properties = (new PropertiesLoaderImpl()).LoadAllPropertiesForUtilAndEnv(environment, fileName);
} catch (FileNotFoundException exception) {}
}
return properties;
}
private static String getEnvironment() {
// Проверка на наличие параметра при запуске java-машины
String environment = System.getProperty("env");
if (environment == null) {
try {
// Попытка найти файл env.properties
ResourceBundle bundle = ResourceBundle.getBundle("properties/env");
environment = bundle.getString("env");
} catch (MissingResourceException exception) {
environment = "";
}
}
return environment;
}
Property search implements that way:
1. look in ..proeprties;
2. if there is no suitable property, then look in .property;
3. else return empy.

Getting assemblyinfo of a feature in Sharepoint

I have a method that collects the assemblyversion of a webpart. (works fine) :
private void GetVersion(object control, out string name, out string version)
{
name= control.GetType().ToString();
version = control.GetType().Assembly.GetName().Version;
}
Now I want to achieve the same for my features:
private void GetFeatureVersion(SPFeature feature, out string name, out string version)
{
name = feature.Definition.GetTitle(new System.Globalization.CultureInfo("en-us"));
version = feature.GetType().Assembly.GetName().Version;
}
But in the Assembly of feature.GetType() isn't the information of my feature, but of sharepoint (14.0.0.0). The name var is fine but thats no surprise as it is not read out of the type.
I added the following to the template.xml - File.
ReceiverAssembly="$SharePoint.Project.AssemblyFullName$"
That did the trick
If you want to get the version of the feature receiver assembly you can do the following:
string version = Assembly.Load(feature.Definition.ReceiverAssembly).GetName().Version;