I got the following exception:
System.Workflow.Runtime.Hosting.PersistenceException: Type ‘Microsoft.SharePoint.SPWeb’ in Assembly ‘Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c’ is not marked as serializable. —> System.Runtime.Serialization.SerializationException: Type ‘Microsoft.SharePoint.SPWeb’ in Assembly ‘Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c’ is not marked as serializable
The error came from here:
public sealed partial class MyWorkflow : StateMachineWorkflowActivity
{
public SPWorkflowActiviationProperties workflowProperties = new SPWorkflowActivationProperties();
private SPWeb spWebtemp;
private SPWeb spWeb
{
get { return spWebtemp ?? (spWebtemp = workflowProperties.Web); }
}
...
There are two blog posts I found:
... is not marked as serializable
Serialization Issue with Windows Workflow Foundation and Sharepoint Workflow
There is one solution to be found to this problem: Not have complex member objects as global variables, but as a local variables - i.e. declare SPWeb locally (workflowProperties.Web) instead of on a global level.
So I would have to redeclare spWeb in every method I am using - which I deem rather ugly.
What I also tried is this:
...
[NonSerialized]
private SPWeb spWebtemp;
private SPWeb spWeb
{
get { return spWebtemp ?? (spWebtemp = workflowProperties.Web); }
}
...
==> no more serialization exception!
Are there any negative implications when using the NonSerialized attribute on this field?
Or in other words - what are the implications?
Why don't you simply do :
private SPWeb spWeb
{
get { return workflowProperties.Web; }
}
the lazy load of the spweb object is already handled by the properties property
This looks like it also would also work (the OnDeserialized Attribute):
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ondeserializedattribute.aspx
[EDIT]
I haven't tested this, but I'm thinking something like this:
public sealed partial class MyWorkflow : StateMachineWorkflowActivity
{
public SPWorkflowActiviationProperties workflowProperties = new SPWorkflowActivationProperties();
[NonSerialized()]
private SPWeb spWebtemp;
private SPWeb spWeb
{
get { return spWebtemp ?? (spWebtemp = workflowProperties.Web); }
}
[OnDeserialized()]
internal void OnDeserializedMethod(StreamingContext context)
{
spWebTemp = workflowProperties.Web;
}
...
Also, why not initialize the spWebtemp object in the constructor, or is that not possible with workflows?
Related
I have a Automapper Mapping Profile like this:
CreateMap<MyViewModel, MyDto>()
.ForMember(s => s.MyProperty, opt => opt.ResolveUsing<CustomResolver>());
And this is my CustomResolver class (that aims to solve a value through the Claims):
public class CustomResolver : IValueResolver<object, object, string>
{
private readonly HttpContext _context;
public CompanyResolver(IHttpContextAccessor httpContextAccessor)
{
_context = httpContextAccessor.HttpContext;
}
public string Resolve(object source, object destination, string destMember, ResolutionContext context)
{
return "I will return here a value from Claims inside _context";
}
}
Obviously, on my Startup class I registered my Services:
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
But, Always, I received this exception from Automapper:
No parameterless constructor defined for this object.
But, precisely, I want the request to go through the constructor (CustomResolver) with parameters because I want to receive IHttpContextAccesor instance.
What's wrong? Why is NET Core not capable of injecting the interface?
I solved the problem by changing this:
var automapperConfig = new MapperConfiguration(configuration =>
{
configuration.AddProfile(new MyProfile());
});
var autoMapper = automapperConfig.CreateMapper();
services.AddSingleton(autoMapper);
To this:
services.AddAutoMapper(configuration =>
{
configuration.AddProfile(new MyProfile());
});
I do not understand 100% the reason but I guess we should not add Automapper as Singleton
I have object like below
public class MyObject
{
private IEnumerable _data;
public MyObject(IEnumerable<int> data)
{
_data = data;
}
public IEnumerable GetData()
{
return this._data;
}
}
the _data property is private. I am storing this object in session as below using jsonserializer
var val = new MyObject(new int[] {1,2,3})
HttpContext.Session.SetString("MyKey", JsonConvert.SerializeObject(val));
then im trying to retrieve it as below
var val = HttpContext.Session.GetString("MyKey");
var myObject = JsonConvert.DeserializeObject<MyObject>(val);
However MyObject.GetData() returns null. I am assuming since _data property is private JsonSerializer is not able to serialize it.
So what are my options here to store an object in session which has private properties?
You can try to make your class serializable like this
[Serializable]
public class MyObject : ISerializable
{
private IEnumerable _data;
public MyObject(IEnumerable<int> data)
{
_data = data;
}
public IEnumerable GetData()
{
return this._data;
}
protected MyObject(SerializationInfo info, StreamingContext context)
{
_data = (IEnumerable<int>)info.GetValue(nameof(_data), typeof(IEnumerable<int>));
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
throw new ArgumentNullException(nameof(info));
info.AddValue(nameof(_data), _data, typeof(IEnumerable<int>));
}
}
For this to work, you have to target a minimum of netstandard1.3 (.NET Framework 4.6 or .NET Core). In your project.json you need to add System.Runtime.Serialization.Formatters dependency
"netstandard1.3": {
"imports": [ "dnxcore50", "portable-net45+win8" ],
"dependencies": {
"NETStandard.Library": "1.6.0",
"System.Runtime.Serialization.Formatters": "4.0.0-rc3-24212-01"
}
}
I didn't test it on .NET Core, so no idea if it works. But this is how you implement but JSON.NET actually does support serializing ISerializable objects. I just don't know if the .NET Core version of JSON.NET does support it, because the nuget package targets netstandard1.0 and ISerializable requires System.Runtime.Serialization.Formatters which requires netstandard1.3.
I believe this is a standard JSON.Net serialization problem. Private properties aren't serialized unless you provide your own serializer as provided in this answer.
Additionally, you'll need a default constructor, or ensure to tag your constructor correctly (unsure whether that'll work with private fields). This is a good answer to the non-default constructor problem.
I feel like your class is a simple DTO without too much value of keeping this field private. Why not marking it as public? Or if your object is more complex than the example given, you might want to have a dedicated DTO with only public properties and no functionality which you create just for serialization/deserialization and then manually convert into the class you actually want. This way, you can also ensure your DTO stays compatible as you release new versions even if you introduce breaking changes in the other class.
I've created this code:
public class AddonsModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
this.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(UIExtensibility.AbstractAddon))
.BindWith(new AddonBindingGenerator())
);
}
private class AddonBindingGenerator : IBindingGenerator
{
public System.Collections.Generic.IEnumerable<Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(System.Type type, Ninject.Syntax.IBindingRoot bindingRoot)
{
if (type.IsInterface || type.IsAbstract)
yield break;
yield return bindingRoot.Bind(type).ToProvider(typeof(UIExtensibility.AbstractAddon));
}
}
private class AddonProvider : IProvider<UIExtensibility.AbstractAddon>
{
public object Create(IContext context)
{
return null;
}
public Type Type
{
get { throw new NotImplementedException(); }
}
}
}
AddonProvider seems be avoided. This is never performed.
When I perform:
kernel.GetAll<UIExtensibility.AbstractAddon>(), AddonProvider.Create method is never performed.
Could you tell me what's wrong?
I'll appreciate a lot your help.
Thanks for all.
AddOnProvider is inheriting from IProvider<T> instead of UIExtensibility.AbstractAddon.
also, you may have issues binding to private inner classes. make AddOnProvider a public top level class.
You're binding a specific type which inherits from typeof(UIExtensibility.AbstractAddon) to a provider. For example, there could be a class Foo : UIExtensibility.AbstractAddon.
Now your convention binding translates to this:
Bind<Foo>().ToProvider<AddonProvider>();
Now, kernel.GetAll<UIExtensibility.AbstractAddon>() however is looking for bindings made like:
Bind<UIExtensibility.AbstractAddon>().To...
Fix It
So what you need to do is change the line
bindingRoot.Bind(type).ToProvider(new AddonProvider());
to:
bindingRoot.Bind(typeof(UIExtensibility.AbstractAddon)).ToProvider<AddonProvider>();
Furthermore
you're line object f = bindingRoot.Bind(type).ToProvider(new AddonProvider()); is never returning the binding (object f).
does UIExtensibility.AbstractAddon implement IProvider?
Thanks for your answer and comments.
I believe the trouble is on I'm not quite figuring out how this "generic" binding process works.
I'm going to try writing my brain steps process out:
I need to bind every AbstractAddon implementation inside addons assemblies folder. So, I think this code is right, but I'm not sure at all.
this.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(UIExtensibility.AbstractAddon))
.BindWith(new AddonBindingGenerator())
);
My AbstractAddon is like:
public abstract class AbstractAddon : IAddon
{
private object configuration;
public AbstractAddon(object configuration)
{
this.configuration = configuration;
}
// IAddon interface
public abstract string PluginId { get; }
public abstract string PluginVersion { get; }
public abstract string getCaption(string key);
public abstract Type getConfigurationPanelType();
public abstract System.Windows.Forms.UserControl createConfigurationPanel();
}
I guess I need to:
foreach implementation of `AbstractAddon` found out,
I need to "inject" a configuration object ->
So, I guess I need to set a provider and provide this configuration object.
This would be my main way of thinking in order to solve this problem.
I've changed a bit my first approach. Instead of using a IBindingGenerator class, I've used the next:
public class AddonsModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
this.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(UIExtensibility.AbstractAddon))
.BindAllBaseClasses()
.Configure(c => c.InSingletonScope())
);
this.Bind<object>().ToProvider<ConfigurationProvider>()
.WhenTargetHas<UIExtensibility.ConfigurationAttribute>();
}
So, My ConfigurationProvider is:
private class ConfigurationProvider : IProvider<object>
{
public object Create(IContext context)
{
return "configuration settings";
}
}
And now, my AbstractAddon constructor contains the parameter annotated with ConfigurationAttribute as:
public AbstractAddon([Configuration]object configuration)
{
this.configuration = configuration;
}
The problem now, NInject seems to ignore the configuration object provider. NInject generates a dump object, however, not perform ConfigurationProvider.Create method...
What I'm doing wrong, now?
Is this approach really better than the last one?
Thanks for all.
I am trying to load the domain class by deserializing an xml file. So I have used System.Collections.Generic.List in the domain class. But when I try to save the object using Session object then it is failing with exception "Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericBag1[MyFirstMapTest.Class5]' to type 'System.Collections.Generic.List1[MyFirstMapTest.Class5]'." This issue was posted in some of the previous discussion and the answer was to use use IList instead of List(Unable to cast object of type NHibernate.Collection.Generic.PersistentGenericBag to List)
But, If I use IList then I am unable to Deserialize the xml in to Domain class.
XmlTextReader xtr = new XmlTextReader(#"C:\Temp\SampleInput.xml");
XmlSerializer serializer = new XmlSerializer(objClass5.GetType());
objClass5 = (MyFirstMapTest.Class5)serializer.Deserialize(xtr);
session.Save(objClass5);
It is throwing the below error
"Cannot serialize member xxxxx of type System.Collections.Generic.IList`1[[xxxxxxxxxx, Examples, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] because it is an interface."
I have tried to use PersistentGenericBag instead of List but PersistentGenericBag is not serializable. So Deserialization is not working.
How can I resolve this issue? Thank you for looking at this issue.
You may try to use backing field for NHibernte binding and property for Serialization, where property will be of type List, while backing field - IList.
Edit
fluent mapping may look like this:
public class HierarchyLevelMap : IAutoMappingOverride<HierarchyLevel>
{
public void Override(AutoMapping<HierarchyLevel> mapping)
{
mapping.HasMany(x => x.StructuralUnits)
.Access.ReadOnlyPropertyThroughCamelCaseField();
}
}
entity:
public class HierarchyLevel : IEntity
{
private readonly IList<StructuralUnit> structuralUnits = new List<StructuralUnit>();
public virtual List<StructuralUnit> StructuralUnits
{
get { return structuralUnits; }
set { structuralUnits = value; }
}
}
You can create two properties like this in your class:
public class Sample
{
private IList<Sample> _list;
[XmlIgnoreAttribute]
public virtual IList<Sample> List
{
get
{
return _list;
}
set
{
_list = value;
}
}
public virtual List<Sample> List
{
get
{
return (List<Sample>)_list;
}
set
{
_list = value;
}
}
}
And you only map your IList Property.
I am trying to bind a repository to property using Ninject but always get null reference of binding object. I will explain the problem using code below.
public interface IServiceRepository
{
User GetUser(string email);
IQueryable<Statistic> GetStatisticForCurrentMonth(string ip);
void InsertStatistic(ConversionModel conversionModel);
class ServiceRepository : IServiceRepository
{
//Implementation of the Interface
}
I am would like to bind the repository above to class below while the class is created. Unfortunately Repository object is always null. Maybe I have misunderstood how Ninject is working? How to solve the problem?
public class Converter
{
[Inject]
public static IServiceRepository Repository { get; set; }
private static Converter _converter;
public static Converter Instance
{
get { return _Converter ?? (_Converter = new Converter ());
}
}
Ninject activator code
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IServiceRepository>().ToMethod(context => Converter.Repository);
}
Update
I have tried to rewrite code like this
public class Converter
{
private readonly IServiceRepository _repository;
public Converter(IServiceRepository repository)
{
_repository = repository;
}
//skip code
}
The test...
[TestMethod]
public void ConverterInstanceCreated()
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
Assert.IsNotNull(kernel.Get<Converter>());
}
}
gives exception
Test method PC.Tests.NinjectTest.ConverterInstanceCreated threw exception:
Ninject.ActivationException: Error activating IServiceRepository
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IServiceRepository into parameter repository of constructor of type Converter
1) Request for Converter
I just lost, I am trying to understand how Ninject is working for about week without any success. In my case why this exception is thrown?
Also please someone post working example with one repository injection to singleton class.
Ninject does not inject statics. Change the coynverter to a non-static class and configure it as Singleton in ninject. Also use constructor injection and make the repo a private field.
Now you can inject the converter to the constructors where you need it.
Even though you are using Property injection and not Constructor injection I think it would still be
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
}
As ninject still just needs to know what concrete type to map to the Interface
I haven't tested this so apologies if it's wrong.