MethodAccessException when calling nlog LogManager.GetCurrentClassLogger() - nlog

I'm getting an exception when I run a unit test on a controller in web project (ASP.NET web api). The exception is thrown when LogManager.GetCurrentClassLogger() of the controller is executed:
System.MethodAccessException: Attempt by method 'Castle.Proxies.ClaimsPrincipalProxy.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' to access method 'Castle.DynamicProxy.Internal.TypeUtil.Sort(System.Reflection.MemberInfo[])' failed
It results in TypeInitializationException in LogManager.GetCurrentClassLogger().
here is the call stack:
at Castle.Proxies.ClaimsPrincipalProxy.GetObjectData(SerializationInfo, StreamingContext)
at System.Runtime.Serialization.ObjectCloneHelper.GetObjectData(Object serObj, String& typeName, String& assemName, String[]& fieldNames, Object[]& fieldValues)
at System.AppDomain.get_Evidence()
at System.AppDomain.get_Evidence()
at System.Configuration.ClientConfigPaths.GetEvidenceInfo(AppDomain appDomain, String exePath, ref String typeName)
at System.Configuration.ClientConfigPaths.GetTypeAndHashSuffix(AppDomain appDomain, String exePath)
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.RequireCompleteInit(IInternalConfigRecord record)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, ref Object result, ref Object resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at NLog.Config.XmlLoggingConfiguration.get_AppConfig()
at NLog.LogFactory.get_Configuration()
at NLog.LogFactory.GetLogger(LoggerCacheKey cacheKey)
at NLog.LogFactory.GetLogger(String name)
at NLog.LogManager.GetCurrentClassLogger()
Update:
The issue happens when the unit test project references NSubstitute. So, it seems like there some dangerous combination of Web API, NSubstitute and NLog.
Update 2:
Found what upsets Nlog in Controller.
Before calling controller method I set mocked principal for Thread.CurrentPrincipal:
var principal = Substitute.For<ClaimsPrincipal>();
principal.Identity.Returns(...);
Thread.CurrentPrincipal = principal;
How could this be fixed?

The Castle assembly may be marked with the AllowPartiallyTrustedCallersAttribute, and that uses the level 2 security transparency model.
Level 2 transparency causes all methods in AllowPartiallyTrustedCallers assemblies to become security transparent by default, which may be the cause of this exception.
Can you try annotating your unit test (and Class) with the following attribute - [SecuritySafeCritical]

Related

Why adding business controller class namespace in DNN makes module disappear?

I am trying to make a module searchable i DNN 9 so I created a class which implements ISearchable and overrides GetSearchItems.
following this documentation:
https://www.dnnsoftware.com/wiki/isearchable
public SearchItemInfoCollection GetSearchItems(ModuleInfo ModInfo)
{
SearchItemInfoCollection SearchItemCollection = new SearchItemInfoCollection();
ArrayList Documents = GetDocuments(ModInfo.ModuleID, ModInfo.PortalID, true);
foreach (var objDocument in Documents)
{
SearchItemInfo SearchItem;
{
var withBlock = (DocumentInfo)objDocument;
int UserId = Null.NullInteger;
// If IsNumeric(.CreatedByUser) Then
// UserId = Integer.Parse(.CreatedByUser)
// End If
UserId = withBlock.CreatedByUserID;
SearchItem = new SearchItemInfo(ModInfo.ModuleTitle + " - " + withBlock.Title, withBlock.Title, UserId, withBlock.CreatedDate, ModInfo.ModuleID, withBlock.ItemId.ToString(), withBlock.Title + " " + withBlock.Category, "ItemId=" + withBlock.ItemId.ToString());
SearchItemCollection.Add(SearchItem);
}
}
return SearchItemCollection;
}
But when I add the namespace of the class in the module manifest, the module disappears from the page (and indexing doesn't work).
The namespace of the class is ProjectName.ListaNews.ListaController
I have also tried ProjectName.ListaNews and changing it to DotNetNuke.Modules.ProjectName.ListaNews.ListaController
I have tried changing the business class controller both from module settings and from .dnn file.
Why adding business class namespace breaks my module and makes it disappear from the page?
-------------- EDIT ----------------
The business controller class name seems to be correct.
I checked the log file and found this error:
DotNetNuke.Framework.Reflection - ProjectName.ListaNews.ListaController, ProjectName.ListaNews
System.IO.FileNotFoundException: Could not load file or assembly 'ProjectName.ListaNews' or one of its dependencies.
Cannot find specified file.
File name: 'ProjectName.ListaNews'
in bin\ folder there is ListaNews.dll. I tried renaming it into ProjectName.ListaNews.dll but I had the same error (+ the site crash).
So I changed the business controller class to ListaNews.ListaController, ListaNews without ProjectName and it gave a new error:
DotNetNuke.Framework.Reflection - ListaNews.ListaController, ListaNews
System.TypeLoadException: Could not load type 'ListaNews.ListaController' from assembly 'ListaNews'.
Looks like it didn't find ListaController class.
I noticed ListaController.cs was not defined in .dnn file when I installed it.
I added this to the .dnn file
<component type="File">
other files definitions....
<files>
<file>
<name>ListaController.cs</name>
</file>
</files>
</component>
So I deleted and re-installed my module. Nothing changed though.
Does that give any hint?
Thanks
-------------- EDIT 2 ----------------
Since it was a namespace error I moved the controller class from ListaController.cs to View.ascx.cs and the previous error disappeared, so the class is probably visible now. But the module is still not visible (crashes) so i checked the log and it gave 2 very similiar errors:
1)
Message: Value cannot be null. Parameter name: type
StackTrace: in System.Activator.CreateInstance(Type type, Boolean nonPublic)
in System.Activator.CreateInstance(Type type)
in DotNetNuke.UI.Skins.Pane.IsVesionableModule(ModuleInfo moduleInfo)
in DotNetNuke.UI.Skins.Pane.InjectModule(ModuleInfo module)
in DotNetNuke.UI.Skins.Skin.InjectModule(Pane pane, ModuleInfo module)
InnerMessage: Value cannot be null. Parameter name: type
InnerStackTrace: at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Activator.CreateInstance(Type type)
at DotNetNuke.Services.Search.ModuleIndexer.GetModuleList(Int32 portalId)
I read System.Activator.CreateInstance documentation here:
https://learn.microsoft.com/it-it/dotnet/api/system.activator.createinstance?view=netcore-3.1#System_Activator_CreateInstance_System_Type_System_Boolean_
and actually CreateInstance has a constructor with type parameter,
But I think it is called in DNN compiled libraries and I can't see what is going on
I added this line in constructor
object instance = Activator.CreateInstance(typeof(ListaController));
and it logged this error:
Error Creating BusinessControllerClass
'ProjectName.ListaNews.ListaController, ProjectName.ListaNews' of
module(ProjectName.ListaNews) id=(577) in tab(45) and portal(0)
StackTrace:
at DotNetNuke.Services.Search.ModuleIndexer.ThrowLogError(ModuleInfo module,
Exception ex)
InnerMessage:Value cannot be null. Parameter name: type
InnerStackTrace:
at System.Activator.CreateInstance(Type type, Boolean nonPublic) at
system.Activator.CreateInstance(Type type) at
DotNetNuke.Services.Search.ModuleIndexer.GetModuleList(Int32 portalId)
I found this forum
https://www.dnnsoftware.com/forums/threadid/495897/scope/posts/help-with-rror-in-custom-module
so I added a parameterless constructor in my controller class but it didn't change anything
Why is type null in CreateInstance?
The value for businessControllerClass in the manifest must be in the format {FQCN}, {Assembly}. This is per The manifest schema
For your project, assuming the namespace is as you mentioned ProjectName.ListaNews.ListaController your assembly name is most likely ProjectName.ListaNews which would mean the proper value for the businessControllerClass is
ProjectName.ListaNews.ListaController, ProjectName.ListaNews
If that doesn't correct it, as Chris Hammond mentioned you can use the logs to get a more detailed error

Returning mock objects with Mockito using given arguments

For my JUnit Tests with Mockito, I am doing the following:
Mockito.lenient().when(tokenService.create(String id, Any)).thenReturn(new String (id))
Mockito.lenient().when(voucherRepo.findById(id String).thenReturn(new Voucher(id));
I would like to access the String id given to tokenService.create() and voucherRepo.findById() methods, create and then return mock objects using it. How it can be done?
Mockito.when(voucherRepo.findById(id)).thenReturn(new Voucher(id));
Your solution should work and is probably the preferred solution for any clear defined test.
As you know in your test what the exact id is, you can just return the specific object for it.
Another way to do this - for arbitrary strings - is using mockito's thenAnswer funtionality:
Mockito.when(voucherRepo.findById(Mockito.any(String.class))).thenAnswer(new Answer<Voucher>() {
#Override
public Voucher answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String id = (String) args[0];
return new Voucher(id);
}
});
I am not sure what reason you have to do that in your test (as this a rather arbitrary defintion), but in doubt consider adding some more context to your question.

Providing Coded-UI support for VS2012,2013,2015

I have successfully implemented the Coded UI support for my custom control in VS2010. But when i try to upgrade those projects to VS2012, VS2013, or VS2015, the following exception has occurred. Please find the exception stack trace below:
Sample code:
if (uiTestControl.ControlType == ControlType.Table)
{
//To-Do
}
Exception:
System.InvalidCastException was unhandled
HResult=-2147467262
Message=Invalid cast from 'System.String' to 'Microsoft.VisualStudio.TestTools.UITesting.ControlType'.
Source=mscorlib
StackTrace:
at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.GetPropertyInternal[T](String propertyName)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.get_ControlType()
at CustomControl.GetPropertyNames(UITestControl uiTestControl) in d:\Coded_UI_Source\Src\CustomExtensionProvider\CustomPropertyProvider.cs:line 94
at Microsoft.VisualStudio.TestTools.UITesting.ALUtility.GetProperties(UITestPropertyProvider provider, UITestControl uiControl, UITestPropertyAttributes attributes, UITestPropertyAttributes ignoreAttributes)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.GetReadableAndAssertablePropertyNames()
at Microsoft.VisualStudio.TestTools.CodedUITest.Controls.UIControlLocator.UIControlFinder.FetchProperties(UITestControl element)
at Microsoft.VisualStudio.TestTools.CodedUITest.Controls.UIControlLocator.UIControlFinder.PopulateUITestControlDetails(UITestControl element, UIControlDetails uiControlDetails)
at Microsoft.VisualStudio.TestTools.CodedUITest.Controls.UIControlLocator.UIControlFinder.CaptureControl(UITestControl element)
at Microsoft.VisualStudio.TestTools.CodedUITest.Controls.UIControlLocator.UIControlFinder.PlaybackThreadproc()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Please help me to overcome this issue and also please let me know whether i need to do anything to support in VS2012, 2013 and 2015.
The problem occours in your code CustomPropertyProvider.cs:line 94, it is calling the get_ControlType() which is looking from control type. It seems you haven't set the control type correctly in the custom control when it tries to convert the name of the controltype into a Type.
at CustomControl.GetPropertyNames(UITestControl uiTestControl) in d:\Coded_UI_Source\Src\CustomExtensionProvider\CustomPropertyProvider.cs:line 94

How to add formatProvider parameter to NLog.LogEventInfo.Create method?

I have following NLog 2.0 code to log exceptions:
Dim theEvent = NLog.LogEventInfo.Create(NLog.LogLevel.Error, loggerName, message, ex)
After upgrading to NLog 4.1 I see following warning:
Function Create(logLevel As LogLevel, loggerName As String, message As String, exception As Exception) As LogEventInfo' is obsolete: 'use Create(LogLevel logLevel, string loggerName, Exception exception, IFormatProvider formatProvider, string message)'
... it asks me to add IFormatProvider formatProvider as parameter. What should I add there?
Dim theEvent = NLog.LogEventInfo.Create(NLog.LogLevel.Error, loggerName, ex, ???, message)
You can safely use null, one from the System.Globalization.CultureInfo members (a good guide can be found here) or create your own custom format provider depending on your needs.
The current implementation (as of v.4.1.2 on GitHub) will simply use CultureInfo.CurrentCulture if the FormatProvider property is null.

Liferay - Hook for GroupWrapper

I'm trying to override the getDescriptiveName() method in com.liferay.portal.model.Group
I found a wrapper (com.liferay.portal.model.GroupWrapper), so I tried to write a hook as written in the documentation :
liferay-hook.xml:
<service>
<service-type>com.liferay.portal.model.GroupWrapper</service-type>
<service-impl>fr.villedeniort.hook.expando.GroupWrapperImpl</service-impl>
</service>
fr.villedeniort.hook.expando.GroupWrapperImpl.java:
public class GroupWrapperImpl extends GroupWrapper {
public GroupWrapperImpl(Group group) {
super(group);
}
#Override
public java.lang.String getDescriptiveName()
throws com.liferay.portal.kernel.exception.PortalException,
com.liferay.portal.kernel.exception.SystemException {
return super.getDescriptiveName();
}
When the hook is deployed, it raises an exception :
java.lang.NoSuchMethodException: fr.villedeniort.hook.expando.GroupWrapperImpl.<init>(com.liferay.portal.model.GroupWrapper)
I browse the code I found out that it breaks at this part for a reason I ignore:
Constructor<?> serviceImplConstructor = serviceImplClass.getConstructor(new Class<?>[] {serviceTypeClass});
At this point, variables have theses values:
serviceType "com.liferay.portal.model.GroupWrapper" (id=14829)
serviceImpl "fr.villedeniort.hook.expando.GroupWrapperImpl" (id=14830)
serviceTypeClass Class<T> (com.liferay.portal.model.GroupWrapper) (id=14831)
serviceImplClass Class<T> (fr.villedeniort.hook.expando.GroupWrapperImpl) (id=14832)
Do you have any idea?
Thanks!
You should have also a constructor without any argument. Now you have one with constuctor arguments, but there is no pure class constructor that java searches when it makes class instance. After calling the pure constructor java then calls the argumented one.
I had similar case in some other context and this was the solution. <init> tag on the error message refers on this kind of issue.
Apparently, it's not possible to hook other classes than Services, so I had to find a different way. For my case, I hooked a JSP and wrote my own method to get the right descriptive name from the hook.

Resources