Problem with Fedex Address Verification Web Reference - c#

I'm trying to get the sample FedEx Address Verification application to work in C#. After contacting my FedEx technical contact and having him activate Address Verification on my test account (apparently it is considered an advanced service that requires additional permissions) I was able to compile and run the example application.
However, I wasn't getting quite the results I expected given the settings...
request.Options.ConvertToUpperCase = true;
request.Options.CheckResidentialStatus = true;
Based on these flags, I expected to have the address come back in upper case, and to be able to check the Residential or ResidentialStatus properties to determine commercial vs residential. Neither were occuring.
So I installed Fiddler to see the exact SOAP exchange that was taking place and found that the outbound Options tag was not populating except for one property, MaximumNumberOfMatches.
Is there something I should check for in the Reference.cs file that is created by Visual Studio? I didn't see anything out of the norm, but something is happening that is preventing the serialization of some of the properties.
--Edit--
Updated my code as per the suggestion below. Unfortunately, it still only populates 2 of the options parameters. I've included the C# settings code and the outbound/inbound SOAP request below. Can anyone think of a reason the rest of the options are not being sent in the SOAP request?
AddressValidationRequest request = new AddressValidationRequest();
//
request.WebAuthenticationDetail = new WebAuthenticationDetail();
request.WebAuthenticationDetail.UserCredential = new WebAuthenticationCredential();
request.WebAuthenticationDetail.UserCredential.Key = "XXX-KEY-XXX"; // Replace "XXX" with the Key
request.WebAuthenticationDetail.UserCredential.Password = "XXX-PWD-XXX"; // Replace "XXX" with the Password
//
request.ClientDetail = new ClientDetail();
request.ClientDetail.AccountNumber = "XXX-ACCT#-XXX"; // Replace "XXX" with client's account number
request.ClientDetail.MeterNumber = "XXX-MTR#-XXX"; // Replace "XXX" with client's meter number
//
request.TransactionDetail = new TransactionDetail();
request.TransactionDetail.CustomerTransactionId = "***Address Validation v2 Request using VC#***"; // This is just an echo back
//
request.Version = new VersionId(); // Creates the Version element with all child elements populated
//
request.RequestTimestamp = DateTime.Now;
//
request.Options = new AddressValidationOptions();
request.Options.CheckResidentialStatus = true;
request.Options.CheckResidentialStatusSpecified = true;
request.Options.VerifyAddresses = true;
request.Options.MaximumNumberOfMatches = "5";
request.Options.StreetAccuracy = AddressValidationAccuracyType.MEDIUM;
request.Options.DirectionalAccuracy = AddressValidationAccuracyType.MEDIUM;
request.Options.CompanyNameAccuracy = AddressValidationAccuracyType.MEDIUM;
request.Options.ConvertToUpperCase = true;
request.Options.RecognizeAlternateCityNames = true;
request.Options.ReturnParsedElements = true;
//
request.AddressesToValidate = new AddressToValidate[2];
request.AddressesToValidate[0] = new AddressToValidate();
request.AddressesToValidate[0].AddressId = "Kimmel";
request.AddressesToValidate[0].Address = new Address();
request.AddressesToValidate[0].Address.StreetLines = new String[1] { "425 Morningside Dr" };
request.AddressesToValidate[0].Address.City = "Deerfield";
request.AddressesToValidate[0].Address.PostalCode = "53531";
request.AddressesToValidate[0].Address.CountryCode = "US";
//
request.AddressesToValidate[1] = new AddressToValidate();
request.AddressesToValidate[1].AddressId = "WD";
request.AddressesToValidate[1].Address = new Address();
request.AddressesToValidate[1].Address.StreetLines = new String[1] { "2830 Progress Rd" };
request.AddressesToValidate[1].Address.PostalCode = "53716";
request.AddressesToValidate[1].CompanyName = "Wingra Direct";
The outbound SOAP Request (obtained using Fiddler). Note the missing options:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<AddressValidationRequest xmlns="http://fedex.com/ws/addressvalidation/v2">
<WebAuthenticationDetail>
<UserCredential>
<Key>XXX-KEY-XXX</Key>
<Password>XXX-PWD-XXX</Password>
</UserCredential>
</WebAuthenticationDetail>
<ClientDetail>
<AccountNumber>XXX-ACCT#-XXX</AccountNumber>
<MeterNumber>XXX-MTR#-XXX</MeterNumber>
</ClientDetail>
<TransactionDetail>
<CustomerTransactionId>***Address Validation v2 Request using VC#***</CustomerTransactionId>
</TransactionDetail>
<Version>
<ServiceId>aval</ServiceId>
<Major>2</Major>
<Intermediate>0</Intermediate>
<Minor>0</Minor>
</Version>
<RequestTimestamp>2010-08-26T16:40:13.2026134-05:00</RequestTimestamp>
<Options>
<CheckResidentialStatus>true</CheckResidentialStatus>
<MaximumNumberOfMatches>5</MaximumNumberOfMatches>
</Options>
<AddressesToValidate>
<AddressId>Kimmel</AddressId>
<Address>
<StreetLines>425 Morningside Dr</StreetLines>
<City>Deerfield</City>
<PostalCode>53531</PostalCode>
<CountryCode>US</CountryCode>
<Residential>true</Residential>
</Address>
</AddressesToValidate>
<AddressesToValidate>
<AddressId>WD</AddressId>
<CompanyName>Wingra Direct</CompanyName>
<Address>
<StreetLines>2830 Progress Rd</StreetLines>
<PostalCode>53716</PostalCode>
</Address>
</AddressesToValidate>
</AddressValidationRequest>
</soap:Body>
</soap:Envelope>
The response I get back is:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"/>
<soapenv:Body>
<v2:AddressValidationReply xmlns:v2="http://fedex.com/ws/addressvalidation/v2">
<v2:HighestSeverity>SUCCESS</v2:HighestSeverity>
<v2:Notifications>
<v2:Severity>SUCCESS</v2:Severity>
<v2:Source>wsi</v2:Source>
</v2:Notifications>
<v2:TransactionDetail xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<v2:CustomerTransactionId>***Address Validation v2 Request using VC#***</v2:CustomerTransactionId>
</v2:TransactionDetail>
<v2:Version xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<v2:ServiceId>aval</v2:ServiceId>
<v2:Major>2</v2:Major>
<v2:Intermediate>0</v2:Intermediate>
<v2:Minor>0</v2:Minor>
</v2:Version>
<v2:ReplyTimestamp>2010-08-26T21:40:14.140Z</v2:ReplyTimestamp>
<v2:AddressResults>
<v2:AddressId>Kimmel</v2:AddressId>
<v2:ProposedAddressDetails>
<v2:Score>93</v2:Score>
<v2:Changes>MODIFIED_TO_ACHIEVE_MATCH</v2:Changes>
<v2:ResidentialStatus>UNAVAILABLE</v2:ResidentialStatus>
<v2:DeliveryPointValidation>CONFIRMED</v2:DeliveryPointValidation>
<v2:Address>
<v2:StreetLines>425 Morningside Dr</v2:StreetLines>
<v2:City>Deerfield</v2:City>
<v2:StateOrProvinceCode>WI</v2:StateOrProvinceCode>
<v2:PostalCode>53531-9492</v2:PostalCode>
<v2:CountryCode>US</v2:CountryCode>
</v2:Address>
<v2:RemovedNonAddressData/>
</v2:ProposedAddressDetails>
</v2:AddressResults>
<v2:AddressResults>
<v2:AddressId>WD</v2:AddressId>
<v2:ProposedAddressDetails>
<v2:Score>93</v2:Score>
<v2:Changes>MODIFIED_TO_ACHIEVE_MATCH</v2:Changes>
<v2:ResidentialStatus>UNAVAILABLE</v2:ResidentialStatus>
<v2:DeliveryPointValidation>CONFIRMED</v2:DeliveryPointValidation>
<v2:CompanyName>Wingra Direct</v2:CompanyName>
<v2:Address>
<v2:StreetLines>2830 Progress Rd</v2:StreetLines>
<v2:City>Madison</v2:City>
<v2:StateOrProvinceCode>WI</v2:StateOrProvinceCode>
<v2:PostalCode>53716-3338</v2:PostalCode>
<v2:CountryCode>US</v2:CountryCode>
</v2:Address>
<v2:RemovedNonAddressData/>
</v2:ProposedAddressDetails>
</v2:AddressResults>
</v2:AddressValidationReply>
</soapenv:Body>
</soapenv:Envelope>

It appears that on option is ignored unless you also set the optionSpecified flag to true also.
Here is my new options code that works - the key being that you need to add the Options.(property)specified = true for each one you want:
request.Options = New AddressValidationOptions()
request.Options.CheckResidentialStatus = True
request.Options.CheckResidentialStatusSpecified = True
request.Options.VerifyAddresses = True
request.Options.VerifyAddressesSpecified = True
request.Options.MaximumNumberOfMatches = 5
request.Options.StreetAccuracy = AddressValidationAccuracyType.MEDIUM
request.Options.DirectionalAccuracy = AddressValidationAccuracyType.MEDIUM
request.Options.CompanyNameAccuracy = AddressValidationAccuracyType.MEDIUM
request.Options.ConvertToUpperCase = True
request.Options.ConvertToUpperCaseSpecified = True
request.Options.RecognizeAlternateCityNames = True
request.Options.RecognizeAlternateCityNamesSpecified = True
request.Options.ReturnParsedElements = True
request.Options.ReturnParsedElementsSpecified = True

I was unable to get the API working so I ended up manually coding the handling of SOAP requests and responses. Aside from the API not properly setting all the flags, I also found out that the FedEx DEV server was not returning the Residential Status, regardless of what the options were (confirmed by our FedEx Web Services contact). When we gained access to the production servers the new code worked like a charm.

Here's another answer from FedEx tech support:
"The address verification API is not available from the test
environment".
So I'm not sure how you got your test account "activated" for address verification. Supposedly the FedEx system uses the USPS production address verification system which is why it's not accessible from the FedEx test environment.
I don't know if I believe this 100%, but I know that I'm hitting the FedEx test server with valid credentials and getting a "Authentication Failed" response.

Related

How to connect Twilio autopilot to voice call with custom memory parameters

I'm trying connect Twilio autopilot to voice call with custom data. According to documentation there is Memory parameter where I can put custom data.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Connect action="https://www.example.com/autopilot">
<Autopilot Memory={"CarModel":"Diablo","CarMake":"Lamborghini","CarYear":"2019"}>UAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</Autopilot>
</Connect>
</Response>
But when I try to put it via strong types I receive a message "Sorry an error occurred."
Here is the method:
public VoiceResponse ConnectAutopilot(Guid requestId)
{
var response = new VoiceResponse();
var autopilotUrl =
$"https://channels.autopilot.twilio.com/v1/{ AccountSid}/{AutopilotName }/twilio-voice";
var connect = new Connect
{
Action = new Uri(autopilotUrl)
};
var pilot = new Autopilot { Name = AutopilotName};
pilot.SetOption("Memory", new{requestId});
pilot.SetOption("TargetTask", "greeting");
connect.Append(pilot);
response.Append(connect);
response.Hangup();
return response;
}

Web Service dll behaving differently in Xamarin from Framework and Core versions

I have a SOAP web service that I need to call in a wide array applications, so I created a service DLL that targets both .net standard 2.0 and .net framework 4.6.1.
The DLL seems to work fine with on Desktop Framework applications, and on Desktop Core applications. However, the behavior on a Xamarin Android project is just slightly off of what the other two are.
A correctly sent message from the other two applications looks like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ZBAPI_GOODSMVT_CREATE xmlns="urn:sap-com:document:sap:rfc:functions">
<CODE xmlns="">
<GM_CODE>03</GM_CODE>
</CODE>
<HEADER xmlns="">
<PSTNG_DATE>2019-12-08</PSTNG_DATE>
<DOC_DATE>2019-12-08</DOC_DATE>
</HEADER>
<ITEM xmlns="">
... data here ...
</ITEM>
<RETURN xmlns="">
... data here ...
</RETURN>
</ZBAPI_GOODSMVT_CREATE>
</s:Body>
And the a successfully sent(but not processed) message from the android device is so:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ZBAPI_GOODSMVT_CREATE>
<CODE>
<GM_CODE>03</GM_CODE>
</CODE>
<HEADER>
<PSTNG_DATE>2019-12-08</PSTNG_DATE>
<DOC_DATE>2019-12-08</DOC_DATE>
</HEADER>
<ITEM>
... data here ...
</ITEM>
<RETURN>
... data here ...
</RETURN>
</ZBAPI_GOODSMVT_CREATE>
</s:Body>
So nearly identical, except every namespace inside the body element has been stripped out.
I've confirmed with SOAPUI that All the namespaces are needed, even the blank ones.
The DLL in question is, as stated, a .net standard 2.0, and the service was imported using the vendor provided wsdl file.
inside the DLL code I am calling the service like so:
private void RunRequest(ServiceData payload)
{
var binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic;
var address = new EndpointAddress("https:\\serviceaddress.com\service");
new ChannelFactory<ServiceChannel>(binding, address).Using(factory =>
{
factory.Credentials.UserName.UserName = "Uset";
factory.Credentials.UserName.Password = "Pass";
var proxy = factory.CreateChannel();
proxy.Open();
var context = new OperationContext((IClientChannel)proxy);
var prevOpContext = OperationContext.Current;
OperationContext.Current = context;
try
{
var results = proxy.ServiceChannel_CREATEAsync(payload).ConfigureAwait(false).GetAwaiter().GetResult().SerivceChannelResponse;
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(ServiceChannelResponse));
using StringWriter text = new StringWriter();
serializer.Serialize(text, results);
Message = text.ToString();
}
catch
{
throw;
}
});
how can I force the xmlns namespaces inclusion across all platforms?

Prevent "To" SOAP header being added

I'm have a problem with a SOAP header created in my C# client. The server is sending back the error
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<s:Header xmlns:s="http://www.w3.org/2003/05/soap-envelope" />
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:MustUnderstand</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">MustUnderstand headers: [{http://www.w3.org/2005/08/addressing}To] are not understood.</soap:Text>
</soap:Reason>
</soap:Fault>
</soap:Body>
</soap:Envelope>
I have been under the impression that I have been removing all SOAP headers with the following code.
internal class CustomMessageInspector : IEndpointBehavior, IClientMessageInspector
{
public object BeforeSendRequest( ref Message request, IClientChannel channel )
{
request.Headers.Clear();
return null;
}
...
}
However, after activating System.ServiceModel.MessageLogging in the app.config, (WCF - Inspect the messages being sent/received?), I see that the server is correct - lo and behold there is a "To" header with "mustUnderstand" set to 1 :
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:To s:mustUnderstand="1">https://ws-single-transactions-int-bp.nmvs.eu:8443/WS_SINGLE_TRANSACTIONS_V1/SinglePackServiceV30</a:To>
</s:Header>
Any thoughts how I can prevent this header from being added?
Many thanks.
In case it helps anybody else, I have found a solution. In fact Nicolas Giannone provided all the necessary code here WSHttpBinding in .NetStandard or .NET core . What we can do is to replace the WSHttpBinding with a custom binding based on the WSHttpBinding, and then replace the TextMessageEncodingBindingElement with one with no addressing. Here's the code :
string endPoint = myConfig.SinglePackServicesEndPoint;
//Defines a secure binding with certificate authentication
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
// create a new binding based on the existing binding
var customTransportSecurityBinding = new CustomBinding( binding );
// locate the TextMessageEncodingBindingElement - that's the party guilty of the inclusion of the "To"
var ele = customTransportSecurityBinding.Elements.FirstOrDefault( x=>x is TextMessageEncodingBindingElement );
if( ele != null )
{
// and replace it with a version with no addressing
// replace {Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing)}
// with {Soap12 (http://www.w3.org/2003/05/soap-envelope) AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)}
int index = customTransportSecurityBinding.Elements.IndexOf( ele );
var textBindingElement = new TextMessageEncodingBindingElement
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None)
};
customTransportSecurityBinding.Elements[index] = textBindingElement;
}

Soap Fault Exception "The predefined Type does not exist"

I'm currently working on a task and I need to connect to a soap service and call a methode. But I always get the error:
"The predefined type does not exist. Please choose a type manually"
This is how the soap xml part looks like:
<soapenv:Body>
<v2:create>
<!--Optional:-->
<v2:data>
<creator>CREATOR</creator>
<topicName>TOPICNAME</topicName>
<typeName>TYPENAME</typeName>
<variable>
<technicalName>ArticleNumber</technicalName>
<value>testpltd1</value>
</variable>
<variable>
<technicalName>cdb_bezeichnung_</technicalName>
<value>testtd1</value>
</variable>
<variable>
<technicalName>JobName</technicalName>
<value>testtd1</value>
</variable>
<workflowTypeName>WORKFLOW</workflowTypeName>
</v2:data>
</v2:create>
Here is my code:
DsePortTypeV2Client s = new DsePortTypeV2Client();
s.ClientCredentials.UserName.UserName = USERNAME;
s.ClientCredentials.UserName.Password = PASSWORD;
SetCertificatePolicy();
descriptionDto desc = new descriptionDto();
desc.creator = CREATOR;
desc.topicName = TOPICNAME;
desc.typeName = TYPENAME;
desc.workflowTypeName = WORKFLOW;
variableDto ArticleNumber = new variableDto();
variableDto cdb_bezeichnung_ = new variableDto();
variableDto JobName = new variableDto();
ArticleNumber.technicalName = "ArticleNumber";
ArticleNumber.value = r.id;
cdb_bezeichnung_.technicalName = "cdb_bezeichnung_";
cdb_bezeichnung_.value = r.bezeichnung;
JobName.technicalName = "JobName";
JobName.value = r.bezeichnung;
desc.variable = new variableDto[] { ArticleNumber, cdb_bezeichnung_ , JobName };
result res = s.createV2(desc);
Or is it possible that I catch the command that is sent to the server before it is encrypted by ssl?
I simply called the wrong methode, the remote methode was s.create not createV2 so off course my description was missing.

Error geting location data from latitude and longitude on Bingmaps

I'm using Bingmaps API to get the AdminDistrict and CountryRegion of a Latitude and Longitude.
It works entering in a browser to this url:
http://dev.virtualearth.net/REST/v1/Locations/-30,-70/?includeEntityTypes=AdminDivision1,CountryRegion&o=xml&c=es-ES&key=myBingmapsApiKey
But in C# on WP7 I can't get get it work.
This is the code:
string wsUrl = "http://dev.virtualearth.net/REST/v1/Locations/-30,-70/?includeEntityTypes=AdminDivision1,CountryRegion&o=xml&c=es-ES&key=*myBingmapsApiKey*";
var request = new RestSharp.RestRequest(Method.GET);
var client = new RestSharp.RestClient(wsUrl);
try
{
RestSharp.RestResponse resource;
client.ExecuteAsync(request, (response) =>
{
resource = response;
string content = resource.Content;
string status_code = resource.StatusCode.ToString();
string response_status = resource.ResponseStatus.ToString();
});
}
catch (Exception e)
{
string error = "Error: " + e.ToString() + "\n. Stack Trace: " + e.StackTrace;
}
And the response is:
<?xml version="1.0" encoding="utf-8"?>
<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1">
<Copyright>Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.</Copyright>
<BrandLogoUri>http://dev.virtualearth.net/Branding/logo_powered_by.png</BrandLogoUri>
<StatusCode>401</StatusCode><StatusDescription>Unauthorized</StatusDescription>
<AuthenticationResultCode>InvalidCredentials</AuthenticationResultCode>
<ErrorDetails><string>Access was denied. You may have entered your credentials incorrectly, or you might not have access to the requested resource or operation.</string></ErrorDetails>
<TraceId>59ebcf604bb343d79a6e8b93ad5695fe|MIAM001452|02.00.71.1600|</TraceId>
<ResourceSets />
</Response>
The url is the same that is working on web browser.
What can be wrong?
probably at this point you already came up with a solution but searching on google i found this topic and the solution is to not send the key through the url like you doing, instead add it as parameter in the request like this:
string wsUrl = "http://dev.virtualearth.net/REST/v1/Locations/-30,-70/";
var request = new RestSharp.RestRequest(Method.GET);
request.AddParameter("includeEntityTypes", "AdminDivision1,CountryRegion");
request.AddParameter("key", myLey);
request.AddParameter("o", "xml");
If I understand this right then the REST API you use may cost money. Maybe your API key istn't set up for billable transactions?
The page says about billing of Location API:
*This category is not billable if it occurs within the context of an AJAX Control or Silverlight Control session.
Maybe the browser counts as AJAX control and the phone isn't exactly a "Silverlight Control".

Categories

Resources