WIX: don't show build number from [ProductVersion] - wix

My Wix installer has the product version set like this:
<Product Version="4.6.0.0" ..>
And I show it in the UI like this:
<String Id="WelcomeDlgTitle">{\WixUI_Font_Bigger}Welcome to the [ProductName] v[ProductVersion] Setup Wizard</String>
This works well but I would like to omit the build number (ie. v4.6.0 instead of v4.6.0.0). Is there a way to do this?

You can omit the 4th field of the Product/#Version attribute as Windows Installer ignores it anyway.
<Product Version="4.6.0" ..>
If you really want to keep the 4th field of the version number, you'd have to write a custom action to parse the string and strip the 4th field.

Thank you #zett42, your comment pointed me out in the right direction - I created a Wix Preprocessor Extension, following the documentation here: http://wixtoolset.org/documentation/manual/v3/wixdev/extensions/extension_development_preprocessor.html
Here are the classes I created:
public class MaterialiserExtension : WixExtension
{
private MaterialiserPreprocessorExtension preprocessorExtension;
public override PreprocessorExtension PreprocessorExtension
{
get
{
if (this.preprocessorExtension == null)
{
this.preprocessorExtension = new MaterialiserPreprocessorExtension();
}
return this.preprocessorExtension;
}
}
}
public class MaterialiserPreprocessorExtension : PreprocessorExtension
{
private static string[] prefixes = { "versionUtil" };
public override string[] Prefixes { get { return prefixes; } }
public override string EvaluateFunction(string prefix, string function, string[] args)
{
string result = null;
switch (prefix)
{
case "versionUtil":
switch (function)
{
case "ToString":
if (0 < args.Length)
{
result = Version.Parse(args[0]).ToString(args.Length >1 && args[1] != null ? int.Parse(args[1]) : 4);
}
else
{
result = String.Empty;
}
break;
}
break;
}
return result;
}
}
One thing that was not immediately obvious - in my Visual Studio Wix project, I had to add
-ext "$(SolutionDir)Materialiser.Wix\bin\Release\Materialiser.Wix.dll" to Properties (Alt+Enter) > Tool Settings > Compiler (candle) and the same in Linker (light).
To use, it is very simple:
in my .wxs file I define a property like this:
<?define ProductVersion="4.6.0.5" ?>
Then I use it in Product like this:
<Product Version="$(var.ProductVersion)" .. >
And then I create anew property like this:
<Property Id="VersionWithNoBuildNumber" Value="$(versionUtil.ToString([ProductVersion], 3))" />
and in my .wxl file I use it normally:
<String Id="WelcomeDlgTitle">{\WixUI_Font_Bigger}Welcome to the [ProductName] v[VersionWithNoBuildNumber] Setup Wizard</String>
I hope this helps someone else too :p

Related

Can I add to or change the default CSS class when using ValidationMessage in ASP.NET Core?

I am using ValidationMessage in a razor component to show validation message, like this:
<ValidationMessage For="#(() => ViewModel.CompanyNumber)" />
This generates this HTML code:
<div class="validation-message">The company number field is required.</div>
Is it possible to change the CSS-class? I want to use something else than validation-message. Adding class="myclass" is ignored by the controller. I've also tried with #attributes without success.
With .NET5 they added functionality to customize the validation classes on the actual input-fields (which issue 8695 was about) by way of setting a FieldCssClassProvider to the edit context. But there still seems to be no way of customizing the classes of the ValidationSummary or ValidationMessage components
Snipped directly from the .NET 5 docs
var editContext = new EditContext(model);
editContext.SetFieldCssClassProvider(new MyFieldClassProvider());
...
private class MyFieldClassProvider : FieldCssClassProvider
{
public override string GetFieldCssClass(EditContext editContext,
in FieldIdentifier fieldIdentifier)
{
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
return isValid ? "good field" : "bad field";
}
}
Using this will yield the below html for an invalid input. At least with this we can style the actual input elements. Just not the messages...
<input class="bad field" aria-invalid="">
<div class="validation-message">Identifier too long (16 character limit).</div>
You can change the validation-message class inside the css file app.css inside the wwwroot. Or site.css in in earlier previews.
.validation-message {
color: red;
}
The class is set in ValidationMessage.cs
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
foreach (var message in CurrentEditContext.GetValidationMessages(_fieldIdentifier))
{
builder.OpenElement(0, "div");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttribute(2, "class", "validation-message");
builder.AddContent(3, message);
builder.CloseElement();
}
}
https://github.com/dotnet/aspnetcore/blob/master/src/Components/Web/src/Forms/ValidationMessage.cs
Why don't you just copy the code for ValidationMessage.cs and write in your own property? There is nothing special about this class except for capturing a Cascading Parameter. Just take this file and make your own with a slightly different name then add:
[Parameter] public string AdditionalClassNames {get;set;}
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
foreach (var message in CurrentEditContext.GetValidationMessages(_fieldIdentifier))
{
builder.OpenElement(0, "div");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttribute(2, "class", string.IsNullOrEmpty(AdditionalClassNames) ? "validation-message" : $"validation-message {AdditionalClassNames}");
builder.AddContent(3, message);
builder.CloseElement();
}
}
https://github.com/dotnet/aspnetcore/blob/master/src/Components/Web/src/Forms/ValidationMessage.cs
EDIT
Even better, it's not sealed! Just use it as a base class for a new version and add what I mentioned above.
It is not possible in ASP.NET Core 3.1. Hopefully, it will be included in next major version, see this feature request:
https://github.com/dotnet/aspnetcore/issues/8695

Sitecore Pipeline (indexing.filterIndex.inbound) not being called

I am trying to create a Lucene index in Sitecore 8.x of items that are visible to unauthenticated users (extranet\Anonymous). In order to do this I am trying to use the indexing.filterIndex.inbound pipeline.
I have tried writing a custom pipeline that returns false if the item cannot be read as extranet\Anonymous:
public class ApplyInboundIndexAccessFilter : InboundIndexFilterProcessor
{
public override void Process(InboundIndexFilterArgs args)
{
var item = args.IndexableToIndex as SitecoreIndexableItem;
var anonymousUser = Sitecore.Security.Accounts.User.FromName("extranet\\anonymous", false);
if (!item.Item.Security.CanRead(anonymousUser))
{
args.IsExcluded = true;
}
}
}
but at no time does this pipeline get invoked.
I have added my config (tried it with the default, before, after, with the default removed)
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<indexing.filterIndex.inbound>
<processor type="MyApplication.Site.Features.ContentSearch.IndexFilters.ApplyInboundIndexAccessFilter, MyApplication.Site">
<includedIndexNames hint="list">
<indexName>siteSearchIndex_web</indexName>
</includedIndexNames>
<excludedIndexNames hint="list">
<indexName>siteSearchIndex_master</indexName>
</excludedIndexNames>
</processor>
</indexing.filterIndex.inbound>
</pipelines>
</sitecore>
</configuration>
Am I right in assuming that this should be called on indexing, if not, when?
Any suggestions would be gratefully received.

Bean Validation with JAX-RS (rest-easy): parameter name not recognized

I'm using JAX-RS resources with Bean Validation and integration between these two works as expected.
However, the default error messages generated in case of a validation error report parameter names as arg0, like so
[PARAMETER]
[login.arg0.password]
[password is required]
[]
Corresponding method definition:
#POST //and other JAX-RS annotations
public Response login(
#NotNull
#Valid
LoginBody loginBody) {
[...]
protected static class LoginBody {
#NotNull(message = EMAIL_REQUIRED)
public String email;
#NotNull(message = PASSWORD_REQUIRED)
public String password;
}
While I'm generally fine with this message pattern, what actually is annyoing, is the fact that the original parameter name is not recognized, i. e. I'd rather like to see
login.loginBody.password instead of arg0.
Is there an easy way to fix this, e. g. somehow provide an explicit name for that parameter?
I'm using WildFly Swarm 2017.6.0. From what I found out this means I have resteasy + resteasy-validator + hibernate-validator
Thanks.
You could try to compile your app with -parameters or instruct your IDE to do so, e.g. in case of
eclipse: preferences -> java -> compiler -> "store information about method parameters (usable via reflection)"
With that in place you then need to instruct the Bean Validation infrastructure (e.g. ) hibernate-validator to
use the ReflectiveParameterNamer via META-INF/validation.xml.
<parameter-name-provider>org.hibernate.validator.parameternameprovider.ReflectionParameterNameProvider</parameter-name-provider>
See also Hibernate Validator Configuration
I got something reliably working with the Paranamer library
META-INF/validation.xml:
<?xml version="1.0" encoding="UTF-8"?>
<validation-config
xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://jboss.org/xml/ns/javax/validation/configuration
validation-configuration-1.1.xsd"
version="1.1">
<default-provider>org.hibernate.validator.HibernateValidator
</default-provider>
<message-interpolator>org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator
</message-interpolator>
<traversable-resolver>org.hibernate.validator.internal.engine.resolver.DefaultTraversableResolver
</traversable-resolver>
<constraint-validator-factory>org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl
</constraint-validator-factory>
<parameter-name-provider>org.hibernate.validator.parameternameprovider.ParanamerParameterNameProvider</parameter-name-provider>
</validation-config>
To get paranamer working with wildfly I needed to create a parameter-namer jboss-module
and reference that module from the module.xml of the hibernate-validator module.
With that in place I could simply write:
#POST
public Response login(#NotNull #Valid #Named("authRequest") AuthRequest authRequest) {
return Response.ok().build();
}
...
public class AuthRequest {
#NotNull(message = AuthMessages.EMAIL_REQUIRED)
public String email;
#NotNull(message = AuthMessages.PASSWORD_REQUIRED)
public String password;
}
which yields the following response for a request sent via curl:
curl -H "Content-Type: application/json" -H "Accept: application/json" -d '{"email":"foo#bar.com"}' -v http://localhost:8080/javaweb-training/resources/auth
Response:
{"exception":null,"fieldViolations":[],"propertyViolations":[],"classViolations":[],"parameterViolations":[{"constraintType":"PARAMETER","path":"login.authRequest.password","message":"password.required","value":""}],"returnValueViolations":[]}%
... note login.authRequest.password instead of just login.arg0.password
There is a very simple solution: you can set your own error message in the constraint definition as follows
#NotNull(message = "password is required")
If you want a more generic solution based on the JAX-RS parameter annotations you can implement your own simple ParameterNamProvider and register it in validation.xml as follows. This has the advantage of not having to change the jboss module structure. I also didn't have to change any compiler flags...
public class AnnotatedParameterNameProvider implements ParameterNameProvider {
#Override
public List<String> getParameterNames(Constructor<?> constructor) {
return lookupParameterNames(constructor.getParameterAnnotations());
}
#Override
public List<String> getParameterNames(Method method) {
return lookupParameterNames(method.getParameterAnnotations());
}
private List<String> lookupParameterNames(Annotation[][] annotations) {
final List<String> names = new ArrayList<>();
if (annotations != null) {
for (Annotation[] annotation : annotations) {
String annotationValue = null;
for (Annotation ann : annotation) {
annotationValue = getAnnotationValue(ann);
if (annotationValue != null) {
break;
}
}
// if no matching annotation, must be the request body
if (annotationValue == null) {
annotationValue = "requestBody";
}
names.add(annotationValue);
}
}
return names;
}
private static String getAnnotationValue(Annotation annotation) {
if (annotation instanceof HeaderParam) {
return ((HeaderParam) annotation).value();
} else if (annotation instanceof PathParam) {
return ((PathParam) annotation).value();
} else if (annotation instanceof QueryParam) {
return ((QueryParam) annotation).value();
}
return null;
}
}
In validation.xml:
<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.1.xsd"
version="1.1">
<parameter-name-provider>com.yourcompany.providers.AnnotatedParameterNameProvider</parameter-name-provider>
</validation-config>
Note that you can also customize how the error message is formatted by implementing your own MessageInterpolator and registering it in the validation.xml
Can you try to implement an exception mapper for ConstraintViolationExceptions and see if the information you have there (the list of constraint violations) can help you to obtain the parameter name?
Updated version of #thomas-darimont for Hibernate Validator 6.X.
Variant#1 - with build in Java 8 (using -parameters compile parameter)
Specify dependencies (gradle example):
// Define explicit hibernate validator 6.x
implementation('org.hibernate.validator:hibernate-validator:6.0.13.Final')
implementation('org.jboss.resteasy:resteasy-validator-provider-11:3.6.2.Final') {
// Exclude transitive hibernate validator 5.x
exclude group: 'org.hibernate', module: 'hibernate-validator'
}
Specify validator(s):
#GET
#Path("user/{userId}")
public Response getUser(#Size(min = 2) #PathParam("userId") String userId) {
return null;
}
Note: org.hibernate.validator.internal.engine.DefaultParameterNameProvider will return parameter names obtained from the Java reflection API.
Variant #2 - use ParaNamer library. (xml configuration)
In case you don't want to be dependant on compilation flag.
Specify dependencies (gradle example):
// Define explicit hibernate validator 6.x
implementation('org.hibernate.validator:hibernate-validator:6.0.13.Final')
implementation('org.jboss.resteasy:resteasy-validator-provider-11:3.6.2.Final') {
// Exclude transitive hibernate validator 5.x
exclude group: 'org.hibernate', module: 'hibernate-validator'
}
// ParaNamer library
implementation('com.thoughtworks.paranamer:paranamer:2.8')
Specify validator(s):
#GET
#Path("user/{userId}")
public Response getUser(#Size(min = 2) #PathParam("userId") String userId) {
return null;
}
Put <project_dir>/src/main/resources/META-INF/validation.xml
<?xml version="1.0" encoding="UTF-8"?>
<validation-config
xmlns="http://xmlns.jcp.org/xml/ns/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/validation/configuration
http://xmlns.jcp.org/xml/ns/validation/configuration/validation-configuration-2.0.xsd"
version="2.0">
<parameter-name-provider>org.hibernate.validator.parameternameprovider.ParanamerParameterNameProvider</parameter-name-provider>
</validation-config>
Note: Since Hibernate Validator 6.x org.hibernate.validator.parameternameprovider.ReflectionParameterNameProvider is deprecated, use org.hibernate.validator.parameternameprovider.ParanamerParameterNameProvider instead.
Question: Can I configure this with Java-code style only?
Unfortunately, no. (See details here).

Setting the version number for .NET Core projects

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

How do I access ITaskItem meta data from with my MSBuild script?

I have a custom Build task that returns ITaskTem[] as output to my build script. I cannot find an documentation/examples on how I can access these values from with in my MSBuild script.
My Execute method calls this private method which returns the array. I would like to be able to iterate through the Output and get both the TaskItem ItemSpec and the "Message" metadata item. How can I do this?
[Output]
public ITaskItem[] FailedTestsResults { get; set; }
...
private ITaskItem[] GetFailedTests(TestResultsSummary testResultsSummary)
{
IList<TestResult> testList = testResultsSummary.Tests.ToList();
IEnumerable<TestResult> failedTests = testList.Where(x => !x.Passed);
IList<ITaskItem> failedTestsTaskItems = new List<ITaskItem>();
foreach (var failedTest in failedTests)
{
//test encountered enexpected error.
ITaskItem failTestItem = new TaskItem(failedTest.TestName);
failTestItem.SetMetadata("Message", failedTest.Message);
failedTestsTaskItems.Add(failTestItem);
}
return (ITaskItem[]) failedTestsTaskItems.ToArray();
}
I figured it out. Metadata can be accessed like so..
<Message Text="Failed: %(FailedTests.Identity) => %(FailedTests.Message)" />
Notice the use of '%' rather than '$'.