I'm using Code on OSX together with the .NET Core. While trying to create an ArrayList I'm getting an error that the namespace cannot be found.
The System.Collections is used already. While examining what is suggested from System.Collections I see that not all of the methods are listed as in the documentation.
What could be the problem? I installed the latest .NET Core from MS site.
You cannot use the type because it is defined in a separate NuGet package,
http://www.nuget.org/packages/System.Collections.NonGeneric/
Note that only a few platforms are supported by this package, so for some monikers, you cannot reference it.
The recommended approach is to switch to the generic version of the collection types.
Looks like System.Collections.NonGeneric is not supported in Mac. It didn't work for me even though I had that package installed. Looks like it's deprecated and also Microsoft suggests that to use Generic lists instead.
Open you .csproj and add the following under
<ItemGroup>
<PackageReference Include="System.Collections.NonGeneric" Version="4.3.0">
</PackageReference>
</ItemGroup>
in the terminal or command prompt, make sure you are on the same working directory as your project and run
# dotnet restore
You can now use it in your project
Related
I created a class library. The default version was 1.0.0, and then I updated the class and again created the package using this (dotnet pack -p:PackageVersion=1.0.1 -o \packages) command. I realized that I used the wrong directive in the class and the package was created on the wrong path as well. I changed the directives and created again with the same command with same 1.0.1 in a correct folder. I am unable to refer in other classes with using directive. The compiler does not understand that. When I reference 1.0.2 in csproj package reference then the compiler sees that.
Are these versions immutable? Why removing does not work? How can I make it use version 1.0.1? I have spent hours trying different things, and I do not seem to solve this. Help needed please.
Where is CircuitHandler in Blazor .NET 6?
As I am upgrading packages to .NET 6, I noticed in nuget package manager that Microsoft.AspNetCore.Components.Server package was marked obsolete and so assuming CircuitHandler was moved to another package and that one is no longer needed (As they have done in the past with IAsyncEnumerable and Span<T>), I removed the package. Then I realized that package has completely been removed from nuget browser altogether, and there is no word anywhere I can find on any alternative for .NET 6. MSDN even has Blazor .NET 6 articles talking as if CircuitHandler is easily found in Microsoft.AspNetCore.Components.Server namespace, but no mention of what package or how to get access to that namespace! Example here
I figured this out, as I noticed the type exists in my BlazorApp project, but not my library project. It was a matter of figuring out what the differences are, and it turns out that you need to put <Project Sdk="Microsoft.NET.Sdk.Web"> in the project file instead of <Project Sdk="Microsoft.NET.Sdk">. So just adding the .Web part fixed the issue!
Note: Now my library won't build because it says I need a static Main method entry point. So it seems they aren't allowing CircuitHandlers in class libraries anymore, they must all reside in the Web App itself. Total bummer!
The real solution is to add the following to your project file. What a runaround this was for me to figure out! And I could not find this documented anywhere!
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
I'm developing an application that detects and eliminates useless external references in a given C# project for example a package referenced but not used. For this I need to enumerate all assemblies used either at compile and runtime. For those used at a runtime, I can get names using reflection specifically calling Assembly.GetReferencedAssemblies(). But for those used only at compile-time I think that there is no way to list them without using Roslyn. Have you please any answers to my problematic?
This is just a simple approach, far from perfect. I am sure you can go deeper and play around with Roslyn as much as you want. I am also sure there are much better experts on compilers and Roslyn out there than me :)
Note that this approach does not handle dynamically loaded assemblies. It avoids running the project.
Referenced assemblies
You can use an XML parser instead of Roslyn to analyze the project or solution file. There you will find the list of all referenced packages and project, e.g.:
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MessagePack" Version="2.1.115" />
</ItemGroup>
The above example comes from a .NET Core 3.1 project file.
Update
In order to collect transitive dependencies as well there are several options.
For .NET Core projects you may call dotnet restore and then read the following file $ProjectFolder/obj/project.assets.json. It is a json file that contains all references that were resolved containing both NuGet and runtime packages.
If you want to avoid restoring the project/solution you can start with the packages found in .csproj as described above and use the NuGet Server API to get an array of dependencies for each. Doing this recursively will yield the same result as dotnet restore. NuGet Core wraps the API as C# classes so you can call it directly from your code. Dependencies can be easily queried like here: How to get the dependencies of a NuGet package from private NuGet feed?
Required assemblies
Now you need to identify those that are really necessary. The compilation process takes care of that. It does not (to my humble knowledge) insert any unnecessary references into the compiled code.
Roslyn semantic model
Addressed in this question: Roslyn getting dependencies for class
IL option
You can use Roslyn to compile the given project, then load the generated IL and look for references like [System.Private.CoreLib]. Just throw all referenced assemblies into a HashSet and remove them once you find a matching call in the IL. The resulting set will contain the references that can be removed.
Maybe this project can help viewing the IL. Also SharpLab can be very handy when you need Roslyn output examples.
Load option
If you are fine with loading the compiled project, you can use Assembly.GetReferencedAssemblies() as you indicated in the question instead of analyzing the IL.
I have a library project that extends some functionality on EntityFrameworkCore. I'm looking to support both 2.* and 3.*. My project is setup like so:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
[...]
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.0' ">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" />
</ItemGroup>
[...]
</PropertyGroup>
</Project>
In the code I'm using the function EntityTypeExtensions.FindProperty(...). The signature of this function changes between 2.2.6 and 3.0.0.
The project's code (incorrectly?) uses the signature for 2.2.6. This compiles properly (which shouldn't be the case?) in both target frameworks.
I have a unit test project that multi-targets and has conditional references, much like the original project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.0;netcoreapp2.0</TargetFrameworks>
[...]
</PropertyGroup>
[...]
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.2.6" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.0' ">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0" />
</ItemGroup>
[...]
</Project>
All unit tests (incorrectly?) pass in both target frameworks.
Note that even though it builds and tests pass, when the library is used in a netcore3 project (which references efcore 3.0.0 directly) it throws the following exception. Which seems completely reasonable, I just don't understand why it allowed me to get to this point.
System.MissingMethodException: Method not found: 'Microsoft.EntityFrameworkCore.Metadata.IProperty Microsoft.EntityFrameworkCore.EntityTypeExtensions.FindProperty(Microsoft.EntityFrameworkCore.Metadata.IEntityType, System.Reflection.PropertyInfo)'.
Questions:
Is there a way around this so it gets picked up as an error/warning/something, at least, during the build?
Is the solution to this to use preprocessor directives around the call to .FindProperty(...) and based on the framework make the correct method call? Isn't there a way to do this based on the version of efcore instead of the dependency?
Is there a way to unit test this properly with the different packages? Right now as it is, I expected the unit tests to fail in one of the versions since the method does not exist.
Source repository and specifically the call to FindProperty can be found here.
Sample netcore3 project that results in a MissingMethodException when calling the library can be found here.
Stack trace of the exception can be found here.
I have good news and bad news. The good news is that the problem is with your package, and everything works just how you appear to believe it should work. The bad news is I don't know how your package got incorrectly authored.
Steps to verify:
Download Panner.Order version 1.1.0 from nuget.org (you've published 1.1.1 since asking this questions, which has the same, but different, problem). If you have NuGet Package Explorer installed, open the nupkg with that, expand the lib/ folder and double click each of the .dll files. Alternatively you can extract the nupkg as a zip file then use ILSpy or ILDasm or whatever else you want to inspect the assemblies. Notice that both the netstanard2.0 and netcoreapp3.0 assemblies have the same assembly references. In particular the Microsoft.EntityFrameworkCore.dll reference is for version 2.2.6.0, even though we'd expect the netcoreapp3.0 version to use version 3.0.0.0. Therefore I conclude that your netstandard2.0 assembly was copied incorrectly into the netcoreapp3.0 folder of your package. Your 1.1.1 package has the opposite problem. Both the netstandard2.0 and netcoreapp3.0 folders contain the netcoreapp3.0 assembly, so your package doesn't work with projects that try to use the netstandard2.0 assembly.
However, I have no idea why this happens. When I clone your repo and run dotnet pack and check the generated nupkg, I can see that the netstandard2.0 and netcoreapp3.0 assemblies have different references, so I'm confident that the package I generated locally should work. You need to investigate why the packages you publish are not being generated correctly.
To quickly answer your questions:
Is there a way around this so it gets picked up as an error/warning/something, at least, during the build?
It will, as the problem was not with the project, but with the package. If you multi-target your project and call an API that does not exist in at least one of the TFMs, you will get a compile error.
Is the solution to this to use preprocessor directives around the call to .FindProperty(...) and based on the framework make the correct method call? Isn't there a way to do this based on the version of efcore instead of the dependency?
When you call APIs that are different in different TFMs, yes, you can use #if to change your code per project TFM, as described in ASP.NET Core's docs when migrating to 3.0.
I'm going to ignore the "based on the version of efcore" because I'm a detail oriented person, and I don't want to write one thousand words for something that ultimately doesn't matter. The key is that in this scenario, you don't need to. You used conditions on your package references to bring in a different version of efcore per project TFM, so each time your project gets compiled, it's using a different version of efcore, but only one version per compile target. Therefore you don't need runtime selection of different versions of efcore.
Is there a way to unit test this properly with the different packages? Right now as it is, I expected the unit tests to fail in one of the versions since the method does not exist.
You multi-target your test project, but I see you've done that already. Since you're using a project reference, the test won't detect package authoring problems like what's happening.
If you really want to test the package, rather than your code, you could use a nuget.config file to add a local folder as a package source, then your multi-targeting test project references the package, not the project. You'd probably want to also use the nuget.config file to set the globalPackagesFolder to something that's in .gitignore because NuGet considers packages to be immutable and if a debug version of your package gets into your user profile global packages folder, every project you use on that machine (that uses your user profile global packages folder) will use that debug version, making it more difficult for you to make updates. For customers who want to test packages, rather than projects, I highly recommend using SemVer2's pre-release labels and create a unique package version for every single build to reduce the risk of testing a different version than you intend.
Using package reference rather than project reference is a pain, because it's no longer as simple as writing code and then running the test. You'll need to change code, compile the project that gets generated into a package, copy the package into the package source folder if you haven't automated that, update the package version in your test project, then compile and run the test project. I think you're better off keeping the project reference. Fix the package authoring problem and then trust the tooling works.
Not to directly answer all questions above one by one, just to describe the cause of the original issue and some suggestions.
In the code I'm using the function
EntityTypeExtensions.FindProperty(...). The signature of this function
changes between 2.2.6 and 3.0.0.
According to your description, I assume you may use code like EntityTypeExtensions.FindProperty(entityType, propertyInfo); in your original project.
For Microsoft.EntityFrameworkCore 2.2:
FindProperty (this Microsoft.EntityFrameworkCore.Metadata.IEntityType entityType, System.Reflection.PropertyInfo propertyInfo); second parameter=>PropertyInfo
For Microsoft.EntityFrameworkCore 3.0:
FindProperty (this Microsoft.EntityFrameworkCore.Metadata.IEntityType entityType, System.Reflection.MemberInfo memberInfo); second parameter=>MemberInfo
However, please check PropertyInfo Class, you'll find:
Inheritance: Object->MemberInfo->PropertyInfo
And I think that's the reason why the project's code uses the signature for 2.2.6 but it compiles properly in both target frameworks. And it's the cause of other strange behaviors you met after that...
So for this issue, you could use the signature for 3.0.0(MemberInfo) in code instead of 2.2.6(PropertyInfo) to do the test. I think the build will fall as you expected. And as Heretic suggests in comment, for multi-target project, use #if is a good choice.
Hope all above makes some help and if I misunderstand anything, please feel free to correct me :)
I am currently trying to connect my ASP-NET Core 2 application to Magento's API (WSDL v2), but keep receiving the following errors:
*Doesn't matter which method I call, even the new PortTypeClient().loginAsync(username, password); throws that, with this random endpoint name salesOrderShipmentAddComment.
InvalidOperationException: The operation
'salesOrderShipmentAddComment' could not be loaded because it
specifies \"rpc-style\" in \"literal\" mode, but uses message contract
types or the System.ServiceModel.Channels.Message. This combination is
disallowed -- specify a different value for style or use parameters
other than message contract types or
System.ServiceModel.Channels.Message.
However, using SoapUI, postman or importing with framework 4.6, it works perfectly.
Using the Magento v1 API it works too, but I don't want to use this version.
During the import in asp-net core, I also recieve those warnings (importing v1 doesn't shows any warning):
I'm almost creating a new 4.6 application, hosting it separately to work as a bridge between my application and Magento, even if it hurts my performance and architeture.
This is how I'm doing the import:
*Obs: In Data Type Options, I also tried checking different options, and selecting other data types.
Anything would help...
Thanks in advance
I had the same problem. Make sure you update your Nuget Packages to 4.5.3. After, works correctly for me.
Indeed updating the following packages to version 4.5.3 seems to resolve the issue:
System.ServiceModel.Duplex
System.ServiceModel.Http
System.ServiceModel.NetTcp
System.ServiceModel.Security
Seems like 4.4.4 version of those packages are installed by default, while adding WCF service reference via VS 2017 15.9.4 UI
Just update System.ServiceModel.Http to 4.5.3
According to
https://ozguradem.net/english/coding/2018/11/06/soap-services-with-dotnet-core/
Open .csproj file and edit following packages minimum version like these
<ItemGroup>
<PackageReference Include="System.ServiceModel.Duplex" Version="4.5.*" />
<PackageReference Include="System.ServiceModel.Http" Version="4.5.*" />
<PackageReference Include="System.ServiceModel.NetTcp" Version="4.5.*" />
<PackageReference Include="System.ServiceModel.Security" Version="4.5.*" />
</ItemGroup>