How to fix the inconsistent naming convention of embedded resources in vNext? - asp.net-core

As far as I can tell the project.json file has taken over handling the majority of properties for any given file in a project in VS2015. I've setup a project to embed files into my assembly as follows, however the resulting naming convention of the embedded resources is a departure from what is produced by the previous versions of the c# compiler.
In current state resources are embedded using the period as a separator and included the Assembly name at the beginning like: ClassLibrary3.Templates.dashboard.html
In vNext embedded resource names are produced using the forward slash as a separator and do not include the Assembly's name; well sometimes. See the accompanying picture below. .resx files seem to follow the old pattern while anything defined in the project.json is something totally new.
Can I control the naming convention with a setting somewhere? Is this a bug, feature, or a todo? I need something consistent.
{
"version": "1.0.0-*",
"description": "",
"authors": [ "" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"resource": ["Templates/**/*.*"], // embed everything beneath this folder
"dependencies": {
},
"frameworks" : {
"dnx451": { },
"dnxcore50" : {
"dependencies": {
"System.Collections": "4.0.10-beta-22816",
"System.Linq": "4.0.0-beta-22816",
"System.Threading": "4.0.10-beta-22816",
"Microsoft.CSharp": "4.0.0-beta-22816"
}
}
}
}

That's a known issue for beta4 and below. It has been fixed in beta5. The names are now identical to the ones generated by MsBuild, with a few exceptions.
The most notable exception is that MsBuild ignores the "Resources" folder from the name. For example:
Class1/Resources/x.resx -> Class1.x.resources
while in ASP.NET 5 we have:
Class1/Resources/x.resx -> Class1.Resources.x.resources
For that, we've added support for named resources. They are useful in scenarios where you want to share resources between multiple projects, including the resource readers OR in PCL scenarios.

Related

IOS Universal links using expo is NOT working

I've an EXPO app and i'm trying to get into the app from external links (universal/deep linking), Android is up and running perfectly and IOS is not working.
the app.json file is configured as described here:
"associatedDomains": [
"applinks:*.<DOMAIN_NAME>.com",
"applinks:<SUB_DOMAIN>.<DOMAIN_NAME>.com"
]
And because of my app is using WEBVIEW of my original website, the file /.well-known/apple-app-site-association is located at my client repository under the SRC folder like so:
Content-Type: application/pkcs7-mime
{
"applinks": {
"apps": [],
"details": [{
"appID": "<APP_ID>",
"paths": ["/login/*"]
}]
}
}
Now, AASA validator is OK, but external links still not opening the native app!!!
What to do?!
I found the answer on the expo forums and want to post the solution here because I spent hours/days trying to figure out the answer. And kept running into this question here on SO. And due to only being easily testable on production(vs local or release channel deployments). I want to save other users the pain of releasing their app with broken universal deep links.
Expo's documentation isn't clear here. In the iOS section of Expo's linking guide is fairly vague and some of the language is not explicit or clear enough. To make matters worse everything you find on SO or elsewhere is filled with conflicting and out of date info.
While the OP's question is likely solved solely by the last item in this list, I want to cover a couple of things I also had issues figuring this out for posterity and to clear things up I kept trying to piece together:
appID is basically a combination of the iOS team ID which can be found in the apple developer console under membership. And the bundle id found in app store connect > app > app information (or it should also be in your app.json).
Some of apple's documentation can be confusing and wildcards do match more than one character. So for example a path of "/auth/*" will properly route the a url with the path of "/auth/login".
You do not need to sign your AASA file.
Do not include https or paths in your associatedDomains configured in app.json it should just be the domain (e.g. "applinks:google.com").
The working mime type for your AASA is application/pkcs7-mime and not application/json
you're AASA file can me in your root directory or .well-known [docs], I suggest placing it on both as this will help create some redundancy. You can upload one file and configure your server to resolve the same file.
You need to enable associated domains service for you identifier. Expo states this in their documentation but the navigation to where to do this is out of date. On the developer portal > Certificates, Identifiers & Profiles > identifiers > click on the identifier that maches your app's bundle ID > capabilities > Check "Associated Domains" It will tell you that this will invalidate your signing profile and you'll need a new one to deploy your app. So long as you are in a managed expo app, expo will handle this for you when you create a new build.
The main problem you're facing is that the AASA file or apple-app-site-association has gone through 3 different iterations with different schemas. Each schema is fairly different and you need to combine all 3 schemas to support all current + older versions of iOS. The schema in the OPs question is used by ios 11 & 12 and not supported by iOS 13+ (which came out 2019). Expo's documentation is unclear about this and makes it sound like the displayed version will work with all versions and you can use the new schema if you want the added features, however the new schema is absolutely necessary to work with newer iphones. The expo documentation has the new schema minified so you don't even realize it exists if you're not paying attention.
Another user explained this solution in depth on the expo forums - I won't go into as much depth but will include his combinations of the different schemas that did work for me so that it's easier to find. (although the new schema is probably sufficient if you don't plan on supporting anything lower than iOS 13. as 15 is the current version as of this writing)
Example of all the schemas combined.
{
"applinks": {
"apps": [],
"details": [
{
"appIDs": [ "TEAMID.bundleidentifier", "ABCDE12345.com.example.app2" ],
"components": [
{
"#": "no_universal_links",
"exclude": true,
"comment": "Matches any URL whose fragment equals no_universal_links and instructs the system not to open it as a universal link"
},
{
"/": "/buy/*",
"comment": "Matches any URL whose path starts with /buy/"
},
{
"/": "/help/website/*",
"exclude": true,
"comment": "Matches any URL whose path starts with /help/website/ and instructs the system not to open it as a universal link"
},
{
"/": "/help/*",
"?": { "articleNumber": "????" },
"comment": "Matches any URL whose path starts with /help/ and which has a query item with name 'articleNumber' and a value of exactly 4 characters"
}
]
},
{
"appID": "TEAMID.bundleidentifier",
"paths": [ "/buy/*", "/help/website/*", "/help/*" ]
},
{
"appID": "OTHTEAMID.otherbundleidentifier",
"paths": [ "/blog", "/blog/post/*" ]
},
{
"appID": "YAOTHTEAMID.yetanotherbundleidentifier",
"paths": [ "*" ]
}
]
},
"activitycontinuation": {
"apps": [
"TEAMID.bundleidentifier",
"OTHTEAMID.otherbundleidentifier"
]
}
Example of the new schema if you don't need to support older versions of iOS
{
"applinks": {
"apps": [],
"details": [
{
"appIDs": ["ABCDE12345.com.example.app", "ABCDE12345.com.example.app2"],
"components": [
{
"#": "no_universal_links",
"exclude": true,
"comment": "Matches any URL whose fragment equals no_universal_links and instructs the system not to open it as a universal link"
},
{
"/": "/buy/*",
"comment": "Matches any URL whose path starts with /buy/"
},
{
"/": "/help/website/*",
"exclude": true,
"comment": "Matches any URL whose path starts with /help/website/ and instructs the system not to open it as a universal link"
},
{
"/": "/help/*",
"?": { "articleNumber": "????" },
"comment": "Matches any URL whose path starts with /help/ and which has a query item with name 'articleNumber' and a value of exactly 4 characters"
}
]
}
]
}

ASP.NET Core (vNext) project can't find reference to 4.51

I have a asp.net 5 (vNext) project with a project.json that is named FMS.DOMAIN. One of the references is a dotNet 4.51 project named FMS.DAL.
This works on all machine except one. On one machine it can't find this dotNet 4.51 project. I think it is looking for it on a public nuget server.
When I do 'dnu restore' I see this:
C:_Workspaces\MyProject\MyProject\FMS.Domain\project.json
CACHE https://www.nuget.org/api/v2/FindPackagesById()?id='FMS.DAL'
Unable to locate Dependency FMS.DAL >= 1.0.
This is the project.json from FMS.Domain.
{
"version": "1.0.0-*",
"description": "FMS.Domain Class Library",
"authors": [ "ctcrrmcidmc" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"frameworks": {
"dnx451": {
"dependencies": {
"FMS.DAL": "1.0.0-*"
}
}
},
"dependencies": {
"AutoMapper": "4.1.1",
"FMS.Common": "1.0.0-*"
}
}
How does it know when to search nugget and when to use a local project? The reference to "FMS.Common": "1.0.0-*" is also a local project and it's working (but it's vNext).
We did get it to work if we had a reference to the DLL directly using the 'Add Reference' context menu. That produce an edit the project.json that look the same as the manual edit but it works. It must be doing something else.
More Info:
I blew away my workspace and got the code fresh from TFS. I am getting the problem on my machine. I see this error with 'dnu restore':
CACHE https://www.nuget.org/api/v2/FindPackagesById()?id='FMS.DAL'
nable to locate Dependency FMS.DAL >= 1.0.0
It is looking for FMS.DAL at nuget.org instead of in my project. I removed the dependency from project.json and saved, then I add it back by right-clicking on references and picking a project reference. It's added back to project.json and looks exactly the same as before I removed it. I run 'dnu restore' again and it works.
The only pending change is in project.json and when I do a compare with TFS there are no differences. Then I did an undo pending changes for the entire solution and 'dnu restore' still works.

Differences in where you place dependencies in project.json file of ASP.NET Core?

I was just looking at the project.json file in one of my ASP.NET Core projects and noticed there are two different areas to list dependencies.
One inside the frameworks node and the other is a dependencies node. Why/when would/should you place the dependencies in one location over the other?
{
"version": "1.0.0-*",
"description": "My Class Library",
"authors": [ "" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"frameworks": {
"dotnet5.4": {
"dependencies": {
"Microsoft.CSharp": "4.0.1-beta-23516",
"System.Collections": "4.0.11-beta-23516",
"System.Linq": "4.0.1-beta-23516",
"System.Runtime": "4.0.21-beta-23516",
"System.Threading": "4.0.11-beta-23516"
}
}
},
"dependencies": {
"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final"
}
}
The reason is very easy. You can have different dependencies for different frameworks.
In some cases the specified dependence exist in different versions for different frameworks.
In another case the specified dependency like System.Runtime needed be not included as all. The problem is here the DLL is separate module in .NET Core (see here), but the dnx46 or dnx451 contains the implemented methods inside of .Net framework. One don't need to include no external (additional) dll. Thus you need don't include System.Runtime package in the the dnx451 part of the dependencies or as the common dependency. Thus System.Runtime is framework-specific dependencies.
In some seldom cases you can include the dependency in the form "dnx451": "frameworkAssemblies": { "System.Runtime": "" }} to skip including of System.Runtime if it was erroneously required (see the question). Typically one uses frameworkAssemblies to reference to assemblies from Global Assembly Cache (GAC) without redistributing it (see the documentation).

VSCode appends taskName to msbuild automatically

In Visual Studio Code (VSCode) I've create a task to build my c++ project. The build-process is based on Visual-Studio 12.0 projects files create by CMake. It provides configurations for Release/Debug/... modes and I want to create for each configuration a separate task.
Problem: VSCode appends the taskName to msbuild automatically. My tasks.json file looks like:
{
"version": "0.1.0",
"command": "msbuild",
"args": ["${cwd}/build/PROJECTNAME.sln",
"/property:GenerateFullPaths=true"],
"taskSelector": "/t:",
"tasks": [
{
"taskName": "build release",
"args": ["/p:Configuration=Release"],
"problemMatcher": "$msCompile"
},
{
"taskName": "build debug",
"args": ["/p:Configuration=Debug"],
"problemMatcher": "$msCompile"
}]
}
The argument /t:${taskName} seems to be appended automatically to msbuild. If I add the parameter /t:Build in the args variable of a task manually, It gives me the error, that two targets are specified in msbuild. Removing the taskSelector variable does not help. The only way I get it running, is to set all taskName variables to Build, but then I can not distiguish between different tasks in the tasks-selector.
Any ideas how to solve this?
PS: is there a reference of possible parameters for the tasks.json file, except those provided in the example file and on the official documentation site?
We have a work item to support suppressTaskName on the task description. If this does get implemented would it solve your problem.
After playing around with msbuild command-line arguments I've figured out a workaround. It is not nice and only works in some cases, but for me it is fine. Hopefully in later versions of VSCode a better solution can be implemented.
The idea: Add a dummy argument to msbuild, that has no meaningful effect. I've tried two version: (1) add the preprocess command-line switch, that creates a file with content that you could ignore, i.e. "taskSelect": "/pp:"; (2) add a dummy property to msbuild that accepts any argument, like /p:DefineConstants=....
The final tasks.json file looks like:
{
"version": "0.1.0",
"command": "msbuild",
"args": ["${cwd}/build/PROJECTNAME.sln",
"/property:GenerateFullPaths=true"],
// a dummy taskSelector to overcome a restriction in msbuild
// (1) "taskSelector": "/pp:",
// (2) ...
"taskSelector": "/p:DefineConstants=taskName_",
"tasks": [
{
"taskName": "build_release",
"args": ["/t:Build", "/p:Configuration=Release"],
"problemMatcher": "$msCompile"
},
{
"taskName": "build_debug",
"args": ["/t:Build", "/p:Configuration=Debug"],
"problemMatcher": "$msCompile"
}
]}
You can only use taskName without spaces, but this is ok, since one can now distinguish between different tasks.
Maybe in other build-systems like grunt there is a similar dummy-parameter that can be set to taskName without changing the build-process.
I'm open to better solutions to this problem.

Create different versions form one bootstrap file with require.js

I develop an iPad/iPhone App web app. Both share some of the resources. Now I wanna build a bootstrap js that looks like this:
requirejs(['app'], function(app) {
app.start();
});
The app resource should be ipadApp.js or iphoneApp.js. So I create the following build file for the optimizer:
{
"appDir": "../develop",
"baseUrl": "./javascripts",
"dir": "../public",
"modules": [
{
"name": "bootstrap",
"out": "bootstrap-ipad.js",
"override": {
"paths": {
"app": "ipadApp"
}
}
},
{
"name": "bootstrap",
"out": "bootstrap-iphone.js",
"override": {
"paths": {
"app": "iphoneApp"
}
}
}
]
}
But this doesn't seems to work. It works with just one module but not with the same module with different outputs.
The only other solution that came in my mind was 4 build files which seems a bit odd. So is there a solution where i only need one build file?
AFAIK the r.js optimizer can only output a module with a given name once - in your case you are attempting to generate the module named bootstrap twice. The author of require.js, #jrburke made the following comment on a related issue here:
...right now you would need to generate a separate build command for each script being targeted, since the name property would always be "almond.js" for each one.
He also suggests:
...if you wanted just one build file to run, you could create a node program and drive the optimizer multiple times in one script file. This example shows using requirejs as a module and calling requirejs.optimize().
I took a similar approach in one of my projects - I made my build.js file an ERB template and created a Thor task that ran through my modules and ran r.js once for each one. But #jrburke's solution using node.js is cleaner.