Why does CanDeserialize always return false when deserialization succeeds? - xml-serialization

I am attempting to deserialize an xml string into an object, nothing strange about that. Everything was fine until I upgraded my project to .Net5.
In the upgrade, I had to add a reference to the package Microsoft.XmlSerializer.Generator, and alter the project file to add the following:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.XmlSerializer.Generator" Version="1.0.0" />
</ItemGroup>
That allowed me to create the XmlSerializer (first error was just weird). Now, however, every call to CanDeserialize on the XmlReader return false if the class has the XmlRoot attribute. Now, I can deserialize the xml text. That does work. But why would CanDeserialize fail based on that condition?
Below is the class and the code I am using to test in a console app (.Net5).
[Serializable, XmlRoot("TestObj")]
//[Serializable]
public class TestObj
{
public int TestVal;
}
static void Main(string[] args)
{
var serializer = new XmlSerializer(typeof(TestObj));
//generated by doing a test serialization of the class
var teststr = "<TestObj xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><TestVal>2</TestVal></TestObj>";
using (var str = new StringReader(teststr))
using (var reader = XmlReader.Create(str))
{
if (serializer.CanDeserialize(reader))
Console.WriteLine(((TestObj)serializer.Deserialize(reader)).TestVal);
else
{
Console.WriteLine("Value cannot be deserialized into the given Type");
//try it anyway
var o = (TestObj)serializer.Deserialize(reader);
Console.WriteLine(o.TestVal);
}
}
}
My workaround is just to eliminate the CanDeserialize call and wrap the deserialization in a try.. catch, but I'm still curious why this is happening.

Okay, comments on the question from #dbc did lead me to try something else. A couple of details I left of the original question because it didn't seem relevant (due to the testing involved) is that the class I am trying to deserialize in my non-test is in a .Net Standard 2.1 library. While the project doing the deserialization is .Net5.
In the end, I got this work. I had to reference the Microsoft.XmlSerializer.Generator package in my .Net Standard based library, but not reference it in the .Net5 project.
In short, leaving the package reference off the Standard project caused one error, and including it in both caused another.

Related

Includes doesn't work with LinqKit AsExpandable

I'm trying to use LinqKit AsExpandable in my EfCore2.0 project and I am running into this problem where the Includes doesn't work.
In attempting to debug this I have downloaded the LinqKit source from github and have replaced the Nuget references in my project with Project references.
When debugging with the LinqKit project, I noticed that the my call to Include wasn't hitting a breakpoint I set on ExpandableQueryOfClass<T>.Include.
I did some further testing and noticed the breakpoint is hit if I first cast to ExpandableQueryOfClass (this is an internal class in LinqKit which I made public, so I can't do the cast if I'm referencing the Nuget package).
Is this a bug in LinqKit or am I doing something wrong?
Here is my test code.
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Internal.DAL.Db;
using Internal.Models.Customer;
using LinqKit; // Referencing LinqKit.Microsoft.EntityFrameworkCore
using Xunit;
namespace Internal.EntityFramework.Tests
{
public class UnitTest1
{
private DbContextOptionsBuilder<DataContext> _ctxBuilder =>
new DbContextOptionsBuilder<DataContext>().UseSqlServer(Connection.String);
[Fact]
public async Task SuccessTest()
{
using (var ctx = new DataContext(_ctxBuilder.Options))
{
var query =
(
// this cast is the only difference between the methods
(ExpandableQueryOfClass<Order>)
ctx.Orders
.AsExpandable()
)
.Include(r => r.Customer)
.Take(500);
var responses = await query.ToListAsync();
// this succeeds
Assert.All(responses, r => Assert.NotNull(r.Customer));
}
}
[Fact]
public async Task FailTest()
{
using (var ctx = new DataContext(_ctxBuilder.Options))
{
var query = ctx.Orders
.AsExpandable()
.Include(r => r.Customer)
.Take(500);
var responses = await query.ToListAsync();
// this fails
Assert.All(responses, r => Assert.NotNull(r.Customer));
}
}
}
}
Edit 2018-05-15: There is an open issue on the LinqKit github repository.
I'm not sure whether this is LINQKit or EF Core fault (definitely it's not yours).
For sure it's caused by the EF Core Include / ThenInclude implementations which all include a check for source.Provider is EntityQueryProvider and do nothing in case it's false.
I'm not sure what's the idea of EF Core designers - probably custom query providers to inherit from EntityQueryProvider, but at the same time the class is part of the infrastructure and marked as not supposed to be used.
I also have no idea how LINQKit is planning to address it, but as you noticed the current implementation definitely is broken/not working. At the moment it looks to me more like a WIP.
The only workaround I see at this time is to apply AsExpandable() after includes.

"Signature of the body and declaration in a method implementation do not match"

UPDATE: I think I've eliminated Unity from the equation. See below for more details.
UPDATE 2: I think I may have eliminated Entity Framework fro the equation. See below for more details.
I have some code that is building a unity container, but it started failing with the above error message out of the blue. It works on other people's machines, but not mine. I deleted the folder the solution was in and refreshed everything from source control to ensure I had nothing that could be causing issues (e.g. duplicate assemblies lying around from a previous build).
Here is part of my code:
public static class UnityBootstrapper
{
public static IUnityContainer Initialise()
{
Trace.WriteLine("UnityBootstrapper.Initialise()");
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
Trace.WriteLine("UnityBootstrapper.BuildUnityContainer()");
var container = new UnityContainer();
// Other dependencies are registered here
// If the following line is commented out the container is build
// but, obviously, it won't resolve this dependency.
container.RegisterType<IUserAccessEntities, UserAccessEntities>(WebRequestLifetime);
// Other dependencies are registered here
return container;
}
The code apparently fails on the call to BuildUnityContainer(), and I can see that the trace statement I put inside that method is never displayed.
However, if I comment out the line that registers the UserAccessEntities class (which was code generated from Entity Framework 5) then the container is built. Naturally, when I ask for that dependency it can't resolve it, so the code just fails elsewhere.
I've Googled for solutions and they all seem to resolve around generics and moving the generic type from the method to the class level. I can't do that as EF5 creates the class and it puts generics on the properties. e.g
DbSet<MyTable> Tables { get; set; }
The only other thing I can think of is that I've extracted an interface from the EF5 generated class called IUserAccessEntities and the problem could lie there... but I used ReSharper to generate that, so it should be perfectly aligned.
UPDATE
Just to eliminate Unity from the equation, I tried to new up the UserAccessEntities on its own
private static void TestUae()
{
var uae = new UserAccessEntities(); //container.Resolve<IUserAccessEntities>();
Trace.WriteLine("Got the entities: " + uae);
}
And the call to TestUae() fails instead.
UPDATE 2
I created a new class, AlternativeEntities based on the interface I'd previously extracted. When I try to construct that directly it has a new exception: Method 'Set' in type 'AlternativeEntities' from assembly 'UserAccess.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
However, it does. There are two methods called set, both of which I've given a basic implementation:
public class AlternativeEntities : IUserAccessEntities
{
public DbSet<TEntity> Set<TEntity>() where TEntity : class
{
Trace.WriteLine("public DbSet<TEntity> Set<TEntity>() where TEntity : class");
return null;
}
public DbSet Set(Type entityType)
{
Trace.WriteLine("public DbSet Set(Type entityType)");
return null;
}
// Other methods and properties here.
}

Asp.Net Web API Error: The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'

Simplest example of this, I get a collection and try to output it via Web API:
// GET api/items
public IEnumerable<Item> Get()
{
return MyContext.Items.ToList();
}
And I get the error:
Object of type
'System.Data.Objects.ObjectQuery`1[Dcip.Ams.BO.EquipmentWarranty]'
cannot be converted to type
'System.Data.Entity.DbSet`1[Dcip.Ams.BO.EquipmentWarranty]'
This is a pretty common error to do with the new proxies, and I know that I can fix it by setting:
MyContext.Configuration.ProxyCreationEnabled = false;
But that defeats the purpose of a lot of what I am trying to do. Is there a better way?
I would suggest Disable Proxy Creation only in the place where you don't need or is causing you trouble. You don't have to disable it globally you can just disable the current DB context via code...
[HttpGet]
[WithDbContextApi]
public HttpResponseMessage Get(int take = 10, int skip = 0)
{
CurrentDbContext.Configuration.ProxyCreationEnabled = false;
var lista = CurrentDbContext.PaymentTypes
.OrderByDescending(x => x.Id)
.Skip(skip)
.Take(take)
.ToList();
var count = CurrentDbContext.PaymentTypes.Count();
return Request.CreateResponse(HttpStatusCode.OK, new { PaymentTypes = lista, TotalCount = count });
}
Here I only disabled the ProxyCreation in this method, because for every request there is a new DBContext created and therefore I only disabled the ProxyCreation for this case .
Hope it helps
if you have navigation properties and you do not want make them non virtual, you should using JSON.NET and change configuration in App_Start to using JSON not XML!
after install JSON.NET From NuGet, insert this code in WebApiConfig.cs in Register method
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
If you have navigation properties make them non virtual. Mapping will still work but it prevents the creation of Dynamic Proxy entities which cannot be serialized.]
Not having lazy loading is fine in a WebApi as you don't have a persistent connection and you ran a .ToList() anyway.
I just disabled proxy classes on a per needed basis:
// GET: ALL Employee
public IEnumerable<DimEmployee> Get()
{
using (AdventureWorks_MBDEV_DW2008Entities entities = new AdventureWorks_MBDEV_DW2008Entities())
{
entities.Configuration.ProxyCreationEnabled = false;
return entities.DimEmployees.ToList();
}
}
Add the following code in Application_Start function of Global.asax.cs:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
This instruct the API to serialize every response into JSON and remove XML responses.
In my case the object being returned had a property within it with a type that did not have an argumentless/default constructor. By adding a zero-argument constructor to that type the object could be serialized successfully.
I had the same problem and my DTO was missing an parameter less constructor.
public UserVM() { }
public UserVM(User U)
{
LoginId = U.LoginId;
GroupName = U.GroupName;
}
First constructor was missing.
I got this error message and it turns out the problem was that I had accidentally set my class to use the same serialized property name for two properties:
public class ResultDto
{
//...
[JsonProperty(PropertyName="DataCheckedBy")]
public string ActualAssociations { get; set; }
[JsonProperty(PropertyName="DataCheckedBy")]
public string ExpectedAssociations { get; set; }
//...
}
If you're getting this error and you aren't sending entities directly through your API, copy the class that's failing to serialize to LINQPad and just call JsonConvert.SerializeObject() on it and it should give you a better error message than this crap. As soon as I tried this it gave me the following error message: A member with the name 'DataCheckedBy' already exists on 'UserQuery+ResultDto'. Use the JsonPropertyAttribute to specify another name.
After disable Proxy Creation, use eager loading (Include()) to load the proxy object.
In my Project EntityCollection returned from the WebApi action method.
Configuration.ProxyCreationEnabled = false not applicable. I have tried the below approach it is working fine for me.
Control Panel.
2.Turn on Windows Features on or off
Choose Internet Information Service
Check all the World Wide Web Components it would be better to check all the components in IIS.
Install the components.
Go to (IIS) type inetmgr in command prompt.
select the published code in the Virtual directory.
Convert into application
Browse it the application.
The answer by #Mahdi perfectly fixes the issue for me, however what I noticed is that if my Newtonsoft.JSON is 11.0 version then it doesn't fix the issue, but the moment I update Newtonsoft.JSON to latest 13.0 it starts working.

MEF Composition .NET 4.0

Thanks in advance for your assistance. I have the following exported part:
[Export (typeof(INewComponent))] // orignally tried just [Export} here and importing NewComponent below
public class NewComponent : INewComponent
{
// does stuff including an import
}
The Console test program imports the above:
public class Program
{
[Import] // have tried variations on importing "NewComponent NewComponent" etc
public INewComponent NewComponent
{
get;
set;
}
public static void Main(string[] args)
{
var p = new Program();
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
var container = new CompositionContainer(catalog);
container.ComposeParts(p);
}
The Composition fails with these CompositionExceptions (I removed the namespace to protect the guilty :)):
1) No valid exports were found that match the constraint
'((exportDefinition.ContractName == "INewComponent") AndAlso
(exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso
"INewComponent".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))',
invalid exports may have been rejected.
The Composition works successfully if I do the composition in the main program like this:
public class Program
{
public static void Main(string[] args)
{
INewComponent newComponent = new NewComponent();
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
var container = new CompositionContainer(catalog);
container.ComposeParts(newComponent);
}
}
Thank You
Is your Exported part contained in the same Assembly as Program? If it is in a separate DLL, you need to include that Assembly in your catalog as well, like this:
var aggregateCatalog = new AggregateCatalog();
aggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
aggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(NewComponent).Assembly));
var container = new CompositionContainer(aggregateCatalog);
// etc...
If that's doesn't work, then there is a nice open source tool called Visual MEFx that can help you analyze your catalog. Here is a short article about setting it up:
Getting Started With Visual MEFx
In your NewComponent class you wrote this:
// does stuff including an import
If there is a problem with that unshown import, then MEF will complain about the Program.NewComponent import instead of the actual deeper cause. This is called "stable composition". Stable composition can be useful, but it also complicates the debugging of a failed composition.
You can follow the instructions in the MEF documentation about Diagnosing Composition Errors to home in on the actual cause.
In a small program, you can also try to call container.GetExportedValue<ISomeExport>() for a few exports until you find the one that is causing problems.

MEF Contrib Provider Model Not Importing Parts

I have been trying to use the configurable provider model for handling my MEF imports and exports from MEF Contrib (link). I've read the Codeplex documentation and Code Junkie's blog post (link); however, I can't seem to get the container to create the parts. Where am I going wrong?
Program.cs
namespace MEFTest
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
// [ImportMany("command", typeof(IHelp))]
public IEnumerable<IHelp> Commands { get; set; }
void Run()
{
Compose();
foreach(IHelp cmd in Commands)
{
Console.WriteLine(cmd.HelpText);
}
Console.ReadKey();
}
void Compose()
{
var provider = new ConfigurableDefinitionProvider("mef.configuration");
var catalog = new DefinitionProviderPartCatalog<ConfigurableDefinitionProvider>(provider);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}
TestCommand.cs
namespace MEFTest
{
//[Export("command", typeof(IHelp))]
public class TestCommand : IHelp
{
private string _helpText = "This is a test.";
public string CommandName
{
get { return "Test"; }
}
public string HelpText
{
get { return _helpText; }
}
}
}
App.Config section:
<mef.configuration>
<parts>
<part type="MEFTest.TestCommand, MEFTest">
<exports>
<export contract="IHelp" />
</exports>
</part>
<part type="MEFTest.Program, MEFTest">
<imports>
<import member="Commands" contract="IHelp" />
</imports>
</part>
</parts>
</mef.configuration>
I don't get any build errors and it runs fine if I switch to the typical attribute-based system that is part of the MEF core (with the appropriate catalog too). Program.Commands is always NULL in the above example. I tried to just use a singular property instead of a collection and get the same results.
When I debug I can get the provider.Parts collection so I know it's accessing the configuration information correctly; however, I get an InvalidOperationException whenever I debug and try to drill into catalog.Parts.
Anyone have any experience as to where I'm going wrong here?
As documented here, you also need this in your config file:
<configSections>
<section
name="mef.configuration"
type="MefContrib.Models.Provider.Definitions.Configurable.PartCatalogConfigurationSection, MefContrib.Models.Provider" />
</configSections>
If you already have that, then it might be interesting to show us the stack trace of the InvalidOperationException that you get when accessing provider.Parts.
I had the same problems and could not get it to work, but here are some details:
It seems that ComposeParts() does not work as expected (at least in the version I used) because it uses static methods, based on Reflection to find all required Imports (so it seems that this part cannot be changed from outside of MEF). Unfortunately we want to use xml configuration and not the MEF attributes.
It works if you add [Import] attributes to the members of the class you you use with ComposeParts(). In your case this would be "Programm". In this case all exports defined in the configuration file will be found.
I could not find any documentation or examples on the MEF Contrib page relating to that problem. Also there is no unittest in the MEF contrib projekt that uses ComposeParts().
A workaround would be to use container.GetExportedValues() to retrieve the values, but in this case you have to set the classes members manually.
Hope that helps.