Rest Post call with Authentication Token - c#

I'm trying to send a Post request to SharePoint Online (Claims Based Auth Site) from my client application (WPF application). In this case it should be an update to a ListItem to change the 'Title' to 'Test'.
I'm retrieving the CookieContainer via MsOnlineClaimsHelper Class
which successfully returns me an auth token.
But when i try to send the request the response is The remote server returned an error: (403) Forbidden.
WebRequest Code
try
{
var claimshelper = new MsOnlineClaimsHelper(baseUrl, _userName, _password);
var request = (HttpWebRequest)WebRequest.Create(baseUrl + "/" + url);
request.CookieContainer = claimshelper.CookieContainer;
request.Method = "POST";
request.Headers.Add("X-HTTP-Method", "MERGE");
request.Headers.Add("If-Match", "*");
request.Accept = "application/json;odata=verbose";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
}
var webResp = request.GetResponse() as HttpWebResponse;
var theData = new StreamReader(webResp.GetResponseStream(), true);
string payload = theData.ReadToEnd();
}
catch (Exception ex)
{
}
Rest Url:
/_api/lists/getbytitle('SampleList')/items(1)
Json Payload:
string json = "{ '__metadata': { 'type': 'SP.Data.SampleListListItem' }, 'Title': 'Test'}";
Error:
The remote server returned an error: (403) Forbidden.

This error occurs since SharePoint 2013 REST service requires the user to include a Request Digest value with each create, update and delete operation. This value is then used by SharePoint to identify non-genuine requests.
How to provide Request Digest value
In MsOnlineClaimsHelper class (MsOnlineClaimsHelper.cs file) add the following method to request Form Digest value:
/// <summary>
/// Request Form Digest value
/// </summary>
/// <returns></returns>
private string GetFormDigest()
{
var endpoint = "/_api/contextinfo";
var request = (HttpWebRequest) WebRequest.Create(_host.AbsoluteUri + endpoint);
request.CookieContainer = new CookieContainer();
request.Method = "POST";
//request.Accept = "application/json;odata=verbose";
request.ContentLength = 0;
using (var response = (HttpWebResponse)request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
var result = reader.ReadToEnd();
// parse the ContextInfo response
var resultXml = XDocument.Parse(result);
// get the form digest value
var e = from e in resultXml.Descendants()
where e.Name == XName.Get("FormDigestValue", "http://schemas.microsoft.com/ado/2007/08/dataservices")
select e;
_formDigest = e.First().Value;
}
}
return _formDigest;
}
and FormDigest property:
private string _formDigest;
public string FormDigest
{
get
{
if (_formDigest == null || DateTime.Now > _expires)
{
return GetFormDigest();
}
return _formDigest;
}
}
How to perform an update operation for a ListItem using SharePoint 2013 REST API
The following example demonstrates how to perform an update of a list item using the provided implementation for requesting a Form Digest
Key Points:
X-RequestDigest header is used to specify Form Digest value
Request Content Type have to be specified
Example:
var userName = "username#contoso.onmicrosoft.com";
var password = "password";
var payload = "{ '__metadata': { 'type': 'SP.Data.TasksListItem' }, 'Title': 'New Tasl'}"; //for a Task Item
try
{
var claimshelper = new MsOnlineClaimsHelper(baseUrl, _userName, _password);
var request = (HttpWebRequest)WebRequest.Create(baseUrl + "/" + endpointUrl);
request.CookieContainer = claimshelper.CookieContainer;
request.Headers.Add("X-RequestDigest", claimshelper.FormDigest);
request.Method = "POST";
request.Headers.Add("X-HTTP-Method", "MERGE");
request.Headers.Add("If-Match", "*");
request.Accept = "application/json;odata=verbose";
request.ContentType = "application/json;odata=verbose";
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(payload);
writer.Flush();
}
var response = request.GetResponse() as HttpWebResponse;
//...
}
catch (Exception ex)
{
//Error handling goes here..
}

Related

OneDrive upload files with REST API via resumable session

Hi there currently I am trying to make files uploading to one drive trough REST API. But every time I am getting Exception with 401 code for non authorized
The remote server returned an error: (401) Unauthorized.
My code snippet
public async Task<string> UploadFileAsync(Account account, StorageFile file)
{
var publicClientApplication = PublicClientApplicationBuilder.Create(MicrosoftConstants.ClientId)
.WithRedirectUri(MicrosoftConstants.RedirectUri)
.Build();
var scopes = new string[]
{
"files.readwrite.all"
};
AuthenticationResult authToken = null;
try
{
authToken = await publicClientApplication.AcquireTokenInteractive(scopes).ExecuteAsync();
}
catch (Exception)
{
}
if (authToken != null)
{
var postData = new
{
item = new
{
name = file.Name
}
};
var json = JsonConvert.SerializeObject(postData);
var request = (HttpWebRequest)WebRequest.Create($"https://graph.microsoft.com/v1.0/me/drive/items/root:/{file.Name}:/createUploadSession");
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength= json.Length;
request.Headers["Authorization"] = "bearer" + authToken.AccessToken;
using (var requestStream = await request.GetRequestStreamAsync())
using (var streamWriter = new StreamWriter(requestStream))
{
streamWriter.Write(json);
}
var response = (HttpWebResponse)await request.GetResponseAsync();
}
return string.Empty;
}
Do anybody know what am I doing wrong?
To make it work I had to change header with authorization to
request.Headers["Authorization"] = "Bearer " + authToken.AccessToken;

Paypal HTTP post request gives Invalid Merchant or Merchant doesn't exist error in MVC C#

I am facing trouble in making an HTTP post request to Paypal for Secure token to use Paypal's Hosted solution but I am getting this error:
Some required information is missing or incorrect. Please correct the fields below and try again.
Error: Invalid Merchant or Merchant doesn't exist!
This is my C# code throught which I am making HTTP calls:
string strNVP = "https://pilot-payflowpro.paypal.com?PARTNER=PayPal&USER=myUsername&VENDOR=myVendorName&PWD=myPassword&TRXTYPE=A&AMT=" + obj.CurrentPackagePrice + "&CREATESECURETOKEN=Y&SECURETOKENID=" + Guid.NewGuid().ToString("N");
HttpWebRequest wrWebRequest = (HttpWebRequest)WebRequest.Create(strNVP);
wrWebRequest.Method = "POST";
StreamWriter requestWriter = new StreamWriter(wrWebRequest.GetRequestStream());
requestWriter.Write(strNVP);
requestWriter.Close();
HttpWebResponse hwrWebResponse = (HttpWebResponse)wrWebRequest.GetResponse();
StreamReader responseReader = new StreamReader(wrWebRequest.GetResponse().GetResponseStream());
//and read the response
string responseData = responseReader.ReadToEnd();
responseReader.Close();
string result = Server.UrlDecode(responseData);
string[] arrResult = result.Split('&');
Hashtable htResponse = new Hashtable();
string[] responseItemArray;
foreach (string responseItem in arrResult)
{
responseItemArray = responseItem.Split('=');
htResponse.Add(responseItemArray[0], responseItemArray[1]);
}
string responseResult = htResponse["RESULT"].ToString();
string response = htResponse["RESPMSG"].ToString();
///for Success response
if (responseResult == "0" && response == "Approved")
{
ViewBag.secureToken = htResponse["SECURETOKEN"].ToString();
ViewBag.secureTokenId = htResponse["SECURETOKENID"].ToString();
}
Kindly help me in this problem may b I have done some wrong in my code above also.
The issue was that I was unable to receive a Token and TokenID due to that this exception was arising and then I resolved my issue by making modifications in the above code so that the Paypal sends back a response with Token and TokenID which I used in iframe and its working perfect now.
var request = (HttpWebRequest)WebRequest.Create("https://pilot-payflowpro.paypal.com");
var postData = "PARTNER=PayPal&USER=myUser&VENDOR=myVendor&PWD=myPassword&TRXTYPE=A&AMT=50&CREATESECURETOKEN=Y&SECURETOKENID=" + Guid.NewGuid().ToString("N");
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var responseData = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(responseData.GetResponseStream()).ReadToEnd();
string result = Server.UrlDecode(responseString);
string[] arrResult = result.Split('&');
Hashtable htResponse = new Hashtable();
string[] responseItemArray;
foreach (string responseItem in arrResult)
{
responseItemArray = responseItem.Split('=');
htResponse.Add(responseItemArray[0], responseItemArray[1]);
}
string responseResult = htResponse["RESULT"].ToString();
string response = htResponse["RESPMSG"].ToString();
///for Success response
if (responseResult == "0" && response == "Approved")
{
ViewBag.secureToken = htResponse["SECURETOKEN"].ToString();
ViewBag.secureTokenId = htResponse["SECURETOKENID"].ToString();
}
The above code is buggy and throws exceptions while receiving a response etc. So this code block is working good.

Very weird error 401?

I am receiving a 401 error I am not anticipating. I am 100% sure the password and usernamne is correct. When I try the it on postman it works, and I get the data I expect. But in this code, the .downloadstring() method returns a 401 error. I created a new harvest account and tried get to that one with the same code, just changed the password and username and I got the API data I wanted. Is there any other reason then wrong password or username error 401 can be cached?
public List<Project> GetAllProjects()
{
uri = "https://bruh.harvestapp.com/projects";
jsonPath = Path.Combine(HostingEnvironment.MapPath("~/App_Data"), "projects.json");
using (WebClient webClient = new WebClient())
{
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
webClient.Headers[HttpRequestHeader.Accept] = "application/json";
webClient.Headers[HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword));
string response = webClient.DownloadString(uri);
projectsList = JsonConvert.DeserializeObject<List<Wrapper>>(response).Select(p => p.project).ToList();
}
return projectsList;
}
According to this C# code sample from harvest, there are a few things that need to be changed:
static void Main(string[] args)
{
HttpWebRequest request;
HttpWebResponse response = null;
StreamReader reader;
StringBuilder sbSource;
// 1. Set some variables specific to your account.
string uri = "https://yoursubdomain.harvestapp.com/projects";
string username="youremail#somewhere.com";
string password="yourharvestpassword";
string usernamePassword = username + ":" + password;
ServicePointManager.ServerCertificateValidationCallback = Validator;
try
{
request = WebRequest.Create(uri) as HttpWebRequest;
request.MaximumAutomaticRedirections = 1;
request.AllowAutoRedirect = true;
// 2. It's important that both the Accept and ContentType headers are
// set in order for this to be interpreted as an API request.
request.Accept = "application/xml";
request.ContentType = "application/xml";
request.UserAgent = "harvest_api_sample.cs";
// 3. Add the Basic Authentication header with username/password string.
request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
using (response = request.GetResponse() as HttpWebResponse)
{
if (request.HaveResponse == true && response != null)
{
reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
sbSource = new StringBuilder(reader.ReadToEnd());
// 4. Print out the XML of all projects for this account.
Console.WriteLine(sbSource.ToString());
}
}
}

The remote server returned an error: (401) Unauthorized when requesting RestApi data

I am triyng to get data from the Rest API. API wants 3 things to give authentication;
first one is "Accept:application/vnd.###.v1.0+json"
second one : "Content Type : application/json"
third one : Base64 encoded "userName:password" string
and I should pass these credentials for validation and authorization in custom header.I know there are a lot of thread on this site about this topic but I couldn't solve the problem from them.
Here is the code block :
public class McAfeeIPSManager
{
String URL = "https://serviceOfApi/sdkapi/session";
public void getWebRequest()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
String username = "user";
String password = "password1";
var request = HttpWebRequest.Create(URL) as HttpWebRequest;
request.Accept = "application/vnd.###.v2.0+json";
request.Method = "GET";
request.ContentType = "application/json";
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
request.Headers.Add("Authorization","Basic "+encoded);
try
{
// Get response
using (var response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
using (var responseReader = new StreamReader(response.GetResponseStream()))
{
string responseBody = responseReader.ReadToEnd();
// Console application output
System.Diagnostics.Debug.Write("Response Body ---> " + responseBody);
//Console.WriteLine(responseBody);
}
}
}
catch (WebException ex)
{
System.Diagnostics.Debug.Write("Error : " + ex.Message);
Console.WriteLine("Error: {0}", ex.Message);
}
}
}
How can get data from WebAPI under these conditions?Can anybody help me?
You have no PreAuthenticate and credential ?
I have a code that may help you:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://pwmaffr2:8443/remote/system.delete?names=" + DeviceName + "");
request.Headers.Add("AUTHORIZATION", "Basic YTph");
request.ContentType = "text/html";
request.Credentials = new NetworkCredential(Username, Password);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
request.PreAuthenticate = true;
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
);
StreamReader stream = new StreamReader(response.GetResponseStream());
string X = stream.ReadToEnd();
hmm in addition of what i post try deal with this it should work for you hope:
string credentials = String.Format("{0}:{1}", username, password);
byte[] bytes = Encoding.ASCII.GetBytes(credentials);
string base64 = Convert.ToBase64String(bytes);
string authorization = String.Concat("basic ", base64);
request.Headers.Add("Authorization", authorization);

oauth/token returns empty body

I am encountering a problem getting the access_token in client application using oauth.
The returned response has empty body though in API I can see the response is not empty.
tokenresponse = {
"access_token":"[ACCESSTOKENVALUE]",
"token_type":"bearer",
"expires_in":"1200",
"refresh_token":"[REFRESHTOKENVALUE]",
"scope":"[SCOPEVALUE]"
}
The method from API that returns the token http://api.sample.com/OAuth/Token:
public ActionResult Token()
{
OutgoingWebResponse response =
this.AuthorizationServer.HandleTokenRequest(this.Request);
string tokenresponse = string.Format("Token({0})", response!=null?response.Body:""));
return response.AsActionResult();
}
The client method that requests the token is:
public string GetAuthorizationToken(string code)
{
string Url = ServerPath + "OAuth/Token";
string redirect_uri_encode = UrlEncode(ClientPath);
string param = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code",code, ClientId, ClientSecret, redirect_uri_encode);
HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
string result = null;
request.Method = "POST";
request.KeepAlive = true;
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = 10000;
request.Headers.Remove(HttpRequestHeader.Cookie);
var bs = Encoding.UTF8.GetBytes(param);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse response = request.GetResponse())
{
var sr = new StreamReader(response.GetResponseStream());
result = sr.ReadToEnd();
sr.Close();
}
if (!string.IsNullOrEmpty(result))
{
TokenData tokendata = JsonConvert.DeserializeObject<TokenData>(result);
return UpdateAuthorizotionFromToken(tokendata);
}
return null;
}
The result variable is empty.
Please let me know if you have any idea what could cause this. Initially I assumed is because of the cookies so I tried to remove them from request.
Thanks in advance.
Dear just create webclient using following code and you will get json info in tokeninfo.I used it and simply its working perfect.
WebClient client = new WebClient();
string postData = "client_id=" + ""
+ "&client_secret=" + ""
+ "&grant_type=password&username=" + "" //your username
+ "&password=" + "";//your password :)
string soundCloudTokenRes = "https://api.soundcloud.com/oauth2/token";
string tokenInfo = client.UploadString(soundCloudTokenRes, postData);
You can then use substring that contains only token from tokeninfo.
To upload tracks on sound cloud.
private void TestSoundCloudupload()
{
System.Net.ServicePointManager.Expect100Continue = false;
var request = WebRequest.Create("https://api.soundcloud.com/tracks") as HttpWebRequest;
//some default headers
request.Accept = "*/*";
request.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");
request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");
request.Headers.Add("Accept-Language", "en-US,en;q=0.8,ru;q=0.6");
//file array
var files = new UploadFile[] { new UploadFile(Server.MapPath("Downloads//0.mp3"), "track[asset_data]", "application/octet-stream") };
//other form data
var form = new NameValueCollection();
form.Add("track[title]", "Some title");
form.Add("track[sharing]", "public");
form.Add("oauth_token", "");
form.Add("format", "json");
form.Add("Filename", "0.mp3");
form.Add("Upload", "Submit Query");
try
{
using (var response = HttpUploadHelper.Upload(request, files, form))
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
Response.Write(reader.ReadToEnd());
}
}
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}

Categories