I have a python azure function I'm trying to integrate with a C# backend. I'm trying to upload a file from an angular front end using a c# back end to post the data.
However, I'm getting a 401 error unauthorized. My function isnt anonymous level authentication and I'm attaching the keys to the headers, but is there something I'm missing that I need to include?
I've tried adding all the authentication to the headers and the form data headers but no luck.
public HttpResponseMessage UploadPartsTemplate()
{
MultipartFormDataContent form = new MultipartFormDataContent();
Dictionary<string, string> parameters = new Dictionary<string, string>();
string baseUrl = ConfigurationManager.AppSettings["PartsProjectAPIURL"];
try
{
var fileBytes = Request.Content.ReadAsStreamAsync().Result;
client.BaseAddress = new Uri(baseUrl);
HttpContent content = new StringContent("");
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "file",
FileName = "template.xlsx"
};
content = new StreamContent(fileBytes);
form.Add(content, "template.xlsx");
form.Headers.Add("x-functions-key", ConfigurationManager.AppSettings["XFunctionsKey"]);
form.Headers.Add("Ocp-Apim-Subscription-Key", ConfigurationManager.AppSettings["OcmAPISubscriptionKey"]);
form.Headers.Add("Ocp-Apim-Trace", "true");
form.Headers.Add("command", "validate");
form.Headers.Add("code", ConfigurationManager.AppSettings["XFunctionsKey"]);
client.DefaultRequestHeaders.Add("x-functions-key", ConfigurationManager.AppSettings["XFunctionsKey"]);
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", ConfigurationManager.AppSettings["OcmAPISubscriptionKey"]);
client.DefaultRequestHeaders.Add("Ocp-Apim-Trace", "true");
client.DefaultRequestHeaders.Add("command", "validate");
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var response = client.PostAsync(baseUrl, form).Result;
return result;
}
catch(Exception ex)
{
throw;
}
}
And the POST Request in Postman works just fine. Any help would be appreciated!
Thank you!
Related
I have an Azure Function App which is triggered by the task Invoke Azure Function in DevOps Pipeline, because the Function App is taking so long I´m using the async mode in the function and the task is configured in callback mode. That all is working fine. The issue I´m having is that when an exception is occouring in my function app, I want to send a callback to my pipeline so it fails. So it doesn´t stay in waiting for response mode. Is there a way to fail a DevOps Pipeline with a callback?
I have been using this documentation from Microsoft.
Here is some code I tried:
var body = JsonConvert.SerializeObject(new
{
status = "Cancelling",
name = "Taskfailed",
taskId = taskInstanceId.ToString(),
jobId = jobId.ToString(),
result = "failed", // also tryed fail
}) ;
PostEvent(callbackUrl, body, authToken)
The function which is sending the callback
public static void PostEvent(String callbackUrl, String body, String authToken)
{
try
{
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
var requestContent = new StringContent(body, Encoding.UTF8, "application/json");
var response = client.PostAsync(new Uri(callbackUrl), requestContent).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
log.LogInformation(response.StatusCode.ToString());
log.LogInformation(responseContent);
}
catch (Exception ex)
{
log.LogInformation("failed to cancel pipeline");
}
}
I am trying to download a zip archive from Azure via REST API using this Request Url and the C# code below. The response StatusCode is 200 so I assume it is working. But the zip file does not get downloaded to my computer. What am I doing wrong?
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/items?path={path}&scopePath={scopePath}&recursionLevel={recursionLevel}&includeContentMetadata={includeContentMetadata}&latestProcessedChange={latestProcessedChange}&download={download}&$format={$format}&versionDescriptor.version={versionDescriptor.version}&versionDescriptor.versionOptions={versionDescriptor.versionOptions}&versionDescriptor.versionType={versionDescriptor.versionType}&includeContent={includeContent}&resolveLfs={resolveLfs}&sanitize={sanitize}&api-version=6.0
public static void DownloadTest()
{
var repository = "myrepository";
var branch = "main";
var url = $"https://dev.azure.com/{Constants.ORGANIZATION}/{Constants.PROJECT}/_apis/git/repositories/{repository}/items?path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=0&versionDescriptor[version]={branch}&resolveLfs=true&$format=zip&api-version=6.0&download=true";
try
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/zip"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", Constants.PAT))));
var response = httpClient.GetAsync(url).Result;
response.EnsureSuccessStatusCode();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
I have been trying to intergrate the openxml package in Azure function. The code compiles fine but when i try to reach the function url it doesn't downloads the file but fails the call and there is no execution error in the code.
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log, [Inject]TrainingManager trainingManager)
{
//dynamic data = await req.Content.ReadAsAsync<object>();
//string trainingCourseId = data?.trainingCourseId;
log.Info("Function App Started");
HttpResponseMessage response = req.CreateResponse(HttpStatusCode.OK);
using (MemoryStream mem = new MemoryStream())
{
// Create Document
using (WordprocessingDocument wordDocument =
WordprocessingDocument.Create(mem, WordprocessingDocumentType.Document, true))
{
// Add a main document part.
MainDocumentPart mainPart = wordDocument.AddMainDocumentPart();
// Create the document structure and add some text.
mainPart.Document = new DocumentFormat.OpenXml.Wordprocessing.Document();
Body docBody = new Body();
// Add your docx content here
Paragraph para = docBody.AppendChild(new Paragraph());
Run run = para.AppendChild(new Run());
run.AppendChild(new Text("Hi"));
mainPart.Document.Save();
}
mem.Seek(0, SeekOrigin.Begin);
response.Content = new StreamContent(mem);
}
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = "AttendanceList.docx"
};
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/msword");
log.Info("Sending Response");
return response;
}
Let me know if anyone has faced this issue or have a solution to it.
Here is what i see in network tab]1
Thanks!
I have been playing around with the jira rest api to eventually replace my soap implementation in a c# app using the 4.0 .net framework. I am also using restsharp.
While i had no problem getting an issue or searching for an issue with the rest api, i have been pulling my hairs with updating a jira issue. These are my execute methods, they work fine to do get or search jira issues. Usual error message i get when i call SetJiraIssue is the following {"errorMessages":["one of 'fields' or 'update' required"],"errors":{}}.
If i pass a simple JSOn string exeample(string jSonContent = #"{""Fields"":{""summary"":"" testing summary update""}}") to the body of the request, then it complains that there is no constructor for it.
Anybody out there as an idea of what i am doing wrong? Comments and suggestion are more then welcome
private string Execute(RestRequest request)
{
var client = new RestClient(_jiraUrl);
client.Authenticator = new HttpBasicAuthenticator(_accountId, _password);
request.AddParameter("AccountSid", _accountId, ParameterType.UrlSegment);
var response = client.Execute(request);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var jiraManagerException = new ApplicationException(message, response.ErrorException);
throw jiraManagerException;
}
return response.Content;
}
/// <summary>
/// Executes a jira rest call and retuns the response if any as a business object.
/// </summary>
/// <typeparam name="T">Type of the return type for deserialization.</typeparam>
/// <param name="request">THe reste request.</param>
/// <returns></returns>
private T Execute<T>(RestRequest request) where T : new()
{
var client = new RestClient(_jiraUrl);
client.Authenticator = new HttpBasicAuthenticator(_accountId, _password);
request.AddParameter("AccountSid", _accountId, ParameterType.UrlSegment);
var response = client.Execute<T>(request);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var jiraManagerException = new ApplicationException(message, response.ErrorException);
throw jiraManagerException;
}
return response.Data;
}
public void SetJiraIssue(string issueKey, JiraIssue j)
{
RestRequest request = new RestRequest("issue/{key}", Method.PUT);
request.AddUrlSegment("key", issueKey);
request.RequestFormat = DataFormat.Json;
request.AddHeader("Content-type", "application/json");
j.Summary = "modifiying this issue";
request.AddBody(j);
var response = Execute(request);
Console.WriteLine(response);
}
I finally found a way to make it work, it's not totally how i expected it or would of liked it to work but it's the only way i found yet. Hopefully this will be useful to someone else
public void SetJiraIssue(string issueKey, JiraIssue j)
{
RestRequest request = new RestRequest("issue/{key}", Method.PUT);
request.AddUrlSegment("key", issueKey);
request.RequestFormat = DataFormat.Json;
string jSonContent = #"{""fields"":{""summary"":""test changing summary""}}";
request.AddParameter("application/json", jSonContent, ParameterType.RequestBody);
var response = Execute(request);
Console.WriteLine(response);
}
I want to post some request values alongside the multipart-formdata file contents. In the old API you could use PostFileWithRequest:
[Test]
public void Can_POST_upload_file_using_ServiceClient_with_request()
{
IServiceClient client = new JsonServiceClient(ListeningOn);
var uploadFile = new FileInfo("~/TestExistingDir/upload.html".MapProjectPath());
var request = new FileUpload{CustomerId = 123, CustomerName = "Foo"};
var response = client.PostFileWithRequest<FileUploadResponse>(ListeningOn + "/fileuploads", uploadFile, request);
var expectedContents = new StreamReader(uploadFile.OpenRead()).ReadToEnd();
Assert.That(response.FileName, Is.EqualTo(uploadFile.Name));
Assert.That(response.ContentLength, Is.EqualTo(uploadFile.Length));
Assert.That(response.Contents, Is.EqualTo(expectedContents));
Assert.That(response.CustomerName, Is.EqualTo("Foo"));
Assert.That(response.CustomerId, Is.EqualTo(123));
}
I can't find any such method in the new API, nor any overrides on client.Post() which suggest that this is still possible. Does anyone know if this is a feature that was dropped?
Update
As #Mythz points out, the feature wasn't dropped. I had made the mistake of not casting the client:
private IRestClient CreateRestClient()
{
return new JsonServiceClient(WebServiceHostUrl);
}
[Test]
public void Can_WebRequest_POST_upload_binary_file_to_save_new_file()
{
var restClient = (JsonServiceClient)CreateRestClient(); // this cast was missing
var fileToUpload = new FileInfo(#"D:/test/test.avi");
var beforeHash = this.Hash(fileToUpload);
var response = restClient.PostFileWithRequest<FilesResponse>("files/UploadedFiles/", fileToUpload, new TestRequest() { Echo = "Test"});
var uploadedFile = new FileInfo(FilesRootDir + "UploadedFiles/test.avi");
var afterHash = this.Hash(uploadedFile);
Assert.That(beforeHas, Is.EqualTo(afterHash));
}
private string Hash(FileInfo file)
{
using (var md5 = MD5.Create())
{
using (var stream = file.OpenRead())
{
var bytes = md5.ComputeHash(stream);
return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
}
}
}
None of the old API was removed from the C# Service Clients, only new API's were added.
The way you process an uploaded file inside a service also hasn't changed.