C# // GetResponseAsync() // NetworkCredential // .htaccess on a Windows 10 IoT Raspberry Pi 2 - .htaccess

the code tries to download text from a php script via a http request. Since the code should run on a Raspberry Pi with Windows IoT I have to use GetResponseAsync(). It works fine if I use it without the credentials (Http source is public then). When I add the NetworkCredential stuff I get the exception you see in the picture.
Screenshot
In the end I want to be able to load data from a http website that is protected via .htaccess. I hope anyone has some experience with this!
namespace HttpGetBeisp1Hta {
public sealed partial class MainPage : Page {
public MainPage() {
InitializeComponent();
}
private async void ClickMe_Click(object sender, RoutedEventArgs e)
{
try {
await HoleDaten();
}
catch(Exception ex) {
textBlock.Text = ex.ToString();
}
}
private async Task HoleDaten() {
NetworkCredential myCred = new NetworkCredential("user", "pw");
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri("https://..'my secret uri'../getSave.php"), "Basic", myCred);
WebRequest request = WebRequest.Create("https://..'my secret uri'../getSave.php");
request.Credentials = myCache;
WebResponse response = await request.GetResponseAsync();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
textBlock.Text = responseFromServer;
}
}
}

Found it out!
I modified the header manually. The username and pw needs to be added in base64. Use a converter and feed it with "Hans:Mueller" gets you:
private async Task HoleDaten() {
WebRequest request = WebRequest.Create("https:// ... ll.php");
request.Headers["Authorization"] = "Basic SGFuczpNdWVsbGVy";
WebResponse response = await request.GetResponseAsync();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
textBlock.Text = responseFromServer;
}

Related

FTP FileUpload Error: An exception occurred during a WebClient request. InnerException: This method is not supported. (Parameter 'value')

I'm trying to upload a file from IFormFile to FTPS using WebClient.
private async Task SaveFileToFtp(IFormFile file)
{
WebRequest.RegisterPrefix("ftps", new FtpsWebRequestCreator());
using (var client = new WebClient())
{
client.Credentials = new NetworkCredential("username", "password");
var address = "ftps://my-domain.com/folder/filename.txt";
using Stream uploadStream = client.OpenWrite(address);
using Stream fileStream = file.OpenReadStream();
await fileStream.CopyToAsync(uploadStream);
}
}
private sealed class FtpsWebRequestCreator : IWebRequestCreate
{
public WebRequest Create(Uri uri)
{
// Removes the "s" in "ftps://".
var requestUri = uri.AbsoluteUri.Remove(3, 1);
FtpWebRequest webRequest = (FtpWebRequest)WebRequest.Create(requestUri);
webRequest.EnableSsl = true;
return webRequest;
}
}
And I'm getting this error:
"An exception occurred during a WebClient request. InnerException: This method is not supported. (Parameter 'value')."
Can anyone tell me why?
Thanks
I've changed to use WinSCP instead of WebClient, and it works successfully.
https://winscp.net/eng/docs/ui_generateurl#code

How to encrypt xml file in Azure Logicapp?

I have a below requirement
1. XML file need to read from SharePoint and copy into Azure Blob.
2. Need to use Logic app to read the file from share point and copy into Azure Blob.
3. Before copy into Azure Blob need to encrypt the data in Logic app.
Please let me know if any suggestions.
As far as I know there is nothing out the box to help here. You will need to write an Azure Function (or a REST endpoint) to perform the encryption and call that from your Logic App.
There are many examples of such a function, you can find one for PGP here. The core function is copied below and Microsoft's guidance on calling functions from Logic Apps is here.
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using PgpCore;
using System.Threading.Tasks;
using Microsoft.Azure.KeyVault.Models;
using System.Net.Http;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.KeyVault;
using System;
using System.Text;
using System.Collections.Concurrent;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.Extensions.Logging;
namespace AzureFunctionsPGPEncrypt
{
public static class PGPEncrypt
{
private static readonly HttpClient client = new HttpClient();
private static ConcurrentDictionary<string, string> secrets = new ConcurrentDictionary<string, string>();
[FunctionName(nameof(PGPEncrypt))]
public static async Task<IActionResult> RunAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]
HttpRequest req, ILogger log)
{
log.LogInformation($"C# HTTP trigger function {nameof(PGPEncrypt)} processed a request.");
string publicKeyBase64 = req.Query["public-key"];
string publicKeyEnvironmentVariable = req.Query["public-key-environment-variable"];
string publicKeySecretId = req.Query["public-key-secret-id"];
if (publicKeyBase64 == null && publicKeyEnvironmentVariable == null && publicKeySecretId == null)
{
return new BadRequestObjectResult("Please pass a base64 encoded public key, an environment variable name, or a key vault secret identifier on the query string");
}
if (publicKeyBase64 == null && publicKeyEnvironmentVariable != null)
{
publicKeyBase64 = Environment.GetEnvironmentVariable(publicKeyEnvironmentVariable);
}
if (publicKeyBase64 == null && publicKeySecretId != null)
{
try
{
publicKeyBase64 = await GetPublicKeyAsync(publicKeySecretId);
}
catch (KeyVaultErrorException e) when (e.Body.Error.Code == "SecretNotFound")
{
return new NotFoundResult();
}
catch (KeyVaultErrorException e) when (e.Body.Error.Code == "Forbidden")
{
return new UnauthorizedResult();
}
}
byte[] data = Convert.FromBase64String(publicKeyBase64);
string publicKey = Encoding.UTF8.GetString(data);
req.EnableRewind(); //Make RequestBody Stream seekable
Stream encryptedData = await EncryptAsync(req.Body, publicKey);
return new OkObjectResult(encryptedData);
}
private static async Task<string> GetPublicKeyAsync(string secretIdentifier)
{
if (!secrets.ContainsKey(secretIdentifier))
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var authenticationCallback = new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback);
var kvClient = new KeyVaultClient(authenticationCallback, client);
SecretBundle secretBundle = await kvClient.GetSecretAsync(secretIdentifier);
secrets[secretIdentifier] = secretBundle.Value;
}
return secrets[secretIdentifier];
}
private static async Task<Stream> EncryptAsync(Stream inputStream, string publicKey)
{
using (PGP pgp = new PGP())
{
Stream outputStream = new MemoryStream();
using (inputStream)
using (Stream publicKeyStream = GenerateStreamFromString(publicKey))
{
await pgp.EncryptStreamAsync(inputStream, outputStream, publicKeyStream, true, true);
outputStream.Seek(0, SeekOrigin.Begin);
return outputStream;
}
}
}
private static Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
}
}

How to access api.openrouteservice.org through Androids Volley package

I want to access data on the openrouteservice API - specifically the distance between two given coordinates on the globe - from my Android application.
I have made requests and gotten viable responses from another API that converts two given addresses into their latlong coordinates using the same style of code this request is trying to execute. It works fine, the coordinates arrive and i can further utilize them no problem.
My problem is that i seem to be accessing the API wrongly because if I Log the URL as seen below and copy it from the Debug window into my browser it sends the request, gets a response and shows it in the browser window.
But my application doesn't recieve a response from the API as the onResponse code bit is never executed and the "Fetch done" Log never appears in the actual Debug Log.
The following is my setup of code, which uses Volley to access HTTP Requests and which works fine for other APIs.
#Override
protected String doInBackground(String... strings) {
Log.d("Run =>","Query 3");
String targetKoordURL = null;
String startKoordURL = null;
try {
startKoordURL = startK.getString("lon").concat(",").concat(startK.getString("lat"));
targetKoordURL = targetK.getString("lon").concat(",").concat(targetK.getString("lat"));
} catch (JSONException e) {
e.printStackTrace();
}
String URLfin = "https://api.openrouteservice.org/v2/directions/driving-car?api_key=5b3ce3597851110001cf624823e587e7a80c4c6ab02af6d394585213&start="+startKoordURL+"&end="+targetKoordURL;
Log.d("Debug =>", URLfin);
JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET, URLfin, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
store = response;
Log.d("Run =>", "Fetch done!");
continueImp();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if(error instanceof TimeoutError || error instanceof NoConnectionError){
sideFetcherHTTPRequestStart replace = new sideFetcherHTTPRequestStart();
replace.execute();
Log.d("VOLLEY_ERROR", "Retrying on Kilometer request");
}
error.printStackTrace();
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Accept", "application/json,application/geo+json,application/gpx+xml,img/png; charset=utf-8");
return params;
}
};
return null;
}
You forget to add the request to request queue, try to do as following:
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest req = new JsonObjectRequest(/*params*/);
//add above request to queue
queue.add(req);

Azure Service Bus - must add fake message before send the real one - why?

I'm facing a strange issue, and I ran out of the possible causes. The scenario is
Fetch incoming message from queue
Process it and then add new message to another queue
but the thing is, if I finish the long running task for the incoming message, and then try to add new message to another queue, I don't receive it. If I just add a face message to that another queue, then I am able to receive the real message after the long-running operation is finished. But why ? I don't want to put any fake messages to the queue, but without that my scenario doesn't work. Any ideas ?
public class WorkerRole : RoleEntryPoint
{
// QueueClient is thread-safe. Recommended that you cache
// rather than recreating it on every request
Microsoft.ServiceBus.Messaging.QueueClient Client;
ManualResetEvent CompletedEvent = new ManualResetEvent(false);
public override void Run()
{
MyResult result = null;
var queueClient = new Microsoft.Azure.ServiceBus.QueueClient("QueueConnectionString", "QueueName");
Client.OnMessage(async (receivedMessage) =>
{
try
{
using (Stream stream = receivedMessage.GetBody<Stream>())
{
using (StreamReader reader = new StreamReader(stream))
{
string json = reader.ReadToEnd();
OCRQueueItem_Incoming item = JsonConvert.DeserializeObject<IncomingClass>(json);
var someClass = new OCRManager();
var message = new Message(Encoding.UTF8.GetBytes("test 1"));
await queueClient.SendAsync(message);
result = new SomeManager().RunLongRunningTask(item); //it runs for 1-2min
}
}
}
catch (Exception ex) { }
finally
{
var json = JsonConvert.SerializeObject(result);
var message = new Message(Encoding.UTF8.GetBytes(json));
await queueClient.SendAsync(message);
}
});
CompletedEvent.WaitOne();
}
public override bool OnStart()
{
ServicePointManager.DefaultConnectionLimit = 12;
string connectionString = CloudConfigurationManager.GetSetting("Queue.ConnectionString");
Client = Microsoft.ServiceBus.Messaging.QueueClient.Create(connectionString);
return base.OnStart();
}
public override void OnStop()
{
Client.Close();
CompletedEvent.Set();
base.OnStop();
}
}

How does one configure HttpClient not to automatically redirect when it receives a 301 HTTP Status Code?

Consider an ASP.NET Web API service that redirects
public class ThisController : ApiController
{
/* more methods */
public override HttpResponseMessage Post()
{
var result = new HttpResponseMessage(HttpStatusCode.MovedPermanently);
// Post requests should be made to "ThatController" instead.
string uri = Url.Route("That", null);
result.Headers.Location = new Uri(uri, UriKind.Relative);
return result;
}
}
Trying to verify that POST'ing data to "api/this" will redirect you to "api/that", I have the following test method:
[TestMethod]
public void PostRedirects()
{
using (var client = CreateHttpClient("application/json"))
{
var content = CreateContent(expected, "application/json");
using (var responseMessage = client.PostAsync("api/this", content).Result)
{
Assert.AreEqual(HttpStatusCode.MovedPermanently, responseMessage.StatusCode);
Assert.AreEqual(new Uri("https://api.example.com/api/that"), responseMessage.Headers.Location);
}
}
}
protected HttpClient CreateHttpClient(string mediaType)
{
var client = new HttpClient();
client.BaseAddress = new Uri("http://api.example.com/");
MediaTypeWithQualityHeaderValue headerValue = MediaTypeWithQualityHeaderValue.Parse(mediaType);
client.DefaultRequestHeaders.Accept.Add(headerValue);
client.DefaultRequestHeaders.AcceptEncoding.Add(StringWithQualityHeaderValue.Parse("gzip"));
client.DefaultRequestHeaders.AcceptEncoding.Add(StringWithQualityHeaderValue.Parse("deflate"));
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(new ProductHeaderValue("MyProduct", "1.0")));
client.MaxResponseContentBufferSize = 1024*1024*8;
return client;
}
protected ObjectContent CreateContent(T model, string mediaType)
{
var requestMessage = new HttpRequestMessage();
MediaTypeFormatter mediaTypeFormatter = null;
switch (mediaType)
{
case "application/json":
mediaTypeFormatter = new JsonMediaTypeFormatter();
break;
case "application/xml":
case "text/xml":
mediaTypeFormatter = new XmlMediaTypeFormatter();
break;
default:
Assert.Fail();
break;
}
return requestMessage.CreateContent(
model,
new[] { mediaTypeFormatter },
new FormatterSelector());
}
What really happens that is that a HTTP Status Code is sent to the client with the correct Location header and that HttpClient then automatically performs a GET on that URI. As a result, my test never passes.
How do I configure the HttpClient not to automatically redirect when it receives a 301 so that I can verify that my server response?
Try:
var handler = new HttpClientHandler()
{
AllowAutoRedirect = false
};
HttpClient client = new HttpClient(handler);

Resources