I'm in the process of porting a Asp.Net Core Website targeting the full framework to a website that targets Asp.Net Core 3.
In that process I have hit a snag. The website references the Newtonsoft 11.0.3 NuGet package and among other things uses the Newtonsoft.Json.Serialization.DynamicValueProvider class.
Interestingly that class exists when targeting the full framework but does not exist when targeting netcoreapp3.1 and so Visual Studio is producing compilation errors stating that the class doesn't exist. At first that seemed crazy to me, but I checked the source code for the class and sure enough it contains the following conditional compilation statement wrapped around the whole class
#if HAVE_REFLECTION_EMIT
Apparently the netStandard 2.0 dll in the NuGet package that my netcoreapp3.1 project would use causes the conditional compilation statement to not include the DynamicValueProvider class.
So I did some poking around in the Newtonsoft.Json.Serialization namespace and I see that there is a ReflectionValueProvider class available that does not contain such conditional compilation and is available when targeting netcoreapp3.1
I've looked at the source code for both the DynamicValueProvider class and the ReflectionValueProvider class and I'm unclear on the difference. Both appear to get or set the value of a property or member type based on the MemberInfo passed in into the constructor. Both appear to use reflection to accomplish their work. As I mentioned, apparently DynamicValueProvider needs reflection Emit ability and ReflectionValueProvider does not. Emit ability apparently is used to Emit IL as best I can tell.
So I wonder if perhaps the two are drop in replacements for each other except that maybe DynamicValueProvider might be faster since it apparently leverages IL Emitting. But that's just a hunch. I'd prefer to have a more concrete understanding of the differences between the two classes before I start swapping the one for the other in this existing codebase as a way to get to .Net Core 3.
Can you provide me with better insight into the differences between the DynamicValueProvider
class and the ReflectionValueProvider class, or at least confirm my hunch?
We had updated Newtonsoft.Json from 9.* to 12.0.3 version, and observed performance degradation on paths that includes json serialization. All paths lead to DynamicValueProvider. Fortunately, we had global descendant for DefaultContractResolver, and I was able to overload CreateMemberValueProvider method to return ReflectionValueProvider.
For now we are continue testing the new version, but I can say that from performance perspective ReflectionValueProvider works faster than DynamicValueProvider.
I think there is a correlation with the fact that NetStandard 2.0 is also used to build Xamarin.Forms applications for iOS which require an AOT compilation.
As written here:
Limitations of Xamarin.iOS
"Since applications using Xamarin.iOS are compiled to static code, it is not possible to use any facilities that require code generation at runtime."
and
"No Dynamic Code Generation.
The System.Reflection.Emit is not available"
For example, this is a System.Text.Json limitation that actually cannot be used in Xamarin.Forms projects for iOS. More info here.
System.Text.Json Serializer does not appear to work on Xamarin iOS
Related
Apologies if this sounds like a silly question. I'm not very experienced with how things are linked/bundled/assembled under the hood.
Before I begin, I'd like to say that I've tried reading documentation (such as https://learn.microsoft.com/en-us/xamarin/cross-platform/app-fundamentals/code-sharing) to find the answer, but was unable to.
If I have a Xamarin.Forms solution and I reference a .Net Standard project:
Question 1: Does all the code from this project get compiled and included into the app such that it may be disassembled later, or is it only code from classes that I actually make use of that gets included?
Bit more elaboration:
For example, I may have a School class that expects an IStudent (inject via DI), and a Student class that implements IStudent. Both of these exist in the .Net Standard project that I reference in the Xamarin.Forms project. However, if I only actually make use of the Student class (by registering it with type IStudent in my IoC container), will the code from School get included in the built app as well?
Question 2: If all the code from the project does get included, is there a way to forcefully specify which classes to include/exclude by way of some configuration setting, attributes, 3rd-party library, or something else?
As far as i know everything in the NETStandard project get compiled and shipped with the app.
If you want to remove unused code from compiled assemblies you have to use the linker.
To link everything, you have to select "Sdk and User Assemblies".
The linker tries to dont strip away mthods and fields you are using, but often is too aggressive (for example, methods referenced only by reflection will be stripped).
Luckily there are few methods where you can fine-tune the linker behaviour and make it work. Some link to elaborate on:
Linker in iOS and Android
https://learn.microsoft.com/en-us/xamarin/ios/deploy-test/linker
https://learn.microsoft.com/en-us/xamarin/android/deploy-test/linker
Official doc about the linker config:
https://learn.microsoft.com/en-us/xamarin/cross-platform/deploy-test/linker
Useful blogposts:
https://xamarinhelp.com/xamarin-linker/
https://medium.com/#harrycblum/reduce-your-xamarin-app-size-with-linking-26247edc87f6
I've got two questions here. The first one is just specific and another one is more general, but is a source of the first one.
So, my specific problem: I want to use Encryption (actually, Hashing) algorithms with using System.Security.Cryptography namespace (for instance, SHA256Managed class).
I found out that (happily) Xamarin has implemented those in System.dll.
But it is not portable and obviously can not be used from Core application directly.
But I've also found another great project -- PclContrib -- which allows you to do that. But, unfortunately, they don't have the implementation for Touch and Android. (However, that still works great for Desktop (Web) and Windows Phone, plus, still can be included into Core (as it uses portable project)).
Anyway, to solve that nicely, I've decided to create some base class for the encryption methods and then override core methods which require the custom dll (for any custom system).
The way I did it (at least, trying to do) was:
Defining virtual method in Core App base class:
public virtual IEncryptionProvider CreateEncryptionProvider()
Overriding Core App class in Touch project with overriding CreateEncryptionProvider (which creates an instance of TouchEncryptionProvider class instance).
Core:
public class App : MvxApplication
Touch:
public class AppTouch : App
Launching it in Touch setup.cs:
protected override Cirrious.MvvmCross.ViewModels.IMvxApplication CreateApp (
{
return new AppTouch();
}
But, that does not work for me. On startup I've got this exception message in log:
"Exception masked KeyNotFoundException: Could not find view for Mynamespace.Etc.LoginViewModel", which works fine when I do new App() instead. I am not sure if that message shows actual problem (as before it was saying the same even that was a problem with some third-party dll, unrelated to views at all). But speaking shortly, that's just a primitive inheritance of App : MvxApplication, but placed not in Core but Touch project.
So, does it requeire some more custom initialization for such situations or do I miss something else?
And, actually, more general question is how should I build such Multiplatform approaches? Actually, now I've got similar problem with HttpUtility.UrlEncode, which I would want to use in my Core project.
What is the MvvmCross "philosophy" to handle such situations?
Thank you.
For the 'viewmodel not found' problem, this is caused because mvvmcross by default only looks for viewmodels in the Assembly containing your app.
If you want it to look in other assemblies, override ViewModelAssemblies in Setup.cs - see how this done in, for example, MvvmCross - structuring shared View Models and Views
For general multplatform approach, please read questions and answers like:
Platform-specific IoC in MVVMCross
Instantiation of ViewModels and Service classes
Please also remember you don't have to use PCLs - if you prefer to use file-linking between multiple platform-specific core projects, then you can of course use this approach.
Finally, please also try to ask one question per question - I find it makes stackoverflow work better for users and with search engines too. If you need to link questions, then you can just add a hyperlink reference - stackoverflow then marks them as related.
I understand C# Code Fragments and .NET Assemblies offer the same functionality for modular template development. We manage the code fragments in the CME and assembly code in Visual Studio, but use both the same way in Template Builder.
In terms of code, I can create a C# Code Fragment Template Building Block (TBB), for example:
var timeStamp = DateTime.Now.ToString("d MMM yyyy");
package.PushItem("timeStamp from fragment", package.CreateHtmlItem(timeStamp));
I can also create a .NET assembly Template Building Block using the same code by implementing ITemplate as below.
using System;
using Tridion.ContentManager.Templating;
using Tridion.ContentManager.Templating.Assembly;
namespace CreateAndBreakTemplates
{
[TcmTemplateTitle("Add Date to Package")]
public class AddDateToPackage : ITemplate
{
public void Transform(Engine engine, Package package)
{
var timeStamp = DateTime.Now.ToString("d MMM yyyy");
package.PushItem("timeStamp from assembly",
package.CreateHtmlItem(timeStamp));
}
}
}
The docs explain that "SDL Tridion inserts the code fragment in its predefined method of a predefined class." It looks like this class implements ITemplate and adds some references below (am I missing anything?).
The assembly setup instructions mention at least these dlls.
Tridion.Common.dll
Tridion.ContentManager.dll
Tridion.ContentManager.Templating.dll
Tridion.ContentManager.Publishing.dll
Any other difference between fragment and assembly and how would you choose between the two?
A C# fragment is compiled into an assembly by Tridion when the template is first invoked and after it's been modified. To compile the fragment, Tridion wraps it in some "dungeon dressing" (bonus points for those who know where that term comes from) that:
Uses the Tridion.ContentManager, Tridion.ContentManager.CommunicationManagement, Tridion.ContentManager.ContentManagement and Tridion.ContentManager.Templating namespaces
Makes the Package and Engine available in fields called package and engine respectively
Creates a logger for the C# fragment that is available through a field called log
Adds references to some commonly used assemblies (but does not add a using for their namespaces yet)
Edit: given the other answers it seems many people are not aware of how to accomplish certain tasks in C# fragment TBBs, so I'll document them below:
Import additional namespaces
To import/use additional namespaces into your C# fragment, you need to use this syntax:
<%# Import Namespace="Tridion.ContentManager.ContentManagement.Fields" %>
Note that this will only import namespaces from assemblies that are already referenced by Tridion. There is no mechanism for you to add references to other assemblies explicitly; so if you need a third-party DLL, you will need to add it to the GAC.
Defining custom functions
You can define custom fields and functions in your C# fragment by using this syntax:
<%!
public static string GetDate()
{
return new DateTime().ToString("u").Replace(" ", "T");
}
%>
Defining member fields and (nested) classes
The syntax for defining custom functions also allows you to define nested classes and/or member fields:
<%!
public class MyLittleHelper
{
public MyLittleHelper(string param1)
{
}
}
%>
Frank has explained the difference between the two approaches, but that still leaves the question of how to choose between the two. My personal advise is to never use C# fragments for anything, with only one exception*. As you have found out, there is some dark magic going on in them that I personally do not like. Also, there is so much you cannot do in them that a .NET programmer is quite fond of, such as creating classes.
Putting my personal taste aside, I see only one reason why you would ever resort to C# fragments: if you do not have access to Visual Studio or another tool that builds DLLs. And that is not a very strong argument either: if you want a job done, you should get the proper tools!
*The exception being the C# fragments that Tridion automatically creates for each ITemplate in your assembly, of course.
The main differences between C# code Fragment and .net Assemblies in my point of view are categorized into below high level buckets.
Step-by-Step Debugging
With .net assemblies you could do step-by-step debugging from visual studio where as C# Code fragments it is not possible.
Re-Use or Base Classes
With .net assemblies you could extend ITemplate to create something like BaseTemplate and all your template could extend them so you have common design pattern, where as C# there is no concept of BaseTemplate other than Tridion ITemplate interface.
With .net assemblies you could add common utility classes (often TridionUtilities) and all your templates refer to the same TridionUtilities for common functionality. C# code fragment the utility functions need to be defined within the same TBB and cannot be reused with other TBBs unless you create a class and deploy to GAC.
Easier Upgrade Scans and Maintenance
With .net assemblies it is easier to do any upgrade scans like deprecated APIs/Methods simply referring to new dlls/.net framework. .net assemblies make it easy to identify potential impacts on planning either Tridion upgrades or .net framework upgrades. C# code fragments it is much harder to find the deprecated or any impacts of upgrade.
Developer Friendly
Obviously .net assemblies are developed using Visual Studio (developers love it!) vs. C# Code Fragments in a Text Editor (painful).
When I started back with Tridion 5.3, started with C# code fragments and quickly realized what a mistake I made for not going .net assemblies.
My vote is always .net assemblies and C# code fragments is not even in consideration unless I don't have a choice. lol..
I think the differences indeed are best explained by Frank's answer, as to how would you choose between the two. I normally say, since you are using Visual Studio anyways, always create a .NET Assembly TBB for your code. They offer you a lot more benefits like including 3rd party assemblies, allow for proper coding with classes and methods a lot easier and probably most important, allow for proper debugging (although this last one can be hard to setup depending on where you are, thinking of customer environments, firewalls etc.).
There are for me only two exceptions for using C# Fragments:
The references to classes implementing ITemplate in an assembly, allowing you to use these as separate TBBs
If there is a requirement to manage constants or other hardcoded constants directly from SDL Tridion
Number 2 is of course debatable, but you never can do without configuration properties, for a TBB most of these you can handle using a Parameters Schema, but sometimes it is just a lot easier, to directly write them in a C# Fragment and have that push them to the package for other TBBs to use.
In my training sessions, I usually referred to the following story of the only time I ever choose to use a C# Fragment TBB so far, indicating how much of an exception it is to use them:
I was working at a customer abroad, and my taxi for the airport was leaving in 10 minutes when one of the developers I was coaching asked me a question on how to get a list of items from a Folder in his TBB. I had already closed my Visual Studio and Outlook and was about to shutdown my laptop, but quickly browsed through some of my code samples to find what he needed. Knowing that starting up Visual Studio or Outlook would take a few minutes, I quickly pasted the code in a C# Fragment so he had it for easy reference.
I would never use C# fragments for the sole reason that it makes management of your code quite difficult and you need to manually deploy them. And if you do write your code from Visual Studio, then you should create a .NET Building Block assembly.
I am developing DotNetNuke modules and naturally want them compiled before installing or distributing them. In the past I've simply referenced a specific version of DotNetNuke.dll by browsing to the /BIN folder of a local DotNetNuke installation.
This reference allowed me to use the DNN base classes and create my own set of classes upon those. I also use various helper methods throughout the DNN namespaces/classes that I require. (i.e. Make derived classes from their PortalModuleBase, ModuleSettingsBase and use their Localization classes which replace those provided by Microsoft's ASP.NET implementation.)
I've been able to get away with this approach making that direct DLL reference (Copy Local = True, Specific Version = False) because until now I've been installing these modules onto client websites that I maintain. As such, I've kept them on at least the version of DotNetNuke I've been developing on - or newer. Most recently, I was referencing 6.1.3.108 in development.
NOTE: This automatically copies in the following associated DLLs into the /BIN directory of my modules:
DotNetNuke.dll
DotNetNuke.Instrumentation.dll
dotnetnuke.log4net.dll
DotNetNuke.Services.Syndication.dll
DotNetNuke.Web.Client.dll
DotNetNuke.WebControls.dll
DotNetNuke.WebUtility.dll
Installing this onto a DotNetNuke site of a NEWER version worked fine, which isn't a bad start.
What I've been wondering though, is if there is a non-hackish way of making my modules insensitive to the minor, build or revision levels of the DLL?
I realize that it makes it my responsibility to ensure the product (if developed on a "mid range" version) still works on slightly earlier as well as newer versions of the product. That said, I feel I can do thorough testing across those builds. To me this is preferential to having to run the OLDEST major build in development.
Put another way, I'd rather not develop with references to 6.0.0.0 just so it works on 6.x.x.x without extra effort. I'll only do that if someone doesn't have a brilliant way for me to make referencing say, 6.1.3.108 working on slightly earlier or later versions. (Naturally I'm okay with having to make a different module for major version changes, such as 5.x.x.x or 7.x.x.x.)
Thanks in advance!
Instead of referencing the assemblies in the bin folder, keep a copy of DotNetNuke.dll (and any other references) with your source code, and reference it there. Put the oldest supported version there, but develop on a newer site. Set Copy Local=False on the reference so you don't overwrite the newer version, and you should be fine.
In this way, we're able to reference DNN 4.5.3 while developing a module that runs on DNN 6.1.x. I've been using this method for years without any significant problems (except when I occasionally forget to turn off Copy Local and my DNN site mysteriously blows up).
In regards to determining the version of DNN in a class you've subclassed from a DNN one.
Here's what I would do, assuming YourClass inherits from DNNClass, but because you have referenced an earlier version of a property, 'NewProp' doesn't exist. Here's how to do it:
public class YourClass : DNNClass
{
public string NewPropSubstitute
{
get {
string newPropVal = "your default if earlier DNN";
System.Reflection.PropertyInfo pi = this.GetType().GetProperty("NewProp");
if (pi != null)
newPropVal = (string)pi.GetValue(this, null);
return newPropVal;
}
}
}
That's a made-from-memory guess so it might not compile, but you get the idea. You don't necessarily have to get the DNN Version if you want - just try and get the property through reflection - if it's there, implicitly you've got the right version.
Of course this method assumes you can substitute in a value for a later-DNN property (or method) if the DNN version doesn't support it. But that all depends on what you're trying to do.
If you do want to find the DNN Version (version safe and always correct) you can use the code for that which is embedded in my version-safe jQuery inclusion code, linked from this blog post:
Using jQuery in DotNetNuke 5 and 6
I have a previous project running Ninject 2.0 runtime version 2.0 and now I am using Ninject in a new project and using the new Ninject, ninject web.mvc version 2.2 for runtime version 4.0.
Every single time I get the error no parameterless constructor
Invalid Operation exception
An error occurred when trying to create a controller of type HomeController'. Make sure that the controller has a parameterless public constructor.
What am I missing. All the bindings are registered.
Do I need to now define interfaces for Controllers as well such as HomeController as IHomeController as I have seen in some examples, Or do I get back to using the older version
There is one version that does not show activation exceptions properly but show this exception instead. Most likely the problem is a duplicated binding.
In addition to what Remo Gloor said, you might want to check that MVC is set up to use Ninject correctly. I was doing some things manually on an older version of the MVC plugin and ended up needing to just bite the bullet and make Global extend the NinjectHttpApplication class, which I had previously been avoiding.
The error you're getting is the error you would get if MVC tries using its built-in controller factory to produce controllers. So you may want to create a custom method binding on your controller class and put a breakpoint inside to make sure it's even being invoked.
You may also want to switch to version 2.3. You can pick up the latest builds of Ninject and all its extensions here.
I have seen this issue mentioned couple of times on forums where there is no direct answer, here is the solution to the above problem, i.e., working with latest ninject
Download the latest Ninject from github.
The ninject I got for MVC2 is named as Ninject.Web.Mvc2-2.2.0.0-release-net-4.0 (runtime version 4)
Now during adding reference add Ninject.Web.Mvc.dll(check the version is same as above by right click properties in VS)
Now Add Ninject.dll from the lib folder in same parent folder (check the version as above)
Now Add CommonServiceLocator.NinjectAdapter.dll from the extensions folder in lib parent folder (check the version as above.)
The missing link in all these have been the commonserviceLocator.dll and the correct version should match. This should be tried if you are sure your bindings are correct as mine were and check to see if your project work with older version.
Thanks to everyone, and good luck :)