I'm working on a new application where I need to use Clockify's API. When I make my test application for a proof of concept, I notice that I'm getting a 401 error as a response to using one of their base functions, get clients by work space. Am I missing something with the authentication? Is there a setting I need to allow on my profile? The error I'm getting is: System.Net.WebException: 'The remote server returned an error: (401) Unauthorized.' Thanks.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace Api
{
public class ApiHelper
{
public static HttpClient ApiClient { get; set; } = new HttpClient();
public static void InitializeClient(string username, string password)
{
ApiClient = new HttpClient();
ApiClient.BaseAddress = new Uri("https://api.clockify.me/api/");
ApiClient.DefaultRequestHeaders.Accept.Clear();
ApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public static void GetClientsFromWorkspace(string workspace)
{
ApiClient.DefaultRequestHeaders.Add("X-Api-Key", "*********");
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.clockify.me/api/workspaces/" + workspace + "/clients");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "GET";
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
}
}
}
You’re setting the api key header on the ApiClient but then making your request with a newly createdHttpWebRequest which doesn’t then have the required api key header.
You should either make your request using the ApiClient or add the X-Api-Key header to theHttpWebRequest as follows:
httpWebRequest.Headers.Add(“X-Api-Key”, “********”)
Related
The URL works if I run it in a browser, so key and response are correct. However when I run the code locally, it throws a 503 error. Any ideas?
using System.Collections.Generic;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Text;
using Newtonsoft.Json;
namespace ProjectM2.Shared
{
public class ReCaptcha
{
public bool Success { get; set; }
public List<string> ErrorCodes { get; set; }
public static bool Validate(string encodedResponse)
{
if (string.IsNullOrEmpty(encodedResponse)) return false;
var client = new System.Net.WebClient();
var secret = ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"];
if (string.IsNullOrEmpty(secret)) return false;
var googleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, encodedResponse));
var reCaptcha = JsonConvert.DeserializeObject<ReCaptcha>(googleReply);
return reCaptcha.Success;
}
}
}
Solved. It turns out it was the web filter was the culprit. I moved my machine to a vlan without the web filter and the code works.
Thanks to everyone who took the time to read and answer my question.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using pdrake.Models;
namespace pdrake.Controllers
{
public class MovieApiController : Controller
{
private const string baseUrl = "https://api.themoviedb.org/3/discover/movie?api_key=my_key";
public List<Movie> Movies { get; set; }
public async Task<AcceptedResult> GetMovies()
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(baseUrl);
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
Movies = JsonConvert.DeserializeObject<List<Movie>>(Json(baseUrl));
return View(Movies);
}
}
}
I've been struggling all day trying to figure out how to transfer the Json from baseUrl to the list Movies which can be looped through with a foreach loop.
Change your using block to the following,
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(baseUrl);
string data = await response.Content.ReadAsStringAsync();
return View(JsonConvert.DeserializeObject<List<Movie>>(data));
}
This will call the baseUrl along with receiving the text / content from the response. once you have the data, you can deserialize that to your List<Movie> object and return it as a View.
I'm new to .NET and I'm making a web api with asp.net. I'm trying to post a file to AWS S3 using the AWS .Net SDK.
It works but not if I try to read the fileName and send that as the key. It only works if I hardcode the key to a string (whereas I always want the key to be the same as the filename of the uploaded file).
When I try to read the filename from the file the error I'm getting is "Your socket connection to the server was not read from or written to within the timeout period. Idle connections will be closed."
So far I'm just using Postman to POST the files. I set the "Content-Type" header to multipart/form-data but exactly the same thing happens if I set it to application/x-www-form-urlencoded.
This is my UploadController:
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
using BlogApi.Models;
using System.Web;
using awsTestUpload;
using Amazon.S3.Model;
using Microsoft.AspNetCore.Http;
namespace BlogApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class S3UploadController : ControllerBase
{
public S3UploadController()
{
}
[HttpGet]
public ListObjectsResponse GetAll()
{
var uploader = new AmazonUploader();
return uploader.ListingObjectsAsync().Result;
}
[HttpPost]
public PutObjectResponse MyFileUpload()
{
var request = HttpContext.Request;
var fileStream = request.Body;
var contentLength = request.ContentLength;
string filePath = request.Form.Files.First().FileName;
var length = contentLength.HasValue ? (long)contentLength : 0;
var uploader = new AmazonUploader();
return uploader.sendMyFileToS3(fileStream, filePath, length).Result;
}
}
}
and the Uploader class looks like this:
using System;
using System.Diagnostics;
using System.Net;
using System.Threading.Tasks;
using System.IO;
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
using Microsoft.Extensions.Configuration;
namespace awsTestUpload
{
public class AmazonUploader
{
public AmazonUploader() {
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
client = new AmazonS3Client(Configuration["aws:AWS_KEY"],
Configuration["aws:AWS_SECRET"], bucketRegion);
}
private IAmazonS3 client;
public static IConfiguration Configuration { get; set; }
private const string bucketName = "my-bucket-name";
private static readonly RegionEndpoint bucketRegion = RegionEndpoint.EUWest2;
public async Task<ListObjectsResponse> ListingObjectsAsync()
{
ListObjectsRequest request = new ListObjectsRequest
{
BucketName = bucketName
};
return await client.ListObjectsAsync(request);
}
public async Task<PutObjectResponse> sendMyFileToS3(System.IO.Stream inputStream, string fileNameInS3, long contentLength = 0)
{
PutObjectRequest request = new PutObjectRequest
{
BucketName = bucketName,
Key = fileNameInS3,
InputStream = inputStream
};
request.Headers.ContentLength = contentLength;
return await client.PutObjectAsync(request);
}
}
}
When I debug and set a breakpoint, the value of filePath is a string matching the file name ( as I expect) but the upload is timing out. if I just set filePath to be a hardcoded string (ie replace string filePath = request.Form.Files.First().FileName; with string filePath = "foo.png";) it works fine.
Can anyone see why there's a difference?
I'm pretty new to rest API and restsharp so I need some help. I need to get a magento version 2.2.3 admin token but I keep getting a bad request. I've followed this tutorial: https://www.youtube.com/watch?v=2sdGuC7IUAI&t=343s. But I'm ending up with a bad request. When I check the statuscode using a the breakpoints from the tutorial I get: NotFound.
My main goal is to get the categories I have in Magento. But to get that I need an admin token. I already have a bearer acces code etc.
I would really appreciate your help.
my code so far:
magento.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RestSharp;
using Newtonsoft.Json;
namespace MagentoTest
{
public class magento
{
private RestClient Client { get; set; }
private string Token { get; set; }
public magento(string magentoUrl)
{
Client = new RestClient(magentoUrl);
}
public magento(string magentoUrl,string token)
{
Client = new RestClient(magentoUrl);
Token = token;
}
public string GetAdminToken(string userName, string passWord)
{
var request = CreateRequest("/rest/V1/integration/admin/token", Method.POST);
var user = new Credentials();
user.username = userName;
user.password = passWord;
string Json = JsonConvert.SerializeObject(user, Formatting.Indented);
request.AddParameter("aplication/json", Json, ParameterType.RequestBody);
var response = Client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return response.Content;
}
else
{
return "";
}
}
private RestRequest CreateRequest(string endPoint, Method method)
{
var request = new RestRequest(endPoint, method);
request.RequestFormat = DataFormat.Json;
return request;
}
}
}
Credentials:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MagentoTest
{
public class Credentials
{
public string username { get; set; }
public string password { get; set; }
}
}
(Client)
Program.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MagentoTest;
namespace Client
{
class Program
{
static void Main(string[] args)
{
GetToken("blabla", "blabla");
}
static void GetToken(string userName, string passWord)
{
var m2 = new magento("http://beta.topprice24.com");
string token = m2.GetAdminToken(userName, passWord);
}
}
}
It looks, relative URL needs to be changed as "/rest/default/V1/integration/admin/token"
(https://devdocs.magento.com/guides/v2.1/get-started/order-tutorial/order-admin-token.html).
I have simplified the above code and you can easily get the token.
Keep your Credentials class as it is and change your main program as below
Modified Code:(Program.cs)
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client
{
class Program
{
static void Main(string[] args)
{
//Base URL needs to be Specified
String host = "http://beta.topprice24.com";
//Relative URL needs to be Specified
String endpoint = "/rest/default/V1/integration/admin/token";
RestClient _restClient = new RestClient(host);
var request = new RestRequest(endpoint, Method.POST);
//Initialize Credentials Property
var userRequest = new Credentials{username="blabla",password="blabla"};
var inputJson = JsonConvert.SerializeObject(userRequest);
//Request Header
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/json");
//Request Body
request.AddParameter("application/json", inputJson, ParameterType.RequestBody);
var response = _restClient.Execute(request);
var token=response.Content;
}
}
}
Currently, I am retrieving a file by making a HTTP call with a HttpClient.
mRetriever = new MyRetriever(new HttpClient());
result = mRetriever.MyRetriever("https://some.url/myFile.js");
I would like to mock this call. After looking here, I added this to my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace MyTestModule
{
public class FakeResponseHandler : DelegatingHandler
{
private readonly Dictionary<Uri, HttpResponseMessage> _FakeResponses = new Dictionary<Uri, HttpResponseMessage>();
public void AddFakeResponse(Uri uri, HttpResponseMessage responseMessage)
{
_FakeResponses.Add(uri, responseMessage);
}
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (_FakeResponses.ContainsKey(request.RequestUri))
{
return _FakeResponses[request.RequestUri];
}
else
{
return new HttpResponseMessage(HttpStatusCode.NotFound) { RequestMessage = request };
}
}
}
}
However, I'm not sure how to move on from here:
I added this code where myLocalFile is the file I would like to return as a response.
FakeResponseHandler fakeResponseHandler = new FakeResponseHandler();
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.AddHeader("content-disposition", "attachment;filename=" + "./myLocalFile");
fakeResponseHandler.AddFakeResponse(new Uri("https://some.url/myFile.js"), response);
Mock<HttpClient> mockHttpClient = new Mock<HttpClient>();
HttpClient httpClient = new HttpClient(fakeResponseHandler);
However, I don't know:
1.How to reference a file from the local file system in the code.
2.How to add that file to HttpResponseMessage.
The current way I am doing it:
response.AddHeader("content-disposition", "attachment;filename=" + "./myLocalFile");
throws this error:
'HttpResponseMessage' does not contain a definition for 'AddHeader'
and no extension method 'AddHeader' accepting a first argument of type
'HttpResponseMessage' could be found(are you missing a using directive
or an assembly reference?)