MvvmCross throws NullReferenceException in Windows Phone Designer - windows-phone

I'm getting the following error after using a Visibility Converter from MVVMCross in the designer, stopping me from using Blend to work on my UI. Any Ideas?
NullReferenceException: Object reference not set to an instance of an object.
at Cirrious.CrossCore.Mvx.Resolve[TService]()
at Cirrious.MvvmCross.Plugins.Visibility.MvxBaseVisibilityValueConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
at Cirrious.CrossCore.WindowsPhone.Converters.MvxNativeValueConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
at System.Windows.Data.BindingExpression.ConvertToTarget(Object value)
at System.Windows.Data.BindingExpression.GetValue(DependencyObject d, DependencyProperty dp)
at System.Windows.DependencyObject.EvaluateExpression(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry)
at System.Windows.DependencyObject.EvaluateBaseValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)
at System.Windows.DependencyObject.EvaluateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry, ValueOperation operation)
at System.Windows.DependencyObject.UpdateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)
at System.Windows.DependencyObject.RefreshExpression(DependencyProperty dp)
at System.Windows.Data.BindingExpression.SendDataToTarget()
at System.Windows.Data.BindingExpression.SourceAcquired()
at System.Windows.Data.BindingExpression.System.Windows.IDataContextChangedListener.OnDataContextChanged(Object sender, DataContextChangedEventArgs e)
at System.Windows.Data.BindingExpression.DataContextChanged(Object sender, DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.OnDataContextChanged(DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.OnAncestorDataContextChanged(DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.NotifyDataContextChanged(DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.OnTreeParentUpdated(DependencyObject newParent, Boolean bIsNewParentAlive)
at System.Windows.DependencyObject.UpdateTreeParent(IManagedPeer oldParent, IManagedPeer newParent, Boolean bIsNewParentAlive, Boolean keepReferenceToParent)
at MS.Internal.FrameworkCallbacks.ManagedPeerTreeUpdate(IntPtr oldParentElement, IntPtr parentElement, IntPtr childElement, Byte bIsParentAlive, Byte bKeepReferenceToParent, Byte bCanCreateParent)
Thanks,
MagooChris

The cross-platform visibility functionality is in a plugin - so it needs a bit of the IoC system initialised before it can be used.
To use the designer with the converters present you'll need to add a small amount of design-time initialization.
For the BindingEx module we do this using: https://github.com/slodge/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.BindingEx.WindowsPhone/MvxDesignTimeChecker.cs#L18
If you need design time support for the visibility plugin, then you could do this by using a similar design time check and then using that to make sure the visibility conversion is registered with IoC - e.g. for windowsphone you could insert something like this into a static resource:
if (!DesignerProperties.IsInDesignTool)
return;
if (MvxSingleton<IMvxIoCProvider>.Instance == null)
{
var iocProvider = MvxSimpleIoCContainer.Initialize();
Mvx.RegisterSingleton(iocProvider);
}
var forceVisibility = new Cirrious.MvvmCross.Plugins.Visibility.WindowsPhone.Plugin();
forceVisibility.Load();
Note: obviously this is a bit hacky - would love to see this pulled back into the project to be available for all.

Related

Simple Injector instance is requested outside the context of an active (async scope) scope

I'm trying to inject my IAuthorizationRepository into my VB Web App using SimpleInjector.
Public Class IdentityPackage
Implements IPackage
Public Sub RegisterServices(container As Container) Implements IPackage.RegisterServices
container.Register(Of IUserStore(Of User, Integer), UserStore)(Lifestyle.Scoped)
container.Register(Of IAuthorizationRepository, AuthorizationRepository)(Lifestyle.Scoped)
container.Register(Of ISession, Session)()
End Sub
End Class
Here's my startup.
Public Partial Class Startup
Public Sub Configuration(app As IAppBuilder)
Dim container = ConfigureSimpleInjector(app)
Dim config = New HttpConfiguration() With {
.DependencyResolver = New SimpleInjectorWebApiDependencyResolver(container)
}
ConfigureOAuth(app, container)
WebApiConfig.Register(config)
app.UseCors(CorsOptions.AllowAll)
app.UseWebApi(config)
End Sub
End Class
And here's my ConfigureOAuth.
Public Sub ConfigureOAuth(app As IAppBuilder, container As Container)
Dim authRepositoryFactory As Func(Of IAuthorizationRepository) = container.GetInstance(Of IAuthorizationRepository)
Dim authorizationOptions = New OAuthAuthorizationServerOptions() With {
.AllowInsecureHttp = True,
.TokenEndpointPath = New PathString("/api/token"),
.AccessTokenExpireTimeSpan = TimeSpan.FromHours(4),
.Provider = New AuthorizationServerProvider(authRepositoryFactory)
}
' Token Generation
app.UseOAuthAuthorizationServer(authorizationOptions)
app.UseOAuthBearerAuthentication(New OAuthBearerAuthenticationOptions())
End Sub
When it gets to the first line under ConfigureOAuth, it throws the error The AuthorizationRepository is registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope.
The strange thing is that I'm converting an existing, and fully functional C# project into VB, and this is the VB equivalent of the codebase in C#, but the C# code does not have this problem. This makes me feel like the issue lies in how VB handles the code, as opposed to C#, but I don't see how that could be the case with this example. Can anyone tell me what's going wrong?
The following is my stack trace:
[ActivationException: The AuthorizationRepository is registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope.]
SimpleInjector.Scope.GetScopelessInstance(ScopedRegistration`1 registration) +168
SimpleInjector.Scope.GetInstance(ScopedRegistration`1 registration, Scope scope) +52
SimpleInjector.Advanced.Internal.LazyScopedRegistration`1.GetInstance(Scope scope) +158
lambda_method(Closure ) +223
SimpleInjector.InstanceProducer.BuildAndReplaceInstanceCreatorAndCreateFirstInstance() +32
SimpleInjector.InstanceProducer.GetInstance() +235
SimpleInjector.Container.GetInstanceForRootType() +154
SimpleInjector.Container.GetInstance() +146
ClientWebAppVB.Api.Startup.ConfigureOAuth(IAppBuilder app, Container container) in C:\Projects\TEST\ClientWebAppVB\ClientWebAppVB.Api\App_Start\OAuthConfig.vb:10
ClientWebAppVB.Api.Startup.Configuration(IAppBuilder app) in C:\Projects\TEST\ClientWebAppVB\ClientWebAppVB.Api\Startup.vb:15
[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0
System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +160
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +101
Owin.Loader.<>c__DisplayClass12.<MakeDelegate>b__b(IAppBuilder builder) +66
Owin.Loader.<>c__DisplayClass1.<LoadImplementation>b__0(IAppBuilder builder) +123
Microsoft.Owin.Host.SystemWeb.<>c__DisplayClass2.<InitializeBlueprint>b__0(IAppBuilder builder) +71
Microsoft.Owin.Host.SystemWeb.OwinAppContext.Initialize(Action`1 startup) +462
Microsoft.Owin.Host.SystemWeb.OwinBuilder.Build(Action`1 startup) +40
Microsoft.Owin.Host.SystemWeb.OwinHttpModule.InitializeBlueprint() +70
System.Threading.LazyInitializer.EnsureInitializedCore(T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory) +115
Microsoft.Owin.Host.SystemWeb.OwinHttpModule.Init(HttpApplication context) +106
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +536
System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +173
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +336
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +296
[HttpException (0x80004005): Exception has been thrown by the target of an invocation.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +10044576
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +95
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +254
The strange thing is that I'm converting an existing, and fully functional C# project into VB, and this is the VB equivalent of the codebase in C#, but the C# code does not have this problem
Well this is actually not the equivalent of the c# version. And unless you changed Option Explicit and Option Strict settings I'm pretty sure the code you show does not even compile. Or in your real code you omitted the As Func(Of IAuthorizationRepository) clause.
In c# this two lines are 2 totally different things:
// create a delegate
Func<IAuthorizationRepository> authRepositoryFactory =
container.GetInstance<IAuthorizationRepository>;
// and directly call a delegate or method
Func<IAuthorizationRepository> authRepositoryFactory =
container.GetInstance<IAuthorizationRepository>();
And here the second line does not compile. This line returns IAuthorizationRepository and therefore is not assignable to Func<IAuthorizationRepository>.
In Vb.Net however the following lines are exactly the same. The braces of a method call are totally optional.
' Directly call the method
Dim authRepositoryFactory = container.GetInstance(Of IAuthorizationRepository)
' And directy call the method
Dim authRepositoryFactory = container.GetInstance(Of IAuthorizationRepository)()
If you hover over authRepositoryFactory you'll see that the inferred type is IAuthorizationRepository for both lines.
To create a delegate instead of directly invoking it in VB you need to use the AddressOf Operator
Dim authRepositoryFactory = New Func(Of IAuthorizationRepository)(
AddressOf container.GetInstance(Of IAuthorizationRepository))
'or
Dim authRepositoryFactory As Func(Of IAuthorizationRepository) =
AddressOf container.GetInstance(Of IAuthorizationRepository)
If you would hover over authRepositoryFactory you'll see this is actually a Func (Of IAuthorizationRepository)

Add-Migration error: Object reference not set to an instance of an object

I'm using code-first concept and just tried adding a new class to the Models folder in hope to create a new table in SQL server database. i've added
Public Overridable Property Diagnosis As DbSet(Of Diagnosis)
in the DBContext.vb.
Then in the package manager console, i entered Add-Migration Diagnosis. But below error comes out. Why is this? Can anyone help me out please?
Object reference not set to an instance of an object.
Full error in Package Manager Console:
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.UI.ParseChildrenAttribute.GetHashCode()
at System.Collections.Generic.ObjectEqualityComparer`1.GetHashCode(T obj)
at System.Linq.Set`1.InternalGetHashCode(TElement value)
at System.Linq.Set`1.Find(TElement value, Boolean add)
at System.Linq.Enumerable.<ExceptIterator>d__72`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at System.Data.Entity.ModelConfiguration.Utilities.AttributeProvider.<GetAttributes>b__3(PropertyInfo pi)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at System.Data.Entity.ModelConfiguration.Utilities.AttributeProvider.GetAttributes(PropertyInfo propertyInfo)
at System.Data.Entity.ModelConfiguration.Conventions.PropertyAttributeConfigurationConvention`1.<.ctor>b__0(ConventionTypeConfiguration ec)
at System.Data.Entity.ModelConfiguration.Conventions.TypeConvention.ApplyCore(Type memberInfo, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Conventions.TypeConventionBase.Apply(Type memberInfo, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.ApplyModelConfiguration(Type type, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Conventions.Convention.ApplyModelConfiguration(Type type, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.ApplyModelConfiguration(Type type, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapComplexType(Type type, Boolean discoverNested)
at System.Data.Entity.ModelConfiguration.Mappers.PropertyMapper.MapPrimitiveOrComplexOrEnumProperty(PropertyInfo propertyInfo, Func`1 structuralTypeConfiguration, Boolean discoverComplexTypes)
at System.Data.Entity.ModelConfiguration.Mappers.PropertyMapper.MapIfNotNavigationProperty(PropertyInfo propertyInfo, EntityType entityType, Func`1 entityTypeConfiguration)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.<>c__DisplayClass14.<MapEntityType>b__e(PropertyMapper m, PropertyInfo p)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapStructuralElements[TStructuralTypeConfiguration](Type type, ICollection`1 annotations, Action`2 propertyMappingAction, Func`1 structuralTypeConfiguration)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapEntityType(Type type)
at System.Data.Entity.ModelConfiguration.Mappers.NavigationPropertyMapper.Map(PropertyInfo propertyInfo, EntityType entityType, Func`1 entityTypeConfiguration)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapEntityType(Type type)
at System.Data.Entity.DbModelBuilder.MapTypes(EdmModel model)
at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.LazyInternalContext.get_ModelBeingInitialized()
at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
at System.Data.Entity.Utilities.DbContextExtensions.<>c__DisplayClass1.<GetModel>b__0(XmlWriter w)
at System.Data.Entity.Utilities.DbContextExtensions.GetModel(Action`1 writeXml)
at System.Data.Entity.Utilities.DbContextExtensions.GetModel(DbContext context)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext, DatabaseExistenceState existenceState, Boolean calledByCreateDatabase)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
at System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
at System.Data.Entity.Migrations.Design.ToolingFacade.Scaffold(String migrationName, String language, String rootNamespace, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.Execute(String name, Boolean force, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
Object reference not set to an instance of an object.
I don't know if this is relevant or not, but in my web.config, there is a Default Connection that is already pre-set when i first created my project. When i first did Enable-Migrations i had to specify which connection it was. I've removed that line but it still doesn't work.
Previously when i did the add-migration, it didn't work because i simply created a class and added declaration of the respective strings, integer, etc. as variables like this:
Public Property id As String
Now it suddenly popped into my mind that i had to give a more elaborate description on each of the variables such as below:
<Key>
<StringLength(20)>
Public Property id As String
Now it works =')

Resolution failure on app reload in MVC4 + Unity

I'm working on an ASP.NET MVC4 application, using Unity 3 as DI framework.
I designed the architecture in a modular way, creating several satellite library projects (facade, managers, DB adapters, etc.), all statically linked to the app (which means added as references to the web project).
The reason behind such architecture is to allow reusage in other contexts (for instance a separate REST based backend service, implemented as a standalone web project).
I'm using dependency injection, which occurs at web project level, but also in the satellite DLLs. In order to centralize DI resolution, I'm using a simple interface
public interface IIocInstaller
{
void Setup(IUnityContainer container);
}
and each library project has a class implementing that interface. Using reflection, the web app scans all loaded assemblies for a class implementing the interface, and calls the Setup method.
Everything works when I start the app. However, when the web app is unloaded by the web server due to inactivity, on next request the following exception is thrown:
[InvalidOperationException: The type ICustomerFacade does not have an accessible constructor.]
Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForNullExistingObject(IBuilderContext context) +178
lambda_method(Closure , IBuilderContext ) +25
Microsoft.Practices.ObjectBuilder2.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context) +35
Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +10
Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +196
Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +193
Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +113
Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) +48
lambda_method(Closure , IBuilderContext ) +111
Microsoft.Practices.ObjectBuilder2.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context) +35
Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +10
Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +196
Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +193
Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +165
[ResolutionFailedException: Resolution of the dependency failed, type = "Eden.SMS.UI.Web.Controllers.CustomersController", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type ICustomerFacade does not have an accessible constructor.
-----------------------------------------------
At the time of the exception, the container was:
Resolving Eden.SMS.UI.Web.Controllers.CustomersController,(none)
Resolving parameter "customerFacade" of constructor Eden.SMS.UI.Web.Controllers.CustomersController(Eden.SMS.Service.Facades.Interface.ICustomerFacade customerFacade)
Resolving Eden.SMS.Service.Facades.Interface.ICustomerFacade,(none)
]
Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +329
Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides) +15
Microsoft.Practices.Unity.UnityContainerExtensions.Resolve(IUnityContainer container, Type t, ResolverOverride[] overrides) +18
Unity.Mvc4.UnityDependencyResolver.GetService(Type serviceType) +67
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +41
[InvalidOperationException: An error occurred when trying to create a controller of type 'Eden.SMS.UI.Web.Controllers.CustomersController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +178
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +77
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +66
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +191
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
All unity related code is performed in Application_Start. The ICustomerFacade interface is injected in a controller, and it is subject itself to injection of other instances, of course still using DI.
The error message warns about the controller having a parameterless constructor, which is of course not implemented because I need the one with injected parameters - I've also tried to specify the constructor to be used (by using InjectionConstructor), but with no luck.
Any idea why that exception is thrown?
Update
It looks like the problem is due to failure invoking the initializer in the satellite projects.
This is the code that I'm using to scan all assemblies looking for instances implementing the IIocInstaller interface
public class AssemblyInjector
{
/// <summary>
/// Initialize IoC in all assemblies implementing the IocExportAssembly attribute
/// </summary>
/// <param name="container"></param>
/// <param name="assemblyPrefix">The prefix of the assembly names to load</param>
public static void RegisterAssemblyTypes(IUnityContainer container, string assemblyPrefix)
{
var bootstrapers = EnumerateIocBootstraperTypes(assemblyPrefix);
foreach ( Type type in bootstrapers )
{
var instance = (IIocInstaller) Activator.CreateInstance(type);
instance.Setup(container);
}
}
/// <summary>
/// Given a list of assemblies, find all types exposing the
/// <see cref="IocExportAssemblyAttribute"/> attribute
/// </summary>
/// <param name="assemblyPrefix">The prefix of the assembly names to load</param>
/// <returns>list of types exposing the <see cref="IocExportAssemblyAttribute"/> attribute</returns>
private static IEnumerable<Type> EnumerateIocBootstraperTypes(string assemblyPrefix)
{
var assemblies = EnumerateIocAssemblies(assemblyPrefix);
var iocInterface = typeof(IIocInstaller);
var bootstrapers = assemblies.SelectMany(s => s.GetTypes())
.Where(iocInterface.IsAssignableFrom);
return bootstrapers;
}
/// <summary>
/// Enumerate and return all assemblies whose name starts by "Eden.SMS"
/// </summary>
/// <returns><see cref="IEnumerable{T}"/>list of assemblies</returns>
/// <param name="assemblyPrefix">The prefix of the assembly names to load</param>
private static IEnumerable<Assembly> EnumerateIocAssemblies(string assemblyPrefix)
{
return from assembly in AppDomain.CurrentDomain.GetAssemblies()
where assembly.GetName().Name.StartsWith(assemblyPrefix)
select assembly;
}
}
and this is used in the Unity bootstrapper
/// <summary>
/// Dependency injection bootstrapper
/// </summary>
public static class Bootstrapper
{
private const string ASSEMBLY_PREFIX = "Eden.SMS";
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
AssemblyInjector.RegisterAssemblyTypes(container, ASSEMBLY_PREFIX);
//RegisterSatelliteTypes(container);
// Register local types
RegisterTypes(container);
foreach ( var registration in container.Registrations )
{
Debug.WriteLine(string.Format("Registered {0} as {1}", registration.RegisteredType, registration.MappedToType));
}
return container;
}
private static void RegisterSatelliteTypes(UnityContainer container)
{
new Eden.SMS.Data.Adapters.Mssql.Bootstrapper().Setup(container);
new Eden.SMS.Data.Managers.Bootstrapper().Setup(container);
new Eden.SMS.Service.Bootstrapper().Setup(container);
}
private static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IController, CustomersController>(new InjectionConstructor(typeof(ICustomerFacade)));
container.RegisterType<IController, AuthenticationController>(new InjectionConstructor(typeof(IAuthenticationFacade)));
}
}
The bootstrapper, in turns, is called from Application_Start() in Global.asax.
If in bootstrapper I comment this line
AssemblyInjector.RegisterAssemblyTypes(container, ASSEMBLY_PREFIX);
and uncomment this
RegisterSatelliteTypes(container);
it works as expected (no exception thrown after the app is unloaded by the web server).
That change disables the dynamic lookup of classes implementing the IIocInstaller, replacing that by direct calls on each satellite assembly.
This workaround fixes the bug, but I'd want to stick with the original "dynamic" plan. So I'd like to figure out why that is happening and how to solve it. Any suggestion?
I believe your issue is what this other post describes about the way DLLs are loaded into the AppDomain by the .Net Framework:
The .NET Framework defers loading assemblies into the current
AppDomain until they're needed. For example, if you call into a
third-party library only from SomeMethod(), the third-party DLL
normally won't be loaded until the first time SomeMethod() runs.
AppDomain.GetAssemblies() gives you all assemblies which have already
been loaded into the current AppDomain.
The good news are that there is method BuildManager.GetReferencedAssemblies() that returns a list of all assemblies referenced from Web.config and elsewhere, and it loads those assemblies into the current AppDomain.
This was the cause for this issue similar to yours, which was solved using BuildManager.GetReferencedAssemblies() instead of AppDomain.CurrentDomain.GetAssemblies().
Hope it helps!

How to debug serialization error in tombstoned WP7 app

I am handling the current state of my WP7 app in the OnNavigatedFrom and To events so that if the app is tombstoned OR they navigate to a different page it saves the state to the inbuilt PhoneApplicationService state.
I have a simple ViewModel which I dump to the state to make life easier. When navigate to a different page within my app, the state is stored fine and restores fine (ie. I assume it is serializing at this point). However, when I tombstone the app (i.e. Start button) I am getting an unhandled error with serialization and the stacktrace is not giving me any clues as to why it is failing.
I have tried wrapping the actual call in a try catch block to try and see what is wrong but it doesn't help - it's something that the runtime is doing different on tombstoning with my object than when it just stores it between pages.
Here is my code:
protected override void OnNavigatedFrom(NavigationEventArgs args)
{
appService.State["TournamentViewModel"] = tournamentViewModel;
base.OnNavigatedFrom(args);
}
protected override void OnNavigatedTo(NavigationEventArgs args)
{
if (appService.State.ContainsKey("TournamentViewModel"))
{
tournamentViewModel = (TournamentViewModel)appService.State["TournamentViewModel"];
}
base.OnNavigatedTo(args);
}
This is the error that is generated - I really can't figure out where the problem is - how can I debug this better?
Exception Info:
Message: "SecurityException"
InnerException: "Could not evaluate expression"
StackTrace:
at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateGetOnlyCollectionDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetGetOnlyCollectionDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serialization.DataContract.GetGetOnlyCollectionDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContractSkipValidation(Int32 typeId, RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerializeReference(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at System.Runtime.Serialization.XmlFormatWriter.InternalSerialize(MethodInfo methodInfo, Object memberValue, Type memberType, Boolean writeXsiType, XmlObjectSerializerWriteContext context, XmlWriterDelegator xmlWriter)
at System.Runtime.Serialization.XmlFormatWriter.WriteValue(Type memberType, Object memberValue, Boolean writeXsiType, XmlObjectSerializerWriteContext context, XmlWriterDelegator xmlWriter)
at System.Runtime.Serialization.XmlFormatWriter.WriteMember(SerializingObject serObj, Int32 memberIndex, ClassDataContract derivedMostClassContract)
at System.Runtime.Serialization.XmlFormatWriter.WriteClass(CallStackElement`1 callStackElement)
at System.Runtime.Serialization.XmlFormatWriter.Serialize(XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlFormatWriter.InitializeCallStack(XmlWriterDelegator xmlWriterDel, Object obj, XmlObjectSerializerWriteContext writeContext, DataContract contract)
at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(Stream stream, Object graph)
at Microsoft.Phone.Shell.StreamPersister.Serialize(IDictionary`2 dictionary, IEnumerable`1 knownTypes)
at Microsoft.Phone.Shell.StreamPersister.Save(ShellPageManager shellPageManager, String key, IDictionary`2 dictionary, IEnumerable`1 knownTypes)
at Microsoft.Phone.Shell.PhoneApplicationService.FireDeactivated()
at Microsoft.Phone.Execution.NativeEmInterop.FireOnPause()
Update: By trial and error I found the problem to be the AppBar, which does not seem to be serializable. I marked it with [IgnoreDataMember] and it now throws a more meaningful error on a different problem. I would still like to know if there are any easy ways of catching this info...
Rodney,
My understanding is that when you put an object in one of the two State Dictionaries (the one off of PhoneApplicationPage and the other off of PhoneApplicationServices) it does not immediately serialize or deserialize.
If you use the Page.State to store data, it serializes your state bag when you leave the page, and deserializes when you return to the page (rather than when you add or read an object from the state bag).
If you use the PhoneApplicationService.State, serialization happens when you tombstone and deserialization when the application is re-activated (though I'm not sure if this is tied to the PhoneApplicationService.Activated event or not).
Page.State, by the way, doesn't allow sharing data between pages. Saving to PhoneApplicationService.State does allow you to do so.
IsolatedStorage.AppSettings seems to handle deserialization problems silently, so I'm not sure when that happens. Serialization, however, occurs when you call Save().
James
Well, how does your ViewModel express the way in which it's serializable? Personally I tend to try to steer clear of potentially-intricate serialization: one fairly simple option is to give your ViewModel the ability to explicitly convert itself to/from XML, and then perform that step manually yourself, saving an XDocument (or its string representation) in the application state. That way it's easy to debug the serialization step, see the exact XML being generated etc.
Of course, the use of XML here is incidental - if you can easily put everything in a CSV string, that would be fine too. Anything that you can easily inspect in terms of the serialized form before putting in application state.
I realise this is side-stepping some of the supposed benefits of the "automatic" serialization, but I've run into enough hard-to-diagnose problems with automatic serialization of arbitrary objects that I don't think the benefits outweigh the drawbacks.

NHibernate: Collection was modified; enumeration operation may not execute

I'm currently struggling with this "Collection was modified; enumeration operation may not execute" issue.
I have searched about this error message, and it's all related to the foreach statement. I do have the some foreach statements, but they are just simply representing the data. I did not using any remove or add inside the foreach statement.
NOTE:
The error randomly happens (about 4-5 times a day).
The application is the MVC website.
There are about 5 users operate this applications (about 150 orders a day). Could it be some another users modified the collection, and then occur this error?
I have log4net setup and the settings can be found here
Make sure that the controller has a parameterless public constructor I do have parameterless public constructor in AdminProductController
Does anyone know why this happen and how to resolve this issue?
A friend (Oskar) mentioned that
"Theory: Maybe the problem is that
your configuration and session factory
is initialized on the first request
after application restart. If a second
request comes in before the first
request is finished, maybe it will
also try to initialize and then
triggering this problem somehow."
Many thanks.
Daoming
Here is the error message:
System.InvalidOperationException
Collection was modified; enumeration operation may not execute.
System.InvalidOperationException: An error occurred when trying to create a controller of type 'WebController.Controllers.Admin.AdminProductController'. Make sure that the controller has a parameterless public constructor. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> NHibernate.MappingException: Could not configure datastore from input stream DomainModel.Entities.Mappings.OrderProductVariant.hbm.xml ---> System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
at System.Xml.Schema.XmlSchemaSet.AddSchemaToSet(XmlSchema schema)
at System.Xml.Schema.XmlSchemaSet.Add(String targetNamespace, XmlSchema schema)
at System.Xml.Schema.XmlSchemaSet.Add(XmlSchema schema)
at NHibernate.Cfg.Configuration.LoadMappingDocument(XmlReader hbmReader, String name)
at NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream, String name)
--- End of inner exception stack trace ---
at NHibernate.Cfg.Configuration.LogAndThrow(Exception exception)
at NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream, String name)
at NHibernate.Cfg.Configuration.AddResource(String path, Assembly assembly)
at NHibernate.Cfg.Configuration.AddAssembly(Assembly assembly)
at DomainModel.RepositoryBase..ctor()
at WebController.Controllers._baseController..ctor()
at WebController.Controllers.Admin.AdminProductController..ctor()
at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)
--- End of inner exception stack trace ---
at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
--- End of inner exception stack trace ---
at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)
at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Oskar is right. Two separate threads are trying to initialize the session factory at the same time. Suggest you put some locking around the initialization code, perhaps just using the lock keyword and a suitable synchronization object. We've used a pattern like this, using one of the locks from the Wintellect PowerThreading library:
using (_lock.WaitToRead())
{
if (Factory != null) return Factory;
}
using (_lock.WaitToWrite())
{
if (Factory != null) return Factory;
Factory = ConfigureFactory();
return Factory;
}
You could more simply just use the lock keyword and a double-check locking pattern like so:
class NestedSessionManager
{
internal static SessionManager _sessionManager;
private static readonly object _syncRoot = new object();
internal static SessionManager sessionManager
{
get
{
if (_sessionManager != null) return _sessionManager;
lock (_syncRoot)
{
if (_sessionManager != null) return _sessionManager;
_sessionManager = new SessionManager();
return _sessionManager;
}
}
}
}