I am trying to integrate Fedex Service in my asp.net website. I have downloaded the code from the Fedex website, but when I run this simple program I get an error,
Check the following Code:
static void Main(string[] args)
{
TrackRequest request = CreateTrackRequest();
TrackService service = new TrackService();//I get Error Here
if (usePropertyFile())
{
service.Url = getProperty("endpoint");
}
try
{
// Call the Track web service passing in a TrackRequest and returning a TrackReply
TrackReply reply = service.track(request);
if (reply.HighestSeverity == NotificationSeverityType.SUCCESS || reply.HighestSeverity == NotificationSeverityType.NOTE || reply.HighestSeverity == NotificationSeverityType.WARNING)
{
ShowTrackReply(reply);
}
ShowNotifications(reply);
}
catch (SoapException e)
{
Console.WriteLine(e.Detail.InnerText);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine("Press any key to quit!");
Console.ReadKey();
}
The Following error on debugging occurred on TrackService service = new TrackService(); (line #5):
Unable to generate a temporary class (result=1).
error CS0029: Cannot implicitly convert type
'TrackWebServiceClient.TrackServiceWebReference.EMailNotificationEventType' to
'TrackWebServiceClient.TrackServiceWebReference.EMailNotificationEventType[]'
This might be an issue with the way that WSDL.exe generates the client code.
You will have to manually edit Reference.cs file to replace double brackets [][] to single [] in EmailNotificationEventType definition.
From Microsoft:
There is no resolution available at this point. However, three workarounds are available:
You can generate the proxy class manually by using WSDL.exe and then change the proxy class in which the data type was inappropriately created as a two-dimensional array (for example, "CustomType[][]") so that it is a single-dimensional array (for example, "CustomType[]").
You can change the data type in the desired Web Services Description Language (WSDL) so that a second, optional element is included in the definition. You can do this by adding an element such as the following:
<xs:element minOccurs="0" name="dummyElement" nillable="true" type="xs:string"/>
You can change the complex type in the desired WSDL so that the boundary attributes are part of the complex type instead of being part of the element. (That is, you can move the minOccurs and maxOccurs attributes to the complex type and then remove them from the element.)
Check also this link for further explanation.
I tried the third option "You can change the complex type in the desired WSDL so that the boundary attributes are part of the complex type instead of being part of the element. (That is, you can move the minOccurs and maxOccurs attributes to the complex type and then remove them from the element.)" and it worked. The solution below:
Removed from the WSDL the minOccurs and maxOccurs for the NotificationEventsAvailable element [see the image below]
Related
Is there something I need to configure in the XmlReaderSettings to encourage .net (4.8, 6, 7) to handle some cXML without throwing the following exception:
Unhandled exception. System.Xml.Schema.XmlSchemaException: The parameter entity replacement text must nest properly within markup declarations.
Sample cXML input
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.041/cXML.dtd">
<cXML payloadID="donkeys#example.com" timestamp="2023-02-13T01:01:01Z">
<Header>
</Header>
<Request deploymentMode="production">
</Request>
</cXML>
Sample Application
using System.Xml;
using System.Xml.Linq;
namespace Donkeys
{
internal class Program
{
static void Main()
{
XmlReaderSettings settings = new()
{
XmlResolver = new XmlUrlResolver(),
DtdProcessing = DtdProcessing.Parse,
ValidationType = ValidationType.DTD,
};
FileStream fs = File.OpenRead("test.xml"); // sample cXML from question
XmlReader reader = XmlReader.Create(fs, settings);
XDocument.Load(reader); // this blows up
}
}
}
I'm looking to use the XmlUrlResolver to cache the DTDs but without ignoring the validation I get the error above but i'm not really sure why?
So far I've tried different validation flags but they don't validate at all unless I use ValidationType.DTD which goes pop.
The actual resolver seems to work fine; if I subclass it, it is returning the DTD (as a MemoryStream) as expected.
I can add an event handler to ignore the issue but this feels lamer than I'd like.
using System.Xml;
using System.Xml.Linq;
namespace Donkeys
{
internal class Program
{
static void Main()
{
XmlReaderSettings settings = new()
{
XmlResolver = new XmlUrlResolver(),
DtdProcessing = DtdProcessing.Parse,
ValidationType = ValidationType.DTD,
IgnoreComments = true
};
settings.ValidationEventHandler += Settings_ValidationEventHandler;
FileStream fs = File.OpenRead("test.xml");
XmlReader reader = XmlReader.Create(fs, settings);
XDocument dogs = XDocument.Load(reader);
}
private static void Settings_ValidationEventHandler(object? sender, System.Xml.Schema.ValidationEventArgs e)
{
// this seems fragile
if (e.Message.ToLower() == "The parameter entity replacement text must nest properly within markup declarations.".ToLower()) // and this would be a const
return;
throw e.Exception;
}
}
}
I've spent some time over the last few days looking into this and trying to get my head around what's going on here.
As far as I can tell, the error The parameter entity replacement text must nest properly within markup declarations is being reported incorrectly. My understanding of the spec is that this message means that you have mismatched < and > elements in the replacement text of a parameter entity in a DTD.
The following example is taken from this O'Reilly book sample page and demonstrates something that genuinely should reproduce this error:
<!ENTITY % finish_it ">">
<!ENTITY % bad "won't work" %finish_it;
Indeed the .NET DTD parser reports the same error for these two lines of DTD.
This doesn't mean you can't have < and > characters in parameter entity replacement text at all: the following two lines will declare an empty element with name Z, albeit in a somewhat round-about way:
<!ENTITY % Nested "<!ELEMENT Z EMPTY>">
%Nested;
The .NET DTD parser parses this successfully.
However, the .NET DTD parser appears to be objecting to this line in the cXML DTD, which defines the Object.ANY parameter entity:
<!ENTITY % Object.ANY '|xades:QualifyingProperties|cXMLSignedInfo|Extrinsic'>
There are of course no < and > characters in the replacement text, so the error is baffling.
This is by no means a new problem. I found this unanswered Stack Overflow question which basically reports the same problem. Also, this MSDN Forum post basically has the same problem, and it was asked in 2007. So is this unclear but intentional behaviour, or a bug that has been in .NET for 15+ years? I don't know.
For those who do want to look into things further, the following is about the minimum necessary to reproduce the problem. The necessary C# code to read the XML file can be taken from the question and adapted, I don't see the need to repeat it here:
example.dtd:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT A EMPTY>
<!ENTITY % Rest '|A' >
<!ELEMENT example (#PCDATA %Rest;)*>
example.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example SYSTEM "example.dtd">
<example/>
There are various ways to tweak this to get rid of the error. One way is to move the | character from the parameter entity into the ELEMENT example declaration. Replacing #PCDATA with another element (which you would also have to define) is another way.
But enough of the theory behind the problem. How can you actually move forwards with this?
I would take a local copy of the cXML DTD and adjust it to work around this error. You can download the DTD from the URL in your sample cXML input. The %Object.ANY; parameter entity is only used once in the DTD: I would replace this one occurrence with the replacement text, |xades:QualifyingProperties|cXMLSignedInfo|Extrinsic.
You then need to adjust the .NET XML parser to use your modified copy of the cXML DTD instead of fetching the the one from the given URL. You create a custom URL resolver for this, for example:
using System.Xml;
namespace Donkeys
{
internal class CXmlUrlResolver : XmlResolver
{
private static readonly Uri CXml1_2_041 = new Uri("http://xml.cxml.org/schemas/cXML/1.2.041/cXML.dtd");
private readonly XmlResolver urlResolver;
public CXmlUrlResolver()
{
this.urlResolver = new XmlUrlResolver();
}
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
if (absoluteUri == CXml1_2_041)
{
// Return a Stream that reads from your custom version of the DTD,
// for example:
return File.OpenRead(#"SomeFilePathHere\cXML-1.2.401.dtd");
}
return this.urlResolver.GetEntity(absoluteUri, role, ofObjectToReturn);
}
}
}
This checks to see what URI is being requested, and if it matches the cXML URI, returns a stream that reads from your customised copy of the DTD. If some other URI is given, it passes the request to the nested XMLResolver, which then deals with it. You will of course need to use an instance of CXmlUrlResolver instead of XmlUrlResolver() when creating your XmlReaderSettings.
I don't know how many versions of cXML you will have to deal with, but if you are dealing with multiple versions, you might have to create a custom copy of the DTD for each version, and have your resolver return the correct local copy for each different URI.
A similar approach is given at this MSDN Forums post from 2008, which also deals with difficulties parsing cXML with .NET. This features a custom URL resolver created by subclassing XmlUrlResolver. Those who prefer composition over inheritance may prefer my custom URL resolver instead.
I want to integrate UPS service Locator.
I download from UPS website two XSD templates describing request and response. To generate c# classes I used XSD.exe tool. It generated two files for each template. In both classes are duplicated classes, which make errors, so I remove duplicated classes from one file.
Everything works, I obtain data from UPS API, but when I try to deserialize response to object LocatorResponse (class generated from XSD template) I get errors
Unable to generate a temporary class (result=1). error CS0030: Cannot
convert type 'string[]' to 'string' error CS0029: Cannot implicitly
convert type 'string' to 'string[]'
My code, I attach also generated class
string authBody = GetAuthString();
string accessPoint = GetAccessPointPostBody();
var response = GetResponseString(authBody + accessPoint);
using (TextReader reader = new StringReader(response))
{
// this line below makes problem
var serializer = new XmlSerializer(typeof(LocatorResponse));
// this line above makes problem
var result = (LocatorResponse)serializer.Deserialize(reader);
}
What I do wrong??
I need to pass several different varieties of user defined types as parameters to the same method in a WCF Service Application i.e. CompositeType, CompositeType2, CompositeType3, etc.
Here's the steps to reproduce:
Step 1. Launch Visual Studio 2010.
Step 2. Create a new "WCF Service Application" project.
Step 3. Build and run the project (Debug->Start Debugging from main menu or right click on project in Solution Explorer and click Debug->Start New Instance).
Results: A Web Browser will display the contents of the web folder.
Step 4. Add the following to the IService1.cs interface:
[OperationContract]
string GetDataAsObject(object value);
[OperationContract]
CompositeType GetDataUsingDataContractAsObject(object composite);
Step 5. Add the following to the Service1.svc.cs service:
public string GetDataAsObject(object value)
{
int tmpInt = -1;
tmpInt = (int)value;
return string.Format("GetDataAsObject Responded You entered: {0}", tmpInt);
}
public CompositeType GetDataUsingDataContractAsObject(object composite)
{
CompositeType tmpCompositeType;
tmpCompositeType = (CompositeType)composite;
if (tmpCompositeType == null)
{
throw new ArgumentNullException("composite");
}
if (tmpCompositeType.BoolValue)
{
tmpCompositeType.StringValue += "Suffix";
}
return tmpCompositeType;
}
Step 3. Add a new "Windows Forms Application" project to the solution.
Step 4. Right click on References in the Solution Explorer and Select "Add Service Reference" then click the Discover button then click OK.
Results: A Service Reference named ServiceReference1 is added to the project.
Step 5. Add a button to the form and in the click event add:
string tmpStr = string.Empty;
ServiceReference1.Service1Client tstServiceClient;
tstServiceClient = new ServiceReference1.Service1Client();
tmpStr = tstServiceClient.GetData(1);
tmpStr = tstServiceClient.GetDataAsObject(1);
tmpCompositeType = new ServiceReference1.CompositeType();
tmpCompositeType.BoolValue = true;
tmpCompositeType.StringValue = "Hello";
tmpStr = tstServiceClient.GetDataUsingDataContract(tmpCompositeType);
tmpStr = tstServiceClient.GetDataUsingDataContractAsObject(tmpCompositeType);
Step 6. Place a break point at tmpStr = tstServiceClient.GetData(1); then Run the forms app and click the button then step over the code.
Results: An exception occurs at
tstServiceClient.GetDataUsingDataContractAsObject(tmpCompositeType)
The exception while trying to deserialize the message:
There was an error while trying to deserialize parameter composite.
The InnerException message was 'Error in line 1 position 302.
Element 'http://tempuri.org/:composite' contains data from a type that maps to the name 'CompositeType'.
The deserializer has no knowledge of any type that maps to this name.
Consider using a DataContractResolver or add the type corresponding
to 'CompositeType' to the list of known types - for example,
by using the KnownTypeAttribute attribute or by adding it to the list
of known types passed to DataContractSerializer.'.
Please see InnerException for more details.
Adding the KnownTypeAttribute didn't work.
I want the minimum complexity required to make it work i.e. I don't want to replace the deserializer that is being used...I just want to fix this error,
"The deserializer has no knowledge of any type that maps to this name"
so that it knows what a CompositeType is. Is there something that I need to add to the CompositeType class? Is there anyway to let the deserializer know about the CompositeType type?
Shawn Zhao in the Social.MSDN.Microsoft.com forum provided the solution. Adding the ServiceKnownTypeAttribute to the OperationContract solves this problem:
[OperationContract]
[ServiceKnownType(typeof(CompositeType))]
CompositeType GetDataUsingDataContractAsObject(object composite);
The exception message suggested adding the KnownTypeAttribute to the DataContract which did not work. Thanks for your comments.
I am using System.Web.Helpers.Json to deserialize some JSON into dynamic in NET 4. The following line fails with this error: TypeInitializationException: Attempt by method 'System.Web.Helpers.Json..cctor()' to access method 'System.Web.Helpers.Json.CreateSerializer()' failed.
var json = Json.Decode(response);
The response is lengthy but valid JSON. What could be the matter here? I have tried LINQPad with a short handcrafted JSON and it worked. Is this a configuration issue of some sort?
[EDIT]
Here is the actual sample JSON. It appears the content is pretty much irrelevant. When this is run in a brand new Console application or LINQPad, it works as expected. But if you try to run the same code from a brand new Windows Forms application, it barfs with the above error.
var json = Json.Decode("{\"r\":{\"0\":{\"id\":\"2\"},\"1\":{\"id\":\"33\"}}}");
[EDIT2]
Actually, it turns out this has nothing to do with project types. The exception is thrown if the project is being debugged. If it is simply run, the exception does not occur. Strange, eh?
I forgot about this question and I found my answer in the meantime. I think it was somewhere on Microsoft's Connect site but I am not sure. So let's share it now.
Basically, in order to workaround this problem you need to make sure "Enable the Visual Studio hosting process" is unchecked in your project's settings under Debug. I am not sure why it's happening but this is definitely a way to "fix" it. I stopped searching for answers once I found out about this. It was good enough for me.
This can also happen if you are running in a partial trust.
Check the exception description here for possible reasons.
I don't know if this will apply to you, since you are not running in a web context, but this is what that link describes:
This exception is thrown in situations such as the following:
A private, protected, or internal method that would not be accessible from normal compiled code is accessed from partially
trusted code by using reflection.
A security-critical method is accessed from transparent code.
The access level of a method in a class library has changed, and one or more assemblies that reference the library have not been
recompiled.
There is problem in the inbuilt json class.
If you want to achieve this in alternate way, please use the below code:
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new DynamicJavaScriptConverter[] { new DynamicJavaScriptConverter() });
var result = WrapObject(serializer.DeserializeObject(value)); // here you will have result.
private object WrapObject(object value)
{
IDictionary<string, object> values = value as IDictionary<string, object>;
if (values != null)
{
return new DynamicJsonObject(values);
}
object[] arrayValues = value as object[];
if (arrayValues != null)
{
return new DynamicJsonArray(arrayValues);
}
return value;
}
Further to Roland's answer: some assembly mismatches listed can be fixed in the AssemblyInfo.cs file.
The offending line in my AssemblyInfo was this:
[assembly: AllowPartiallyTrustedCallers]
Removing this allowed me to access the public property (on a public class) that I was trying to set from another assembly that had dynamically loaded this assembly.
Say a vendor has provided two separate webservices, which both share the same data types and same namespace.
e.g.
The following webservices both contain similar objects, such as a TestCredentials object:
TestWebservice/Testwebservice1.asmx
TestWebservice/Testwebservice2.asmx
Including these into Visual Studio using web references I end up with:
Testwebservice1.TestCredentials
Testwebservice2.TestCredentials
When what I really want is:
Testwebservice.TestCredentials
Is there any way in Visual Studio, when dealing with the web references, to link these two webservices together so that the proxy classes that are generated are the same (and within the same namespace)?
Another possible option (along with wsdl.exe /sharetypes) is to use Visual Studio 2008 and use "Add Service Reference". The "Add Service Reference" dialog provides options to reuse types.
You'll have to manually generate your proxy classes using the wsdl.exe program with the /sharetypes switch.
What you should do instead of adding web references in visual studio is use the wsdl.exe command line tool to generate a proxy class that you can then edit to accept a URL instead of having two with hardcoded urls in separate namespaces.
Yes you can do that. We call it a data marshaller, but in this example I'll call it a consolidator.
You will notice that the WSDL generated class is a partial, we create a (web reference name).cs file and have something like:
Below are files you create, not WSDL generated files
WebReference1.cs
public partial class WebReferenceName1 : System.Web.Services.Protocols.SoapHttpClientProtocol
{
// take the methodname and append Local to the end
public Consolidated.ReturnType MethodName1Local(params)
{
// redirect the return value of the call to the consolidation method and return the new value
return Consolidation.Convert(this.MethodName1(params);
}
}
then the second web service
WebReference2.cs
public partial class WebReferenceName2 : System.Web.Services.Protocols.SoapHttpClientProtocol
{
// take the methodname and append Local to the end
public Consolidated.ReturnType MethodName2Local(params)
{
// redirect the return value of the call to the consolidation method and return the new value
return Consolidation.Convert(this.MethodName2(params);
}
}
and now the class that converts from the two types
Consolidator.cs
public class Consolidation
{
// Input from Web Reference #1
public static Consolidated.ReturnType Convert(WebReferenceName1.ReturnType valuetoConvert)
{
// Convert from valuetoConvert to Consolidated.ReturnType
convertedValue = (conversion of valuetoConvert to Consolidated.ReturnType);
return convertedValue;
}
// Input from Web Reference #2
public static Consolidated.ReturnType Convert(WebReferenceName2.ReturnType valuetoConvert)
{
// Convert from valuetoConvert to Consolidated.ReturnType
convertedValue = (conversion of valuetoConvert to Consolidated.ReturnType);
return convertedValue;
}
}
Basically you add methods to the web reference, call the {WebMethod}Local() methods, and that gets routed through the Consolidator and converts the simple WSDL generated class to something you can actually use.
Consolidated.ReturnType is what you define in your local project, its the local version of the data type that the WSDL generated under the web reference. Typically the "conversion" is just a clone / property by property copy from one type to another.
You can create a simple .disco file that references all the web services. It is just a simple contractRef for each web service.
Visual studio will share the types as long as they are using the same xml namespace.
I don't believe so, at least not without tinkering with the auto-generated reference.cs code.
What comes to mind is a few workarounds:
1) create a reflection based copy method that copies values based on property names or
2) if you're using .NET 3.5, write an extension method to copy between the two types.