I've built an application service based on the AsyncCrudAppService class, like this:
public class ServiceTemplateAppService : AsyncCrudAppService<ServiceTemplate, ServiceTemplateDto, int, PagedAndSortedResultRequestDto, CreateServiceTemplateDto, UpdateServiceTemplateDto>, IServiceTemplateAppService
Everything works as intended, but once in a while I get an error when calling the GetAll method and passing in a sorting parameter, like this:
api/services/app/CostCenter/GetAll?SkipCount=0&MaxResultCount=10&Sorting=displayName%20asc
I have overridden the CreateFilteredQuery method and it now looks like this because I want to get some child entities.
protected override IQueryable<ServiceTemplate> CreateFilteredQuery(PagedAndSortedResultRequestDto input)
{
return Repository.GetAll()
.Include(x => x.ServiceTemplateRole)
.ThenInclude(y => y.Role)
.Include(x => x.ServiceTemplateImage)
.Include(x => x.ServiceTemplateCategory);
}
The error message that I get is this one:
INFO 2018-11-16 13:45:02,101 [21 ] ore.Mvc.Internal.ControllerActionInvoker - Route matched with {area = "app", action = "GetAll", controller = "ServiceTemplate"}. Executing action dsim.Services.ServiceTemplateAppService.GetAll (dsim.Application)
INFO 2018-11-16 13:45:02,104 [21 ] ore.Mvc.Internal.ControllerActionInvoker - Executing action method dsim.Services.ServiceTemplateAppService.GetAll (dsim.Application) with arguments (Abp.Application.Services.Dto.PagedAndSortedResultRequestDto) - Validation state: Valid
ERROR 2018-11-16 13:45:02,189 [24 ] Mvc.ExceptionHandling.AbpExceptionFilter - Could not load type 'System.ComponentModel.DataAnnotations.BindableTypeAttribute' from assembly 'System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
System.TypeLoadException: Could not load type 'System.ComponentModel.DataAnnotations.BindableTypeAttribute' from assembly 'System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
at System.ModuleHandle.ResolveType(RuntimeModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
at System.ModuleHandle.ResolveTypeHandleInternal(RuntimeModule module, Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(CustomAttributeRecord caRecord, MetadataImport scope, Assembly& lastAptcaOkAssembly, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, Object[] attributes, IList derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctor, Boolean& ctorHasParameters, Boolean& isVarArg)
at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes)
at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit)
at System.Linq.Dynamic.Core.CustomTypeProviders.AbstractDynamicLinqCustomTypeProvider.<>c.<FindTypesMarkedWithDynamicLinqTypeAttribute>b__0_1(Type x)
at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
at System.Collections.Generic.HashSet`1.UnionWith(IEnumerable`1 other)
at System.Collections.Generic.HashSet`1..ctor(IEnumerable`1 collection, IEqualityComparer`1 comparer)
at System.Linq.Dynamic.Core.CustomTypeProviders.DefaultDynamicLinqCustomTypeProvider.GetCustomTypes()
at System.Linq.Dynamic.Core.Parser.KeywordsHelper..ctor(ParsingConfig config)
at System.Linq.Dynamic.Core.Parser.ExpressionParser..ctor(ParameterExpression[] parameters, String expression, Object[] values, ParsingConfig parsingConfig)
at System.Linq.Dynamic.Core.DynamicQueryableExtensions.OrderBy(IQueryable source, ParsingConfig config, String ordering, Object[] args)
at System.Linq.Dynamic.Core.DynamicQueryableExtensions.OrderBy[TSource](IQueryable`1 source, ParsingConfig config, String ordering, Object[] args)
at System.Linq.Dynamic.Core.DynamicQueryableExtensions.OrderBy[TSource](IQueryable`1 source, String ordering, Object[] args)
at Castle.Proxies.Invocations.CrudAppServiceBase`6_ApplySorting_3.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Abp.Domain.Uow.UnitOfWorkInterceptor.PerformSyncUow(IInvocation invocation, UnitOfWorkOptions options)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.ServiceTemplateAppServiceProxy.ApplySorting(IQueryable`1 query, PagedAndSortedResultRequestDto input)
at Abp.Application.Services.AsyncCrudAppService`8.GetAll(TGetAllInput input)
at Abp.Threading.InternalAsyncHelper.AwaitTaskWithPostActionAndFinallyAndGetResult[T](Task`1 actualReturnValue, Func`1 postAction, Action`1 finalAction)
at lambda_method(Closure , Object )
at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()
I've tried to figure out what could cause the problem and adding the assembly that the exceptions tells me, but no progress. The strange thing is that this sometimes work, so my guess is that is has something to do with the actual data in the DB, but hey?! I don't know...
GetAll Method From AsyncCrudAppService calls ApplySorting Method, you can override it and there sort as you want.
protected override IQueryable<YourEntity> ApplySorting(IQueryable<YourEntity> query, PagedAndSortedResultRequestDto input)
{
if (input.Sorting.IsNullOrEmpty())
{
input.Sorting = "yourColumn asc";
}
return base.ApplySorting(query, input);
}
If you want to crate another GetAll Method here is an example:
public Task<PagedResultDto<PaisDto>> GetAllFiltered(PagedAndSortedResultRequestDto input, string filter)
{
var paisList = new List<Pais>();
var query = Repository.GetAll();
query = ApplySorting(query, input);
if (filter != null && filter != string.Empty)
{
paisList = query
.Where(x => x.Identificador.StartsWith(filter) || x.Nombre.StartsWith(filter))
.Skip(input.SkipCount)
.Take(input.MaxResultCount).ToList();
var result = new PagedResultDto<PaisDto>(query.Count(), ObjectMapper.Map<List<PaisDto>>(paisList));
return Task.FromResult(result);
}
else
{
paisList = query
.Skip(input.SkipCount)
.Take(input.MaxResultCount).ToList()
.ToList();
var result = new PagedResultDto<PaisDto>(query.Count(), ObjectMapper.Map<List<PaisDto>>(paisList));
return Task.FromResult(result);
}
}
query = ApplySorting(query, input); in this line you can call base method base.ApplySorting(query, input);
I'm getting "System.NullReferenceException: Object reference not set to an instance of an object." on my release build. I have created a sample application that imitates what's there in my production code.
void Abc::LogService::Log(String^ message)
{
try
{
int ret = DoProcessing(message);
Exception^ ex;
if (ret == 0)
{
ex = gcnew ArgumentException("Processing done.");
}
else
{
ex = gcnew ArgumentNullException("message", "Null args");
}
throw ex;
}
finally
{
//do someother thing.
}
}
With the above code, it reports the exception line to be:
at Abc.LogService.Log(String message) in logservice.cpp:line 19 which corresponds to the throw ex; statement in the code.
The MSIL in the release build for this function looks as:
.method public hidebysig instance void Log(string message) cil managed
{
// Code size 46 (0x2e)
.maxstack 4
.locals ([0] class [mscorlib]System.Exception V_0,
[1] class [mscorlib]System.Exception ex)
.try
{
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call instance int32 Abc.LogService::DoProcessing(string)
IL_0007: ldnull
IL_0008: stloc.1
IL_0009: brtrue.s IL_0018
IL_000b: ldstr "Processing done."
IL_0010: newobj instance void [mscorlib]System.ArgumentException::.ctor(string)
IL_0015: stloc.0
IL_0016: br.s IL_0028
IL_0018: ldstr "message"
IL_001d: ldstr "Null args"
IL_0022: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string,
string)
IL_0027: stloc.0
IL_0028: ldloc.1
IL_0029: throw
IL_002a: leave.s IL_002d
} // end .try
finally
{
IL_002c: endfinally
} // end handler
IL_002d: ret
} // end of method LogService::Log
From the MSIL code, it shows that at statement IL_0028, it loads up a null value and calls the throw in the subsequent statement.
The strange part is this happens only if I have the try-finally block.
Debug build of the above code works fine.
Does this sound as a bug in VS2015 v140 toolkit?
Yes, this is an optimizer bug. Pretty unusual, first one I've seen for C++/CLI, a language where the jitter is supposed to do the heavy lifting. It appears to be tripped by declaring the ex variable inside the try-block, getting it to choke on the initialization guarantee. Looks like a flow analysis bug.
Short from compiling with /Od, one workaround is to move the variable out of the try block
void Log(String^ message) {
Exception^ ex;
try {
// etc...
}
Also producing much better MSIL, completely eliminating the variable:
.method public hidebysig instance void Log(string message) cil managed
{
// Code size 41 (0x29)
.maxstack 4
.try
{
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call instance int32 Test::DoProcessing(string)
IL_0007: brtrue.s IL_0015
IL_0009: ldstr "Processing done."
IL_000e: newobj instance void [mscorlib]System.ArgumentException::.ctor(string)
IL_0013: br.s IL_0024
IL_0015: ldstr "message"
IL_001a: ldstr "Null args"
IL_001f: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string,
string)
IL_0024: throw
IL_0025: leave.s IL_0028
} // end .try
finally
{
IL_0027: endfinally
} // end handler
IL_0028: ret
} // end of method Test::Log
Optimizer bugs suck, you can report it at connect.microsoft.com
I am trying to understand why this is invalid IL code and/or what would cause this fault.
The exception thrown is:
System.InvalidProgramException: Invalid IL code in
away3d.containers.View3D:updateBackBuffer (): IL_0023: brfalse
IL_00ba
I disassembled using monodis and the method that is being called (updateBackBuffer) and throwing the error follows below, but I can not spot anything wrong with the branch if false statement or the IL around it:
// method line 841
.method family virtual hidebysig newslot
instance default void updateBackBuffer () cil managed
{
// Method begins at RVA 0x1e4d4
// Code size 226 (0xe2)
.maxstack 5
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld class away3d.core.managers.Stage3DProxy away3d.containers.View3D::_stage3DProxy
IL_0007: callvirt instance class [pscorlib_monomac]flash.display3D.Context3D class away3d.core.managers.Stage3DProxy::get_context3D()
IL_000c: brfalse IL_00e1
IL_0011: ldarg.0
IL_0012: ldfld bool away3d.containers.View3D::_shareContext
IL_0017: brtrue IL_00e1
IL_001c: nop
IL_001d: ldarg.0
IL_001e: ldfld float64 away3d.containers.View3D::_width
IL_0023: brfalse IL_00ba
IL_0028: ldarg.0
IL_0029: ldfld float64 away3d.containers.View3D::_height
IL_002e: brfalse IL_00ba
IL_0033: nop
IL_0034: ldarg.0
IL_0035: ldfld class away3d.core.managers.Stage3DProxy away3d.containers.View3D::_stage3DProxy
IL_003a: callvirt instance bool class away3d.core.managers.Stage3DProxy::get_usesSoftwareRendering()
IL_003f: brfalse IL_008c
IL_0044: nop
IL_0045: ldarg.0
IL_0046: ldfld float64 away3d.containers.View3D::_width
IL_004b: ldc.r8 2048.
IL_0054: ble.un IL_0068
IL_0059: ldarg.0
IL_005a: ldc.r8 2048.
IL_0063: stfld float64 away3d.containers.View3D::_width
IL_0068: ldarg.0
IL_0069: ldfld float64 away3d.containers.View3D::_height
IL_006e: ldc.r8 2048.
IL_0077: ble.un IL_008b
IL_007c: ldarg.0
IL_007d: ldc.r8 2048.
IL_0086: stfld float64 away3d.containers.View3D::_height
IL_008b: nop
IL_008c: ldarg.0
IL_008d: ldfld class away3d.core.managers.Stage3DProxy away3d.containers.View3D::_stage3DProxy
IL_0092: ldarg.0
IL_0093: ldfld float64 away3d.containers.View3D::_width
IL_0098: conv.i4
IL_0099: ldarg.0
IL_009a: ldfld float64 away3d.containers.View3D::_height
IL_009f: conv.i4
IL_00a0: ldarg.0
IL_00a1: ldfld unsigned int32 away3d.containers.View3D::_antiAlias
IL_00a6: conv.i4
IL_00a7: ldc.i4.1
IL_00a8: callvirt instance void class away3d.core.managers.Stage3DProxy::configureBackBuffer(int32, int32, int32, bool)
IL_00ad: ldarg.0
IL_00ae: ldc.i4.0
IL_00af: stfld bool away3d.containers.View3D::_backBufferInvalid
IL_00b4: nop
IL_00b5: br IL_00e0
IL_00ba: nop
IL_00bb: ldarg.0
IL_00bc: ldarg.0
IL_00bd: callvirt instance class [pscorlib_monomac]flash.display.Stage class [pscorlib_monomac]flash.display.DisplayObject::get_stage()
IL_00c2: callvirt instance int32 class [pscorlib_monomac]flash.display.Stage::get_stageWidth()
IL_00c7: conv.r8
IL_00c8: callvirt instance void class [pscorlib_monomac]flash.display.DisplayObject::set_width(float64)
IL_00cd: ldarg.0
IL_00ce: ldarg.0
IL_00cf: callvirt instance class [pscorlib_monomac]flash.display.Stage class [pscorlib_monomac]flash.display.DisplayObject::get_stage()
IL_00d4: callvirt instance int32 class [pscorlib_monomac]flash.display.Stage::get_stageHeight()
IL_00d9: conv.r8
IL_00da: callvirt instance void class [pscorlib_monomac]flash.display.DisplayObject::set_height(float64)
IL_00df: nop
IL_00e0: nop
IL_00e1: ret
} // end of method View3D::updateBackBuffer
Maybe it's because loaded value at that place is not boolean?
This code behaves differently in VB12 vs VB14.
How can we force the vb compiler to keep the old behavior? The new behavior throws an unhandled excetion because of the new call to Microsoft.VisualBasic.CompilerServices.Conversions::ToDate(string) in the VB14 IL version.
Exception
Unhandled Exception: System.InvalidCastException: Conversion from string "" to type 'Date' is not valid.
at Microsoft.VisualBasic.CompilerServices.Conversions.ToDate(String Value)
at VBConsoleApplication1.Module1.Main() in c:\Module1.vb:line 7
Source Code
Module Module1
Sub Main()
Dim dt As New DateTime
dt = vbNullString
Console.WriteLine(dt)
Console.WriteLine("Any Key")
Console.ReadKey(False)
End Sub
End Module
VB12 IL
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 49 (0x31)
.maxstack 1
.locals init ([0] valuetype [mscorlib]System.DateTime dt,
[1] valuetype [mscorlib]System.DateTime VB$t_date$N0)
IL_0000: nop
IL_0001: ldloca.s dt
IL_0003: initobj [mscorlib]System.DateTime
IL_0009: ldloca.s dt
IL_000b: initobj [mscorlib]System.DateTime
IL_0011: ldloc.0
IL_0012: box [mscorlib]System.DateTime
IL_0017: call void [mscorlib]System.Console::WriteLine(object)
IL_001c: nop
IL_001d: ldstr "Any Key"
IL_0022: call void [mscorlib]System.Console::WriteLine(string)
IL_0027: nop
IL_0028: ldc.i4.0
IL_0029: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey(bool)
IL_002e: pop
IL_002f: nop
IL_0030: ret
} // end of method Module1::Main
VB14 IL
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 47 (0x2f)
.maxstack 1
.locals init ([0] valuetype [mscorlib]System.DateTime dt)
IL_0000: nop
IL_0001: ldloca.s dt
IL_0003: initobj [mscorlib]System.DateTime
IL_0009: ldnull
IL_000a: call valuetype [mscorlib]System.DateTime [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToDate(string)
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: box [mscorlib]System.DateTime
IL_0016: call void [mscorlib]System.Console::WriteLine(object)
IL_001b: nop
IL_001c: ldstr "Any Key"
IL_0021: call void [mscorlib]System.Console::WriteLine(string)
IL_0026: nop
IL_0027: ldc.i4.0
IL_0028: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey(bool)
IL_002d: pop
IL_002e: ret
} // end of method Module1::Main
I'm an absolute beginner, you see. Say I have a string object on the stack and want to get the number of characters in it - its .Length property. How would I get the int32 number hidden inside?
Many thanks in advance!
There's really no such thing as properties in IL. There are only fields and methods. The C# property construct is translated to get_PropertyName and set_PropertyName methods by the compiler, so you have to call these methods to access the property.
Sample (debug) IL for code
var s = "hello world";
var i = s.Length;
IL
.locals init ([0] string s,
[1] int32 i)
IL_0000: nop
IL_0001: ldstr "hello world"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_000d: stloc.1
As you can see the Length property is accessed via the call to get_Length.
I cheated ... I took the following C# code and took a look at it in ildasm/Reflector
static void Main(string[] args)
{
string h = "hello world";
int i = h.Length;
}
is equivalent to
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] string h,
[1] int32 i)
L_0000: nop
L_0001: ldstr "hello world"
L_0006: stloc.0
L_0007: ldloc.0
L_0008: callvirt instance int32 [mscorlib]System.String::get_Length()
L_000d: stloc.1
L_000e: ret
}