RavenDB Serialization of NameValueCollection - ravendb

We are trying to implement a custom logger for Elmah to log errors in a RavenDB database in an MVC5 application.
The Logging works perfectly but when we try to read the logs we get an exception for all properties of the Error Class that are of type NameValueCollection with the following error :
Cannot populate list type System.Collections.Specialized.NameValueCollection. Path 'Error.ServerVariables'.
If we look at the json properties in the Ravendb document we can see that they have been stored as Arrays which is causing the problem. Is there any way to fix this.
Any assistance would be greatly appreciated

You can use a JsonConverter to serialize/desieralize this propertly

Related

Is it possible in ASP.NET Core to enable XmlSerialization for a single controller

I have a Web API that has several controllers, one of which returns XML for legacy reasons, while all the others return JSON.
In a .NET Framework I can selectively enable XML serialization for a single controller by accessing HttpControllerSettings.Formatters (typically in an attribute used to decorate the controller).
Is it possible to do the same in ASP.NET Core, i.e. only enable Xml serialization for a single controller?
The only way I've found to enable Xml serialization in ASP.NET Core 2.1 is globally, using:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddXmlSerializerFormatters();
This works OK, but has a side-effect that I consider to be undesirable: when I run the application in Visual Studio I see a trace of an warning from XmlSerializerOutputFormatter something like:
Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerOutputFormatter:Warning: An error occurred while trying to create an XmlSerializer for the type 'MyApp.MyModel'.
System.InvalidOperationException: There was an error reflecting type 'MyApp.MyModel'. ---> System.InvalidOperationException: Cannot serialize member ... see inner exception for more details. ---> System.NotSupportedException: Cannot serialize ... because it is an interface.
--- End of inner exception stack trace ---
at System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc, MemberInfo member, Type type)
...
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type)
at Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerOutputFormatter.CreateSerializer(Type type)
It appears to be trying to create an XmlSerializer for a Type that is not used by my "XML" controller.
While it's not a showstopper, I'd prefer not to be creating XmlSerializers except when I need them.
I've encountered the same issue. I do not believe there is a solution at the moment, so I've created a feature request on the Github project.
In the meantime, I've set
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerOutputFormatter": "Error"
}
}
To suppress the warnings during startup.
I've encountered the same issue.Then I changed my code:
builder.Services.AddControllers().AddNewtonsoftJson().AddXmlSerializerFormatters();
U can check this one out, I hope it's has been helpful.

Error casting soap XML to BankData type

Just starting to investigate the Yodlee soap example and I am having problems with an
Unable to cast object of type 'System.Xml.XmlNode[]' to type 'BankData'.
error in the DisplayBankData class. I have tried downloading and creating the Yodlee dll from the wdsl definitions from 2014Q3WSDLs as well as using the DLL that came with the download with no success. The same problem is also happening with the CardData class (and possibly others)
Am I missing something or is there a problem with the wsdl definitions supplied?
After spending many hours trying to work out whats going on here, I have finally worked out that there is something wrong with either the WDSL files generated by Yodlee, or the way that WSDL.exe interprets the WSDL files.
The actual cause of it is because the WSDL does not seem to indicate what type is returned under ItemData1.Accounts, this is because it can be either BankData or CardData, since VisualStudio does not know what type to expect, it de-serialises the object as an XML node.
The way I have managed to get round this is when you use the WSDL.exe to produce the yodleeProxies.vb file, you will need to go into the generated file and then find the defenition for the ItemData1 Class
Partial Public Class ItemData1
You will need to change
Public Property accounts As Object()
to
Public Property accounts As BankData()
Then it knows that the object will be of type BankData
I have also added a new property that expects CardData so that CardData will appear under this one, and will de-serialise correctly
Public Property accounts2 As CardData()
Get
Return Me.accountsField
End Get
Set(value As CardData())
Me.accountsField = value
End Set
End Property
So thats my hack on how to resolve it, if any one else has worked out a more elegant way of getting round this, please do let me know.
I found adding the XmlInclude() attribute below to the ItemData1 class in the proxy file glyn johnston mentioned solves the issue - apparently the deserializer doesn't know to consider ItemAccountData and its descendants when deserializing that property.
I believe 'accounts' should be kept as an array of objects as there are several types that inherit from ItemAccountData including CardData, BankData and others, and upon inspecting the WSDL directly 'accounts' appears to be defined as a 'List' of type 'anyType'.
It is possible it is defined this way to allow for adding newer types in the future without causing de-serialization issues, so basically you need to inspect each element in the array and determine its type individually, ignoring the types you do not know or care about.
...
[System.Xml.Serialization.XmlInclude(typeof(ItemAccountData))]
public partial class ItemData1 {
...
I believe the source of the problem is the Xml deserializer doesn't consider types that aren't somehow tied to the definition of the class ItemData1 via its method signatures, properties etc. and the XmlInclude() is the attribute to use to fix that.

WCF Saving EF 4.1 item throws exception An item cannot be added to a fixed size Array of type

I have searched google and exhausted a fair bit of my time trying to figure out what is going on with my WCF and client Windows form app.
I am continuously getting the following error
"Unable to set field/property Ingredients on entity type Datalayer.UnitOfMeasure. See InnerException for details."
...
inner exception is
"An item cannot be added to a fixed size Array of type 'Datalayer.Ingredient[]'."
Stack Trace -
at System.Data.Objects.Internal.PocoPropertyAccessorStrategy.<AddToCollection>b__0[T](Object collectionArg, Object item)
at System.Data.Objects.Internal.PocoPropertyAccessorStrategy.CollectionAdd(RelatedEnd relatedEnd, Object value)
The way I have configured my solutions I have a WCF web-service which reference my DataLayer class library, I have a windows app (test app) which references the WCF services as well as DataLayer project.
If I don't reference the DataLayer in my test app, this issues does not occur however I lose the ICollection<Ingredient> to simple Ingredient[] array. Now as you can see this becomes a coding pain to initialize the array every time.
Any idea anyone? thanks in advance.
I was running into this exact error, but the accepted answer wasn't quite the solution I needed. It turns out that the client was sending a List<Order> up to my WCF service, but since the Customer.Orders property was defined as an ICollection<Order>, the WCF deserializer deserializer just deserialized it in the simplest form it could, which was an array of type Order, i.e., Order[].
The only solution I was able to come up with was to change the property in question on my POCO objects from an ICollection<Order> to a HashSet<Order>. See Stop WCF Deserializing Empty ICollection into Zero Capacity Array for a few more details.
When you are adding reference to WCF service in the test using 'Add Service Reference' there is a option to configure the default collection type for the generate proxy on the client. The default i think is array, you can change it to a generic list.
In case you are using svcutil,that too allows the same thing.
Weird. I had this same error, and was doing the right thing, calling "ToArray()". Changed it to "ToList()" and it started working fine.

Creating a log for WCF operations / getting app directory

I want my WCF service to log errors / operations, etc.
I have a very simple logging class but finding the directory to create / write to is returning a null reference exception:
public static string Path()
{
return Path.GetDirectoryName
(Assembly.GetEntryAssembly().Location);
}
This works in say a console app but not WCF, perhaps there is a different convention?
Or alternatively are there any simple libraries for logging in WCF?
WCF has built-in message logging, following links should help you.
http://msdn.microsoft.com/en-us/library/ms730064.aspx
http://geekswithblogs.net/mnf/archive/2008/10/03/use-wcf-message-logging.aspx
http://mkdot.net/blogs/dejan/archive/2008/10/23/wcf-tracing-and-message-logging.aspx

How to serialize SubSonic generated class?

I'm trying to use SubSonic with WCF. I can get data into List but I can't return that data to client side, its error is
The socket connection has been disposed. Object name:
'System.ServiceModel.Channels.SocketConnection'.
I try to send and retrieve data to/from WCF by POCO object and it working but when I try to use generated class from SubSonic it don't work anymore, so I think its has some problem.
I would assume that this is not the "real" exception. I am not familiar with WCF but maybe you find something in the logs.
Here is an article about debugging WCF http://www.codeproject.com/KB/WCF/DebugWCFApps.aspx
Most likely WCF is trying to serialize a SubSonic class with nullable properties.
Properties of SubSonic classes are marked as XMLAttribute, which throws an error if you want to serialize a nullable type. Nullables can only be serialized as XMLElements.
Try if it works with a SubSonic generated class that has no nullable property.
After I've downloaded source code of SubSonic and debug into it SubSonic.Core, I found that it error because GetBody<> will create instance of that class, and inside its constructor is trying to connect to database which it can't; client has no access to database.
Now I'm working on create mapping class with SubSonic and return POCO instead.