C# Fedex SOAP API - Get Shipping Label - c#

I'm trying to use the Fedex API to send SOAP requests and get shipping labels. The developer documentation on Fedex's website isn't very helpful. Does anyone have any sample code showing how to get shipping labels from your requests? Below is what I'm trying - looks like my request works, but my filestream returns a broken pdf. Unless Fedex is responding to my request incorrectly I'm at a loss for where to continue looking.
FedExHelper fedExHelper = new();
// builds the xml for the request
var parsedXml = fedExHelper.BuildShipmentRequest();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://ws.fedex.com/web-services");
client.DefaultRequestHeaders.Add("Accept", "image/gif, image/jpeg, image/pjpeg, text/plain, text/html, */*"); // for Accept header
HttpRequestMessage request = new();
request.Method = HttpMethod.Post;
request.Content = new StringContent(parsedXml);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
var response = client.Send(request);
return new FileStreamResult(await response.Content.ReadAsStreamAsync(), "application/pdf")
{
FileDownloadName = "test.pdf"
};
}
Also tried the below after reading the xml response. There's a label node that contains a base64 image. Decoding the base64 string still downloads a broken pdf.
var responseText = FedExHelper.SampleResponseText();
XDocument xml = XDocument.Load(new StringReader(responseText));
var label = xml.Root.Descendants().Where(x => x.Name.LocalName == "Label").FirstOrDefault();
var labelParts = label.Descendants().Where(x => x.Name.LocalName == "Parts").FirstOrDefault();
var image = labelParts.Descendants().Where(x => x.Name.LocalName == "Image").FirstOrDefault();
byte[] bytes = Convert.FromBase64String(image.Value);
MemoryStream stream = new(bytes);
return new FileStreamResult(stream, "application/pdf")
{
FileDownloadName = "test.pdf"
};

#Charleh you were absolutely correct. I had the incorrect ImageType value set in the xml I was posting. I can now return PDF labels.
For anyone else looking at this:
I had ZPLII set as the ImageType. This should have been PDF. I was adapting my code from an old dBase program, having no knowledge of working with the Fedex API.

Related

Problem calling the prediction endpoint uploading an image using rest sharp for the Microsoft custom vision API cognitive service

I am trying to upload an image to the Microsoft custom vision API prediction endpoint using Restsharp, I am trying to use the AddFile method but I am getting a BadRequest as the result, here is the code I am using
public IRestResponse<PredictionResponse> Predict(string imageFileName)
{
var file = new FileInfo(imageFileName);
var serviceUrl = ConfigurationManager.AppSettings["api.custom-vision.prediction.url.file"];
var serviceKey = ConfigurationManager.AppSettings["api.custom-vision.key"];
var client = new RestClient(serviceUrl);
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/octet-stream");
request.AddHeader("Prediction-Key", serviceKey);
request.AddFile(file.Name, file.FullName);
var response = client.Execute<PredictionResponse>(request);
return response;
}
When I execute the method I am getting the following response back from the service
{
"code": "BadRequestImageFormat",
"message": "Bad Request Image Format, Uri: 1062fe0480714281abe2daf17beb3ac5"
}
After looking for ways in the restsharp documentation to properly upload a file, I came to the solution that it needs to be passed as parameter with an array of bytes with the parameter type of ParameterType.RequestBody
Here is the example of the method that actually works
public IRestResponse<PredictionResponse> Predict(string imageFileName)
{
var file = new FileInfo(imageFileName);
var serviceUrl = ConfigurationManager.AppSettings["api.custom-vision.prediction.url.file"];
var serviceKey = ConfigurationManager.AppSettings["api.custom-vision.key"];
var client = new RestClient(serviceUrl);
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/octet-stream");
request.AddHeader("Prediction-Key", serviceKey);
request.AddParameter("content", File.ReadAllBytes(file.FullName), ParameterType.RequestBody);
var response = client.Execute<PredictionResponse>(request);
return response;
}

C# Reading multi-part stream

I'm reading a multi-part formdata in an HTTPHandler.
My code:
var content = new StreamContent(context.Request.InputStream);
//content.Headers.Add("Content-Type", context.Request.ContentType);
//content.Headers.TryAddWithoutValidation("Content-Type", context.Request.ContentType);
//content.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data");
//content.Headers.Add("Content-Type", "multipart/form-data");
//content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(context.Request.ContentType);
// content.Headers.Remove("Content-Type");
//content.Headers.Add("Content-Type", context.Request.ContentType);~
content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(context.Request.ContentType);
if (!content.IsMimeMultipartContent())
{
return HttpStatusCode.BadRequest;
}
var multipart =await content.ReadAsMultipartAsync();
I always get:
The format of value 'Content-Type: multipart/form-data; boundary=9fc46...................... is invalid
If I don't try to put the content-type I get another error.
Note: The commented lines are other alternatives that I tried without result
Working solution:
var content = (HttpContent)new StreamContent(context.Request.InputStream);
content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(context.Request.ContentType);
var multipart = new MultipartMemoryStreamProvider();
await content.ReadAsMultipartAsync(multipart);
Try setting up a MultPartFormDataContent object with the following boundary and posting this
var content = new MultipartFormDataContent("---------------" + Guid);
I believe the dashes have something to do with the way that boundarys are read in.

Proper way to send Raw XML to Tableau Rest API in C#

I simply want to send a rest request to Tableau's REST API but for some reason .NET isn't sending the raw XML (although tested and it works using Postman in chrome)
var admin = "\hardcoded_admin_user"\"";
var pass = "\hardcoded_pass"\"";
var tableau_signin = String.Format("<tsRequest> <credentials name={0} password={1}> </credentials> <site contentUrl=\"\"/> </tsRequest>", admin, pass);
//if user is validated make a REST call to Tableau Server
string endPoint = #"http://server/api/2.0/auth/signin";
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml"));
var post = client.PostAsync(endPoint,
new StringContent(tableau_signin)).Result;
}
Any help would be appreciated.
Provide Encoding and Content Type in the StringContent.
var post = client.PostAsync(endPoint,
new StringContent(tableau_signin, Encoding.UTF8, "application/xml")).Result;
var user = FormatTextBodyForUserSignIn(userName, password);
var httpContent = new StringContent(user, Encoding.UTF8, "application/xml");
var response = client.PostAsync($"api/{TableauAPIVersion}/auth/signin", httpContent).Result;

Dropbox Request URL path to file C#

I have OneDrive & Google Drive successfully processing chunked download however Dropbox is giving me grief because I cannot get the correct http request path to the file.
I am not an expert in rest url's & endpoints, maybe someone can point me in the right direction for the acceptable dropbox request format for the latest UWP SDK.
using (var httpRequest = new HttpRequestMessage())
{
string url = "https://content.dropboxapi.com/1/files/auto" + uri;
string accessKey = ApplicationData.Current.LocalSettings.Values[CommonData.dropboxAccessToken_Key].ToString();
httpRequest.Method = HttpMethod.Get;
httpRequest.RequestUri = new Uri(url);
httpRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accessKey);
}
I have read docs on Dropbox and it is not clear on the formatting for me, also I could not find a clear example anywhere.
Thanks again!
According to your code, the problem here is in your authorization header. For Dropbox API, the correct authorization header should like following:
Authorization: Bearer <access token>
So we should change httpRequest.Headers.Authorization to
httpRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
Then your code should be albe to work. Using "file.mp3" under "temp" folder for example.
The code may like:
var uri = "/temp/file.mp3";
using (var httpClient = new HttpClient())
{
using (var httpRequest = new HttpRequestMessage())
{
string url = "https://content.dropboxapi.com/1/files/auto" + Uri.EscapeDataString(uri);
httpRequest.Method = HttpMethod.Get;
httpRequest.RequestUri = new Uri(url);
httpRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
var response = await httpClient.SendAsync(httpRequest);
if (response.IsSuccessStatusCode)
{
//TODO
}
}
}

Is it possible to upload a file as well as post data using servicestack?

I want to be able to post a file and as part of that post add data.
Here is what I have:
var restRequest = new RestRequest(Method.POST);
restRequest.Resource = "some-resource";
restRequest.RequestFormat = DataFormat.Json;
string request = JsonConvert.SerializeObject(model);
restRequest.AddParameter("text/json", request, ParameterType.RequestBody);
var fileModel = model as IHaveFileUrl;
var bytes = File.ReadAllBytes(fileModel.LocalStoreUrl);
restRequest.AddFile("FileData", bytes, "file.zip", "application/zip");
var async = RestClient.ExecuteAsync(restRequest, response =>
{
if (PostComplete != null)
PostComplete.Invoke(
new Object(),
new GotResponseEventArgs
<T>(response));
});
It posts the file fine but the data is not present - is this even possible?
[UPDATE]
I have amended the code to use the multi-part header:
var restRequest = new RestRequest(Method.POST);
Type t = GetType();
Type g = t.GetGenericArguments()[0];
restRequest.Resource = string.Format("/{0}", g.Name);
restRequest.RequestFormat = DataFormat.Json;
restRequest.AddHeader("content-type", "multipart/form-data");
string request = JsonConvert.SerializeObject(model);
restRequest.AddParameter("text/json", request, ParameterType.RequestBody);
var fileModel = model as IHaveFileUrl;
var bytes = File.ReadAllBytes(fileModel.LocalStoreUrl);
restRequest.AddFile("FileData", bytes, "file.zip", "application/zip");
var async = RestClient.ExecuteAsync(restRequest, response =>
{
if (PostComplete != null)
PostComplete.Invoke(
new Object(),
new GotResponseEventArgs
<T>(response));
});
Still no luck... any pointers?
I am not an expert in C# but I used the same principle in Grails/Java for multipart requests.
Some pointers (ServiceStack/C#)
Multipart Form Post
MSDN MIME Message
ServiceStack File Attachment
Java corresponds:
Posting File and Data as JSON in REST Service
I hope this helps.
I am not sure if this is going to help. But give it a try.
Since you are attempting to pass it as text/json you may try to convert your byte array to a string and add it to the request.
To convert it to a string you may do something like this.
public string ContentsInText
{
get
{
return Encoding.Default.GetString(_bytecontents);
}
}
To convert it to a byte array you may do this. Most probably you will have to do this in your web service.
public byte[] ContentsInBytes
{
get { return Encoding.Default.GetBytes(_textcontents); }
}

Categories

Resources