CircuitHandler Equivalent for .NET 6? - c#

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>

Related

How to auto increment the version (eg. “1.0.*”) of a .NET Core project?

In the old .NET framework, you could set the [assembly: AssemblyVersion("1.0.*")] and the compiler would auto-increment the version.
With .NET core, I've tried all sorts of things, but I can't get it to auto-increment.
I've added <Deterministic>False</Deterministic> and <AssemblyVersion>1.0.*</AssemblyVersion> to the .csproj per similar question. The code compiles but the version stays the same
I've tried the same thing but with <Version>1.0.*</Version> tag as described here. This actually set the product version to 1.0.* (with the asterisk).
I've set the Assembly Version in the Property Properties/Package page. Doesn't seem to do anything either.
None of it seems to work. Am I missing something simple? This is just a standard .NET Core Web Project.
As indicated if you follow some of the links from the comments/answers, the most straightforward way to get .NET Framework-like version auto-incrementing in .NET Core 3/5/6 is to add to your .csproj:
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Deterministic>false</Deterministic>
</PropertyGroup>
And add to your Program.cs:
[assembly: System.Reflection.AssemblyVersion("1.0.*")]
You may still want to read the links if there are other AssemblyInfo properties you want to set.
One simple way I did it previously is by reading the current version and increasing it by one, so you get the current version and increment by one using the command line.
With that said, it is possible to do the following for the .net core project:
In your .csproj file, you add the following:
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Deterministic>false</Deterministic>
</PropertyGroup>
In your code, for instance, in your entry point class, add the following:
using System.Reflection;
[assembly: AssemblyVersion("1.0.*")]
When you build the code, it will get a version like 1.0.8419.40347.
To make more customization, check this article: https://sachabarbs.wordpress.com/2020/02/23/net-core-standard-auto-incrementing-versioning/
In addition, I added this link:
Equivalent to AssemblyInfo in dotnet core/csproj
And I use this exertion as well for Visual Studio:
https://marketplace.visualstudio.com/items?itemName=PrecisionInfinity.AutomaticVersions

Could not load type 'System.Web.HttpPostedFileBase' from assembly System.Web

I am working on a solution which has two projects, one is a .NET Core 3 project and the other is a .NET Framework 4.7.2 project.
The .NET Framework 4.7.2 project has a class which uses HttpPostedFileBase on a method.
The problem is that when I use Autofac to register that class on my .NET Core project, I get this error:
Could not load type 'System.Web.HttpPostedFileBase' from assembly
'System.Web, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a'.
I am aware that HttpPostedFileBase does not exist on System.Web on .NET Core 3, so my guess is that when I try to register the class with Autofac, the System.Web being used is the one from my .NET Core project and not the one from the .NET Framework project. Would it be viable to try to use only the System.Web from the other project, into my .NET Core project?
I've tried adding the System.Web.dll from the other project, in to my .NET Core project but I get the error:
One or more errors occurred. The reference is invalid or unsupported.
I hope this answer helps you get on the right track.
Few options to resolve your problem come to my mind:
1. Completely abandon .NET Framework
Change project using .NET Framework 4.7.2 to use .NET Standard if that is possible and rewrite method in question completlty abandoning .NET Standard. This is in some ways easier options and I advise you to take it if possible.
2. Target both .NET Standard and .NET Framework
If this is not possible, because of some issues e.g. project is used in other solutions that cannot target .NET Standardyou can make this project target both platforms.
You can do second option through VisualStudio or directly in csproj file editing TargetFramework attribute in newer csproj format (I strongly advise you to migrate project to new format with some wizard). Then you should add condition on ItemGroup in csproj to only include System.Web if you are using .NET Framework 4.7.2 and .NET Standard counterpart if using .NET Standard. Then write the method in question again using .NET Standard, but do not delete the old one. Instead you should make compiler choose the right one with #if compiler instructions.
Below you can find examples with new csproj format. If you use old one you can use e.g THIS WIZARD to automatically migrate.
<TargetFramework>net472</TargetFramework>
Should be changed to (mind s):
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
And then to include System.Web only when using net472:
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<Reference Include="System.Web" />
</ItemGroup>
And later the same for .NET Standard.
Last part should be done in C# code itself:
#if NETFRAMEWORK
... method using **HttpPostedFileBase** ...
#elif NETSTANDARD
... its .NET Standard counterpart ...
#endif
Constants used above - NETSTANDARD and NETFRAMEWORK are wildcards for more specific version of mentioned platforms. You can find them all HERE
You might be forced to do similar things with callers of method in question.
If those things do not help you might want to check assembly binding redirects if you have any as this issue I did post about might not be the only one there is.
Good luck, I hope my answer helps in any way.
for some reason when I had registered the class I was talking about with Autofac like this: builder.RegisterType() .EnableClassInterceptors().InterceptedBy(typeof(LogInterceptors), typeof(CacheInterceptor)); and then removed the class interceptors and registered the class like builder.RegisterType(); , then the error disappeared.

Handling conditional package references in code and unit tests

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 :)

The type 'MySqlConnection' exists in both 'MySql.Data Issue

I have Referenced MySql.Data on one project and Other project referenced nuget package which also referenced MySqlConnector inside of it. projects has dependency .
when i compile application im getting this error
This is application hierarchy
is there any way to avoid this? or did i do anything wrong when referencing packages?
Thanks
UPDATE
this is the same namespaces from difference libs
UPDATE 2
This is the sample repo which reproduced same issue
In NET.Framework projects you can go to the reference properties and set an alias for assembly. Net core projects doesn't fully support yet aliases for assemblies. But there is a workaround to use aliases in .net core. Edit your csproj file like this:
<Project Sdk="Microsoft.NET.Sdk.Web">
...
<Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'MySqlConnector'">
<Aliases>MySqlConnectorAlias</Aliases>
</ReferencePath>
</ItemGroup>
</Target>
...
</Project>
then in your cs file before all usings:
extern alias MySqlConnectorAlias;
then you can reference to you type from MySqlConnector like this:
MySqlConnectorAlias::MySql.Data.MySqlClient.MySqlConnection
It will work If you remove mysql.data reference from Your project/references.
Hope it will work for you. for me it was worked. My project is ASP.NET Core Framework. Created project in VS2017 and opening in VS2019 at that time it introduced.

Add project.json package references to a VSIX

When trying to add references to a VSIX, it normally pulls it from the references in the .csproj. However, if the references are not in the .csproj, because they now are in a project.json file, then they don't get pulled to the vsix. The solution then may compile, but then the extension fails with "file not found" errors when installed into Visual Studio (since the assemblies where not copied to the VSIX).
I tried with the section of the manifest like so:
<Asset Type="Microsoft.VisualStudio.Assembly" d:Source="Project" d:ProjectName="*PROJECTNAME*" Path="|*ASSEMBLYNAME*|" AssemblyName="|*ASSEMBLYNAME*;AssemblyName|" />
But it does not work, as it does not recognize the package references.
After some research I saw a similar issue with a PCL, however, without an answer and not the same type of problem: MEF With Portable Class library using Microsoft Composition MEF2 throws file not found exception
In the same note, this seems like an acceptable workaround: VSIX with Project Templates and NuGet Packages however, as far as I understood, it implies using the package during the installation. Besides that, it doesn't work for our case as they need to specify the package version and we are using project.json so we can use floating versions (ie: 2.0.*)
Is there a way to reference this project.json references that we are missing? Maybe a workaround? The solutions I have found seem to all require to "paste" de DLL somewhere, which for floating versions is not that convenient.
Thanks in advance for any help or input.
Edit/Update: Since VSIX automatically pushes any assembly referenced in the CSPROJ (and not the project itself), trying to get the DLLs at a project level seems unlikely. After many tries, I think that a valid workaround would be to get the assemblies from the Output Folder. However, to my knowledge, VSIX does not have a way of doing this, or does it?
I'm not sure I'm understanding your question correctly, but if you're trying to install a Project Template via a VSIX and you want the project template to include all it's nuget packages when you use it you could do something like this.
Edit your Project Template's xproj file and add the following lines:
<ItemGroup>
<None Include="project.json"/>
<None Include="project.lock.json"/>
</ItemGroup>
Edit your Project Template's vstemplate file and add the following lines in the Project node:
<ProjectItem ReplaceParameters="true" TargetFileName="project.json">project.json</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="project.lock.json">project.lock.json</ProjectItem>
That should be all you need to do. Now when you install the project template, then create a new project using that template it should include all the nuget packages that were in the project.json file.

Categories

Resources