A thousand apologies if this question has been posted already, but I am getting a "The remote server returned an error: (401) Unauthorized" error when attempting to upload a string to a remote server via a web request in SSIS (Visual Studio) by means of a script task - the external company to whom I am sending the data are certain that my public IP and the user credentials I am using to authenticate all have access to the server.
My code looks like this;
public void Main()
{
string proxyServer = (string)Dts.Variables["$Project::ProxyServer"].Value;
int proxyPort = (int)Dts.Variables["$Project::ProxyPort"].Value;
string username = Convert.ToString(Dts.Variables["$Project::UserName"].Value);
string password = Convert.ToString(Dts.Variables["$Project::Password"].GetSensitiveValue());
Uri TargetSite = new Uri((string)Dts.Variables["$Project::TargetSite"].Value);
string datatosend = (string)Dts.Variables["User::RequestBody"].Value;
if (datatosend != "")
{
string result;
using (WebClient webClient = new WebClient())
{
webClient.Proxy = new WebProxy(proxyServer, proxyPort); // Connect via the proxy
var bytes = Encoding.UTF8.GetBytes(username + ":" + password);// Build a means to authenticate
var auth = "Basic " + Convert.ToBase64String(bytes);
NetworkCredential myCreds = new NetworkCredential(username, password);
webClient.Credentials = myCreds;
webClient.Headers[HttpRequestHeader.Authorization] = string.Format("Basic ", credentials);
//webClient.Headers[HttpRequestHeader.Authorization] = auth; // Add the authorization header
webClient.Headers[HttpRequestHeader.ContentType] = "text/json"; // Add information about the content
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
try
{
result = webClient.UploadString(TargetSite, datatosend); // Issue the request
}
catch (WebException ex)
{
Dts.Events.FireError(0, "", "UnableToSendData: " + ex.Message.ToString() + ex.StackTrace, string.Empty, 0);
return;
}
}
}
Dts.TaskResult = (int)ScriptResults.Success;
}
Everything works until the request is issued - that's when I am hit with the 401 error and the response from the Uri is null;
I am at a loss because I am told my public IP is on their permissions list, so not sure why the request fails.
Any assistance would be greatly appreciated.
Many thanks in advance.
I have a little C# snippet that is supposed to be requested by Paypal IPN, confirm the payment then get some parameters from the request. The problem is that I am unable to get those parameters.
public class ipn : IHttpHandler {
protected string paypalUrl = "https://www.sandbox.paypal.com/cgi-bin/webscr";
public void ProcessRequest (HttpContext context) {
Task.Run(() => VerifyTask(context));
context.Response.Write("");
}
private void VerifyTask(HttpContext context)
{
var verificationResponse = string.Empty;
StreamReader reader = new StreamReader(context.Request.InputStream);
string requestFromPost = reader.ReadToEnd();
// at this point I am getting the request parameters correctly
File.WriteAllText(context.Server.MapPath("request.txt"), "Request: " + requestFromPost);
context.Request.InputStream.Position = 0;
try
{
// validating request here, all fine
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var verificationRequest = (HttpWebRequest)WebRequest.Create(paypalUrl);
// set values for the verification request
verificationRequest.Method = "POST";
verificationRequest.ContentType = "application/x-www-form-urlencoded";
// add cmd=_notify-validate to the payload
var strRequest = "cmd=_notify-validate&" + requestFromPost;
verificationRequest.ContentLength = strRequest.Length;
// attach payload to the verification request
var streamOut = new StreamWriter(verificationRequest.GetRequestStream(), Encoding.ASCII);
streamOut.Write(strRequest);
streamOut.Close();
// send the request to PayPal and get the response
var streamIn = new StreamReader(verificationRequest.GetResponse().GetResponseStream());
verificationResponse = streamIn.ReadToEnd();
streamIn.Close();
}
catch ( Exception exception)
{
// handling exception here, later
}
// sending context and response
ProcessVerificationResponse(context, verificationResponse);
}
private void ProcessVerificationResponse(HttpContext context, string verificationResponse)
{
// verifications response is VERIFIED
if (verificationResponse.Equals("VERIFIED"))
{
try {
// trying to get payment status
File.WriteAllText(context.Server.MapPath("status.txt"), "Verified: " + context.Request.QueryString["payment_status"]);
}
catch ( Exception exception)
{
// capture exception for manual investigation
File.WriteAllText(context.Server.MapPath("error.txt"), "Error: " + exception.Message);
}
}
}
}
An exception is thrown and the error.txt file is created with an "Object reference not set to an instance of an object" error. This happens no matter what I do with context.Request
context.Request.QueryString.Count.ToString() does the same
context.Request["payment_status"]
context.Request.Params.Count.ToString() triggers the same exception
so I don't know what is uninitialized and why, because context.Request.InputStream is not empty at least
I am attempting to post some XML to a web server. To do so I have to use the HTTP protocol, Post method, a multipart/form-data Content-Type, with 1 parameter called "xmlinfo" containing the XML I am uploading. The server uses basic authentication.
I keep getting the following error message:
System.Net.Http.HttpRequestException: An error occurred while sending the Request ---> System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.
I'm not sure why this is happening because I do posts to this server else where without problem; however, these posts do not involve a multipart/form-data content-type. I am looking for advise on how to get around it.
The following is the function I am currently having problems with posting the xml to the server:
public static async Task<Object> SaveXMLAsync(string xml)
{
Object strResult = String.Empty;
using (HttpClientHandler handler = new HttpClientHandler())
{
NetworkCredential credentials = new NetworkCredential();
credentials.UserName = user;
credentials.Password = password;
handler.Credentials = credentials;
using (var webClient = new HttpClient(handler))
{
webClient.BaseAddress = new Uri(ip);
webClient.DefaultRequestHeaders.Accept.Clear();
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, String.Format("{0}import/xml", ip)))
{
using (var content = new MultipartFormDataContent("----MyBoundary"))
{
StringContent xmlContent = new StringContent(xml, Encoding.UTF8, "application/xml");
content.Add(xmlContent, "xmlinfo");
request.Content = content;
request.Headers.ExpectContinue = false;
try
{
var response = await webClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None);
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync();
strResult = result.Result;
}
else
{
strResult = string.Format("Problem: {0}", response.RequestMessage);
}
}
catch (Exception ex)
{
strResult = ex.ToString();
}
}
}
}
}
return strResult;
}
Im trying to send several images from android client to C# server via http post with AQuery library.
urlport="http://192.168.100.139:1111";
Map<String, Object> params = new HashMap<>();
params.put("testimage", new File(getRealPathFromURI(imageUris.get(0))) );
aQuery
.ajax(urlport,params,JSONObject.class,new AjaxCallback<JSONObject>(){
#Override
public void callback(String url, JSONObject json, AjaxStatus status){
alert("post complete");//not working
}
});
C# HTTP Listener
lstnr = new Server();
lstnr.url = "http://" + ipbox.Text;
lstnr.port = portfield.Text;
lstnr.Received += Server_Received_multipart;
lstnr.StartListen();
in Server.class I set delegate that runs in receiving loop, accepts Stream
class Server{
......
public event EventHandler<Stream> Received = delegate { };
......
public void Start(){
string prefix = String.Format("{0}:{1}/", url, port);
listener.Prefixes.Add(prefix);
if (!listener.IsListening) {
listener.Start();
isListening = true;
try
{
while (isListening)
{
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
Stream postdata = request.InputStream;
Received(this, postdata);
}
}
catch (Exception e)
{
MessageBox.Show("Start() error: " + e.Message);
}
}
}
}
private void Server_Received_multipart(object sender, Stream msg)
{
Dispatcher.Invoke((Action)(() =>
{
//here want to handle stream and show images in window and save on disk
MessageBox.Show("message received"); //this not working too
}));
}
Before I made a fork where server accepts string with imagees in it encoded in base64/ works fine, but app crashes woth OurOfMemory error if send several images with size>3-4 Mb. Sorry if grammatic not good, Im russian
So I'm trying to put together some very simple and elegant code samples to help people use my API. The latest language I'm tackling is C#.
I think the IETF OAuth2.0 standard I read implies the HTTP request Content-Type must be "application/x-www-form-urlencoded". The Django API server I have, currently seems to only support this Content-Type (for the OAuth resource). The other languages POST content this way by default!
After extensive research and several experiments I am wondering if I have missed something fundamental. Surely there would be a helpful library OR technique to create the ...urlencoded string OR at least someone else must have run into this???
I will outline some of the best solution I have so far bellow, but it just seems wrong.
Also from a bunch of internet browsing I figured I would use the HttpClient library. I like the fact that it uses the async model, which perhaps will be more useful for any developers using WPF or XAML or Windows 8 apps. It also works well for Consoles and Forms.
I use the Newtonsoft Json.Net library for serialization. First of all I create a POCO of the authorization strings. Then I serialize it to JSON, then to key/value pairs, then iterate through the key/value pairs catenating with the required '=' and '&' chars, then UTF-8, then escape the spaces etc.
//Setup HTTP request
HttpClient httpRequest = new HttpClient();
httpRequest.DefaultRequestHeaders.Add("Accept", "application/json");
string urlBase = "https://__secret__/api/v1/";
HttpResponseMessage msg = new HttpResponseMessage();
//POST to oauth to get token (must be sent as "application/x-www-form-urlencoded")
OAuthConfig oAuthCredentials = new OAuthConfig { client_id = client_id, client_secret = secret, username = "__secret__", password = "__secret__", grant_type = "__secret__" };
string jsonString = JsonConvert.SerializeObject(oAuthCredentials); //convert to JSON
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString); //convert to key/value pairs
string urlEncodedData = ConvertToFormUrlEncodedFormat(values);
HttpContent payload = new StringContent(urlEncodedData, Encoding.UTF8, "application/x-www-form-urlencoded");
msg = httpRequest.PostAsync(urlBase + "oauth/access_token/", payload).Result;
string responseBodyAsText = msg.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseBodyAsText);
Other options I could think of were...
Reflection, however digging into reflection in a code sample seems a bit manic.
It turns out that other than the OAuth setup, the rest of the API supports JSON type POSTs. So I guess I could write a function to walk through the oAuthConfig model and catenate a string, since that POCO model is unlikely to change and is the only model which requires urlEncoding that I can anticipate. That would save us from the slightly confusing use of the Dictionary. The use of the dictionary and then iterating is more generic, however perhaps a bit OTT.
I figure most of the time people will be using JSON, so showing how that might happen is useful.
In general it seems quite hard to serialize a POCO model to a string and/or to a urlEncoded string.
Questions
does OAuth mandate urlencoded, could you convert server-side?
is HttpClient the best choice, does async matter?
is there a better simpler way to serialize a POCO to ...form-urlencoded?
Thanks for any useful comments you may have.
var model = new LoginModel { Username = "patient#gmail.com", Password = "123456", DeviceId = "123456789", RoleId = 1 };
url.Append("/Login");
string data = JsonConvert.SerializeObject(model);// "{\"username\":\"dscdemo0#gmail.com\",\"password\":\"vipin123\"}";
NameValueCollection inputs = new NameValueCollection();
inputs.Add("json", data);
WebClient client = new WebClient();
var reply = client.UploadValues(url.ToString(), inputs);
string temp = Encoding.ASCII.GetString(reply);
var result = JsonConvert.DeserializeObject<MessageTemplateModel>
(temp);
Api Call
public async Task<IHttpActionResult> Login(HttpRequestMessage request)//(LoginModel modelN)
{
try
{
var form = request.Content.ReadAsFormDataAsync().Result;
var modelN = JsonConvert.DeserializeObject<LoginModel>(form["json"].ToString());
// token = JsonConvert.DeserializeObject<string>(form["token"].ToString());
bool istoken = _appdevice.GettokenID(modelN.DeviceId);
if (!istoken)
{
statuscode = 0;
message = ErrorMessage.TockenNotvalid;
goto invalidtoken;
}
User model = new User();
// var session = HttpContext.Current.Session;
// session.Add("UserRole", GetProfileId.UserRole);
var user = await _userManager.FindAsync(modelN.Username, modelN.Password);}}
i am able to call url-encoder request from device and web app.
//I disclaimer everything and note that I haven't re-checked if this posted code works.
using System;
using System.Text;
using System.Collections.Generic;
using Newtonsoft.Json; //install with Nuget package installer- "json.Net"
using System.Net.Http; //install with Nuget package installer- "...Web API client libraries"
using System.Net;
using System.IO;
using System.Runtime.Serialization.Json; //security risk till certificate fixed
namespace CSharpDemoCodeConsole
{
class Program
{
const string api_key = "your_api_key"; //set your api_key here
const string user_auth = "your_username" + ":" + "your_password"; // set your user credentials here
const string urlBase = "https://#SECRET.com#/api/v1";
static void Main(string[] args)
{
Console.WriteLine("Making call to webserver asynchronously");
MakeCallAsynchronously();
Console.WriteLine("**************************************");
Console.WriteLine("Making call to webserver synchronously");
MakeCallSynchronously();
Console.WriteLine("**************************************");
Console.WriteLine("Making call to webserver synchronously without Newtonsoft serialization");
MakeCallSynchronouslyWithoutNewtonSoft();
Console.WriteLine("Press spacebar to close the application");
Console.ReadKey();
}
private static void MakeCallAsynchronously()
{
//Always accept untrusted certificates - don't use in production
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
//Setup request
string authorizeString = Convert.ToBase64String(Encoding.ASCII.GetBytes(user_auth));
HttpClient httpRequest = new HttpClient();
httpRequest.DefaultRequestHeaders.Add("Authorization", "Basic " + authorizeString);
httpRequest.DefaultRequestHeaders.Add("Accept", "application/json");
//GET from places resource
try
{
var requestTask = httpRequest.GetAsync(urlBase + "places/" + "?api_key=" + api_key,
System.Net.Http.HttpCompletionOption.ResponseContentRead);
//Update UI while waiting for task to complete
while (requestTask.Status != System.Threading.Tasks.TaskStatus.RanToCompletion)
{
Console.Write(".");
System.Threading.Thread.Sleep(30);
}
if (requestTask.Result.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine("Unexpected response from server: {0}", requestTask.Result);
return;
}
var places = JsonConvert.DeserializeObject<Page<Place>>(requestTask.Result.Content.ReadAsStringAsync().Result);
Console.WriteLine("GET places response " + requestTask.Result.Content.ReadAsStringAsync().Result);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
//POST to places resource
try
{
string jsonString = JsonConvert.SerializeObject(new Place { name = "test place", latitude = 0, longitude = 0 });
HttpContent payload = new StringContent(jsonString, Encoding.UTF8, "application/json");
var requestTask = httpRequest.PostAsync(urlBase + "places/" + "?api_key=" + api_key, payload);
//Update UI while waiting for task to complete
while (requestTask.Status != System.Threading.Tasks.TaskStatus.RanToCompletion)
{
Console.Write(".");
System.Threading.Thread.Sleep(30);
}
if (requestTask.Result.StatusCode != HttpStatusCode.Created)
{
Console.WriteLine("Unexpected response from server: {0}", requestTask.Result);
return;
}
Console.WriteLine("POST places response " + requestTask.Result.Content.ReadAsStringAsync().Result);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
}
private static void MakeCallSynchronously()
{
//Always accept untrusted certificates - don't use in production
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
//Setup Request
string authorizeString = Convert.ToBase64String(Encoding.ASCII.GetBytes(user_auth));
var client = new WebClient();
client.Headers.Add("Authorization", "Basic " + authorizeString);
client.Headers.Add("Accept", "application/json");
//GET from places resource
try
{
var responseStream = client.OpenRead(urlBase + "places/" + "?api_key=" + api_key);
var response = (new StreamReader(responseStream).ReadToEnd());
var places = JsonConvert.DeserializeObject<Page<Place>>(response);
Console.WriteLine("GET places response " + response);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
}
//POST to places resource
try
{
client.Headers.Add("Accept", "application/json");
client.Headers.Add("Content-Type", "application/json");
string jsonString = JsonConvert.SerializeObject(new Place { name = "test place", latitude = 0, longitude = 0 });
client.Encoding = System.Text.Encoding.UTF8;
string response = client.UploadString(urlBase + "places/" + "?api_key=" + api_key, jsonString);
Console.WriteLine("POST places response " + response);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
}
private static void MakeCallSynchronouslyWithoutNewtonSoft()
{
//Always accept untrusted certificates - don't use in production
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
//Setup Request
string authorizeString = Convert.ToBase64String(Encoding.ASCII.GetBytes(user_auth));
var client = new WebClient();
client.Headers.Add("Authorization", "Basic " + authorizeString);
client.Headers.Add("Accept", "application/json");
//GET from places resource
try
{
var responseStream = client.OpenRead(urlBase + "places/" + "?api_key=" + api_key);
MemoryStream ms = new MemoryStream();
responseStream.CopyTo(ms);
ms.Position = 0;
var placesDeserializer = new DataContractJsonSerializer(typeof(Page<Place>));
var places = (Page<Place>)placesDeserializer.ReadObject(ms);
ms.Position = 0;
string response = (new StreamReader(ms).ReadToEnd());
ms.Close();
Console.WriteLine("GET places response " + response);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
//POST to places resource
try
{
client.Headers.Add("Accept", "application/json");
client.Headers.Add("Content-Type", "application/json");
DataContractJsonSerializer placesSerializer = new DataContractJsonSerializer(typeof(Place));
Place place = new Place { name = "test place", latitude = 0, longitude = 0 };
MemoryStream ms = new MemoryStream();
placesSerializer.WriteObject(ms, place);
byte[] json = ms.ToArray();
ms.Close();
string jsonString = Encoding.UTF8.GetString(json, 0, json.Length);
client.Encoding = System.Text.Encoding.UTF8;
string response = client.UploadString(urlBase + "places/" + "?api_key=" + api_key, jsonString);
Console.WriteLine("POST places response " + response);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
}
}
public class Place
{
[JsonProperty("url")]
public string url { get; set; }
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("latitude")]
public float latitude { get; set; }
[JsonProperty("longitude")]
public float longitude { get; set; }
}
public class Page<T>
{
[JsonProperty("count")]
public int count { get; set; }
[JsonProperty("next")]
public string next { get; set; }
[JsonProperty("previous")]
public string previous { get; set; }
[JsonProperty("results")]
public List<T> results { get; set; }
}
}