MVC Deserialization Error - c#

Okay. This is my company's customer portal, it's an MVC 2 project. We have a back end SAP system that the portal draws data from. But it does not directly hit SAP, it sends an xml request to a VB app that gets the data and sends it back in an xml response. There is an interface IRequest that all the various requests implement examples would be CustomerNumberRequest, CompanyNameRequest, etc. These all implement the method ToXml which as the name suggests simply builds xml to send. All of the existing requests work fine. (Let me preface this by saying that I inherited this project and the guy who wrote it is no longer with us) I am now trying to send a request to get the Rep Groups from SAP. I basically copied one of the other requests verbatim, making the necessary tweaks to send the appropriate request. But it keeps failing with error messages that I don't understand:
The formatter threw an exception while
trying to deserialize the message:
There was an error while trying to
deserialize parameter
http://tempuri.org/:request. The
InnerException message was 'The
deserializer cannot load the type to
deserialize because type
'XXXXX.CustomerPortal.Domain.RepGroupRequest'
could not be found in assembly
'XXXXX.CustomerPortal.Domain,
Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'. Check that the
type being serialized has the same
contract as the type being
deserialized and the same assembly is
used.'. Please see InnerException for
more details.
This error happens right at _communicationService.ProcessRequest(request); (shown below) It does not enter the ProcessRequest method it just tries to create a NetDataContractSerializer here:
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
{
return new NetDataContractSerializer();
}
and then it dies. These are the methods being called:
private void PopulateRepGroups()
{
List<string> repGroups = new List<string>();
RepGroupRequest request = new RepGroupRequest();
foreach (RepGroup repGroup in _repService.GetRepGroups(request))
repGroups.Add(repGroup.RepGroupName);
ViewData["RepGroups"] = new SelectList(repGroups);
}
public List<RepGroup> GetRepGroups(RepGroupRequest request)
{
string response = _communicationService.ProcessRequest(request);
return RepGroupResponseFactory.GetRepGroupResponse(response);
}
Can anybody tell me what this error message is telling me? It says the type cannot be found but the type should be IRequest (that's what it says when the CreateSerializer is hit) which is used all over this. I'm clearly lost, please help!

Quoting your exception
Check that the type being serialized has the same contract as the type being deserialized and the same assembly is used
Check the version of the library on both ends that CustomerPortal.Domain.RepGroupRequest resides in to make sure they are the same version exactly.

Related

How can I serialize a Collection to send it using WCF?

I am trying to send a object via WCF as parameter in this method:
[OperationContract]
bool SendProject(Project project);
and I got this if i try to call it from client:
There was an error while trying to serialize parameter project. The InnerException message was 'Type 'System.Collections.ObjectModel.Collection`1[[System.Collections.DictionaryEntry, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'
with data contract name 'ArrayOfDictionaryEntry:http://schemas.datacontract.org/2004/07/System.Collections' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example,
by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.
Please see InnerException for more details.
I search some info and I think that the error is how I serialize a class (a class from Dr. WPF) which is inside "project" class:
#region ISerializable
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
Collection<DictionaryEntry> entries = new Collection<DictionaryEntry>();
foreach (DictionaryEntry entry in _keyedEntryCollection)
entries.Add(entry);
info.AddValue("entries", entries);
}
#endregion ISerializable
The problem is that I dont know where to put the tag "KnownType" or how to serialize correctly this Dictionary to send it as parameter using WCF.
Thanks!
I have the solution, which is not so clean but is a solution.
As dbc said, updating DictionaryEntry to KeyValuePair<TKey,TValue> is a recommended step, but what fixed my problem was set [KnownType(typeof(Collection<KeyValuePair<TypeX, TypeY>>))] in the class where the serialization is.

Generating WCF web service (SOAP) from WSDL to accept/return XML rather than serialized types

I have a large WSDL file that I need to generate a WCF Web service from. I can generate a service using svcutil.exe, however it's not generating what I need.
I need a service that accepts/returns XML, rather than serialized types. The reason for this is if there is an error in the incoming XML it will fail before it hits my code - we can't have this. We need to intercept the XML before any serialization happens to catch it.
Is this possible?
Or is there a way I can modify the generated services so I can work with the raw XML rather than the derived "Message" type?
Effecitvely I want something similar to:
XmlDocument PersonRevised(XmlDocument request);
Current code:
[ServiceContract(Namespace = "urn:hl7-org:v3")]
public interface IPRPA_AR101202
{
[OperationContract(Name = "PersonRevised", Action = "urn:hl7-org:v3/PRPA_IN101204")]
PersonRevisedResponse PersonRevised(Message request);
}
public class PRPA_AR101202 : WCFServiceBase, IPRPA_AR101202
{
PersonRevisedResponse IPRPA_AR101202.PersonRevised(Message request)
{
PersonRevised pr = this.ParseMessage<PersonRevised>(request, HL7_XML_NAMESPACE);
PersonRevisedResult result = new PersonRevisedResult();
PersonRevisedResponse r = new PersonRevisedResponse(result);
return r;
}
}
update:
Based on the answer I was able to create a WCF service that accepted a string, however now I am getting null on the implemented services that are based off of WSDL contracts( on the input parameter); regardless of whether it's a string or an XmlDocument/XmlNode.
Thoughts?
I need a service that accepts/returns XML, rather than serialized
types
In that case you are better off using POX and not using SOAP/WSDL at all. There are some resources for this here and here.
The reason for this is if there is an error in the incoming XML it
will fail before it hits my code - we can't have this.
I kind of know what you're saying here. It is annoying that any serialization exceptions will kill the channel rather than bubble back to the client, however, the whole point of exposing a service metadata endpoint is that clients will always serialize types which are exposed outside the service boundary correctly because that's what the WSDL is supposed to be for.
Effecitvely I want something similar to: XmlDocument
PersonRevised(XmlDocument request);
As you are no doubt aware, exposing a XmlDocument type is not equivalent to exposing XML. Exposing XmlDocument will not be pretty.
If you absolutely need full control over the deserialization, you will have to expose your operation as accepting a parameter of type string. Then you can do what you want with it.
public string PersonRevised(string request)
{
// Deserialize here...
}

What causes a cast object type issue?

I am trying to create a webAPI with Visual Studio 2012. I've followed the provided Microsoft ASP.NET tutorial.
So I've got the class, repository and controller down. The software is able to to run and connect with the database. When I run and make the API call, this error occurs:
Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery`1[ReservationsAPI.Contact]' to type 'System.Collections.Generic.IEnumerable`1[ReservationsAPI.Models.Contacts]'.
This error occurs in the method below in my repository file:
public IEnumerable<Contacts> GetAll()
{
var ContactsAll = from c in rdbc.Contacts select c;
return (IEnumerable<Contacts>)ContactsAll;
}
The error occurs at the return line. I am not sure how to deal with this error.
In your method's return type, change the type Contacts to Contact without the s. You can see this in the error message that it needs to be Contact.

Problem with c# webservice, referencing a method and a type

I have run into a bit of a problem, well not sure if it is a problem, but would like some advice.
I have developed a c# webservice in vs2010 and when I debug the service i get this error in my browser
The XML element 'VoucherResponse' from namespace 'http://test.org/' references a method and a type. Change the method's message name using WebMethodAttribute or change the type's root element using the XmlRootAttribute.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The XML element 'VoucherResponse' from namespace 'test.org' references a method and a type. Change the method's message name using WebMethodAttribute or change the type's root element using the XmlRootAttribute.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Now looking at my code in at the actual class "VoucherResponse" i have,
public class VoucherResponse : AResponse
{
public Voucher Voucher { get; set; }
}
And the Voucher object looks like this
public class Voucher
{
public string PIN { get; set; }
public string Serial { get; set; }
public string Batch { get; set; }
}
Now in one of my web methods I return the VoucherResponse and I am assuming that this error occurs when it is reflected through and checked.
Has anyone had a similar problem with this before, or can anyone give me some advice on this?
Thanks
I found another case that raises the error! Here's my code:
[WebMethod]
public CheckUpdateResponse CheckUpdate()
{
...
}
Ok, let me explain: CheckUpdateResponse is a structure I defined in my code, CheckUpdate() is a method. So, in the WSDL .NET add automatically a Response suffix to the method name CheckUpdate.
Et voilĂ : it finds a duplicate element and gives the error "Change the method's message name using WebMethodAttribute..."
Solution? I renamed the returned type from CheckUpdateResponse to CheckUpdateResult and now everything works fine!
I hope this will help someone! I lost a lot of time on this...
Apparently, SOAP cannot handle methods that have the same name as their return type.
You can fix it by reading the error, and acting accordingly:
public class VoucherResponse
{
[WebMethod(MessageName="TheVoucher")]
public Voucher Voucher{get; set;}
}
I had the same issue, but in my case; the application that I developed is web service client, so I don't have control on changing the WSDL\Schema.
The problem was that I had one web service with 17 operations, all of them are returning the same complex type, I got the mentioned error due to deserialization of the return type, because .Net is wrapping the return type for each output, and the serializer is throwing error:
The XML element 'XYZ' from namespace 'ABC' references a method and a type. Change the method's message name using WebMethodAttribute or change the type's root element using the XmlRootAttribute.
Solution:
I opened Reference.cs file, removed all wappered return type generated classes, and kept only one, then changed its class name to be generic, not related to the operation, it worked for me.

WCF AddServiceReference causing custom tool error, not producing proxy

A problem with "Add Service Reference", and actually with SvcUtil over all its features.
In order to reproduce you just need to add an OperationContract with argument or returning the following class :
[XmlSchemaProvider("MySchema")]
public class MyStructure : IXmlSerializable
{
private XmlElement e;
private static void Func(object o, ValidationEventArgs args)
{
}
public static XmlQualifiedName MySchema(XmlSchemaSet xs)
{
//xs.XmlResolver = new XmlUrlResolver();
XmlSchema s = XmlSchema.Read(new XmlTextReader(new StringReader("<?xml version=\"1.0\"?><xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"><xs:complexType name=\"MyStructure\"><xs:sequence><xs:any /></xs:sequence></xs:complexType></xs:schema>")), null);
xs.Add(s);
return new XmlQualifiedName("MyStructure");
}
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
XmlDocument doc = new XmlDocument();
e = (XmlElement)doc.ReadNode(reader);
}
public void WriteXml(XmlWriter writer)
{
e.WriteTo(writer);
}
#endregion
}
The result is that when you use AddWebReference or AddSerivceReference without a reference to the class library containing the MyStructure type, everything will be fine ad you will get an xmlElement representation at the auto created proxy.
However, when you have a reference you will get the following warning :
================
Warning 1 Custom tool warning: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: Referenced type 'ServiceLibrary.MyStructure, ServiceLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' with data contract name 'MyStructure' in namespace '' cannot be used since it does not match imported DataContract. Need to exclude this type from referenced types.
XPath to Error Source: //wsdl:definitions[#targetNamespace='http://tempuri.org/']/wsdl:portType[#name='IService1'] \Projects\WCFSample\WCFExample\TestAddReference\Service References\ServiceReference1\Reference.svcmap 1 1 TestAddReference
======================
And no proxy will be generated for you.
Now, the internet is full with descriptions of this when you have a generic DataContract, and/or using IsReference attribute.
This is a much serious problem, since any non-typed data will do this problem.
Could not find any way to solve the problem. What if I want to know the type at the client side, by sharing the class library of the contracts ?
This type of exception generally means there is at least one difference in the type contracts generated by the service as compared to the referenced types (as the message indicates!). But it may not be obvious at first glance, as I found out. Make sure all nested and referenced types are up to date with the server. In my case, nested types were updated on the server. I thought I had updated by locally referenced assembly (and the shared reference types) but I missed some. It took close examination to find the culprit.
See additional information in this question
I have a suggestion:
I had similar errors, including:
the .svcmap file cannot be found. It may have been moved or deleted. To generate a new .svcmap file, delete the service reference and add it again.
And at that point, no way to delete the service reference unless I close VS2010 and open it again.
The situation is: my WCF service is running, I programmatically added a Description.ServiceMetadataBehavior at an HTTP address that I define.
In VS2010, I try to add a service reference at the HTTP address, I see my service, I add the reference, and voila, errors and warning.
The problem: my HTTP address is containing some key words that WCF doesn't like. Specifically the word COM (it breaks with LPT too).
So my solution: modify my HTTP address not to have the word COM. It worked for me.
If the service is hosted over HTTPS, go into the server's IIS Manager. Under "SSL Settings" for the site, make sure "Require SSL" is checked, and check the Client Certificates radio button for "Accept".

Categories