Thursday, September 16, 2010

Tips: FedEx WebService for Rate Quotes C#/Asp.Net

After a long run of using the UPS quotes for online orders, we moved to FedEx. So that meant, I needed to update the ecommerce app to reflect our new shipper.

This task wasn't *too* hard since I had already written the UPS one about 4 years ago, but the FedEx one uses a WebService, for the UPS rates, I sent an HttpWebRequest. I don't know why they don't have webservice, maybe they do now...

Anyhow, hopefully these tips will help get you started on your way.

1. Get the WSDL. To do this, I downloaded the WSDL file from FedEx, this file includes the RateService_v9.wsdl file. I unzipped this file to my local webserver, then to my production webserver.

2. Create a reference to the WebService in Visual Studio. In my project, I right-clicked then selected Add Web Reference. Then I pointed the reference to my localhost (http://localhost/fedex/RateService_v9.wsdl) and gave it a name.

3. Requested a Test Key from FedEx that I plugged into the values Account Number, Meter Number, Key and Password.

4. Downloaded the FedEx example for getting Rate Service Quotes. Modified it to my liking. Here's a snippet:

RateRequest request = new RateRequest();

RateService service = new RateService(); // Initialize the service

request.WebAuthenticationDetail = new WebAuthenticationDetail();
request.WebAuthenticationDetail.UserCredential = new WebAuthenticationCredential();
request.WebAuthenticationDetail.UserCredential.Key = this._key; // Replace "XXX" with the Key
request.WebAuthenticationDetail.UserCredential.Password = this._password; // Replace "XXX" with the Password
//
request.ClientDetail = new ClientDetail();
request.ClientDetail.AccountNumber = this._accountNumber; // account number
request.ClientDetail.MeterNumber = this._meter; // meter number
//
request.TransactionDetail = new TransactionDetail();
request.TransactionDetail.CustomerTransactionId = "MY-RATE-REQUEST";
//
request.Version = new VersionId(); // automatically set from wsdl


if (packages != null && packages.Count > 0)
{
SetShipmentDetails(request, packages.Count);

int i = 0;
decimal totalWeight = 0.0M;

foreach (Package package in packages){
RequestedPackageLineItem rpli = new RequestedPackageLineItem();
Weight packageWeight = new Weight();
packageWeight.Value = (decimal)package.Weight;
packageWeight.Units = WeightUnits.LB;
rpli.Weight = packageWeight;

totalWeight += (decimal)package.Weight;

request.RequestedShipment.RequestedPackageLineItems[i] = rpli;
i++;
}

Weight weight = new Weight();
weight.Value = totalWeight;
weight.Units = WeightUnits.LB;
request.RequestedShipment.TotalWeight = weight;

}
.....

5. Once I was satisfied with the results, I requested a Production Key from FedEx then plugged in those values. I kept receiving a "Meter Number is missing or invalid".

This where I got tripped up. I had to change the URL being called in the app.config (that seems to have been created for me with properties in it). There is a url value that is referenced by the WebService.

However, even though I kept changing this value, it would continue to use the old value which was the test site, and of course, give me the same error - since my meter number was a production one not a test one.

Finally, I thought to open up the Properties - Settings.settings file. Right when I double-clicked the file to open it, the proprety inside there was updated with the new value I had in the app.config file.

I assume it was some sort of Visual Studio 2010 thing. It seems like it was supposed to auto-update but it didn't. Later, to be sure, I just updated it manually.

After that everything worked like a charm.

FYI:
(for SOAP Requests)
The test url is: https://wsbeta.fedex.com:443/web-services/rate
The production url is: https://gateway.fedex.com:443/web-services