I am trying to attach files (screenshots) to an Azure DevOps work item via a C# desktop app. I have managed to attach files, but they're not valid image files, which leads me to believe that I'm doing something wrong in uploading them.
From the documentation DevOps Create Attachment below is the section on the Request body of the API call, which is rather vague.
From a GitHub discussion this answer seems to suggest that I just upload the binary content directly, which is what I'm doing.
My code is as follows
var img = File.ReadAllBytes(fname);
string query = #"/_apis/wit/attachments?fileName=" + fname + #"&api-version=6.0"
string response = AzureUtils.AttachFile(query, img, "POST", false, "application/octet-stream");
Is it correct that I literally pass in the byte array which is read from the file (variable img) as the body?
Why is it not a valid file when I look at it in DevOps?
The code for AttachFile is
public static string AttachFile(string query, byte[] data = null, string method = "GET",
bool dontUseBaseURL = false, string contentType = "application/json-patch+json")
{
try
{
HttpWebRequest request = WebRequest.Create(query) as HttpWebRequest;
request.ContentType = contentType;
request.Method = method;
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
request.Headers.Add("Authorization", "Basic " +
Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{1}", ["AzurePAT"]))));
if (data != null)
{
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(data);
}
}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
string result = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
request = null;
response = null;
return result;
}
Related
I am provided a webservice url similar to:
http://ericdev35:7280/persons/persons/
and a username and password.
I want to make a post call on this web service from WPF application.
The data to be sent to the service is the first name and last name of a person in the format:
"fname=Abc&lname=Xyz"
How can I make a call for this in C#?
Here is the code that I have tried:
HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create("http://ericdev35:7280/persons/persons/");
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json";
httpWebRequest.Credentials = new NetworkCredential(username, password);
string data = "fname=Abc&lname=Xyz";
StreamWriter writer = new StreamWriter(httpWebRequest.GetRequestStream());
writer.Write(data);
writer.Close();
This does not give me any error but I cannot see the data that I have posted. Is there anything that needs to be corrected?
Is the Content Type correct?
This Method posts json.
After that it gets the response and deserialize the Json Object.
private static string PostJson<T1>(string p_url, string p_json, string p_method, out T1 p_target)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(p_url);
httpWebRequest.UseDefaultCredentials = true;
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = p_method;
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(p_json);
streamWriter.Flush();
streamWriter.Close();
}
HttpWebResponse httpResponse;
try
{
httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
}
catch (WebException ex)
{
httpResponse = ex.Response as HttpWebResponse;
}
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var a_result = streamReader.ReadToEnd();
//If you dont need a Json object delete anything behind here
try
{
p_target = JsonConvert.DeserializeObject<T1>(a_result);
}
catch { p_target = default(T1); }
return a_result;
}
}
I have application that sends requests to same REST server constantly and after some time HttpWebRequest.GetResponse() starts timing out i've noticed that whenever i increase System.Net.ServicePointManager.DefaultConnectionLimit it takes it longer to start timing out again, which should mean that those requests are staying active, but as far as i know i'm closing all of them.
Here is method i'm using for my requests.
Current DefaultConnectionLimit is set to 10.
Also there is 1 request that is going on throughout most of applications lifetime.
I'm using .NET Compact framework and REST server is written using WCF (.NET 4.5)
public static string HttpRequest(string request, string method, string contentType, int timeout)
{
string result = "";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(PodesavanjaManager.TrenutnaPodesavanja.PutanjaServisa + "/" + request);
req.Method = method;
req.ContentType = contentType;
req.Timeout = timeout;
req.KeepAlive = false;
if(method == "POST")
req.ContentLength = 0;
using(Stream stream = req.GetResponse().GetResponseStream())
{
using(StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
reader.Close();
}
stream.Close();
stream.Flush();
}
return result;
}
EDIT new version of method:
public static string HttpRequest(string request, string method, string contentType, int timeout)
{
string result = "";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(PodesavanjaManager.TrenutnaPodesavanja.PutanjaServisa + "/" + request);
req.Method = method;
req.ContentType = contentType;
req.Timeout = timeout;
req.KeepAlive = false;
if(method == "POST")
req.ContentLength = 0;
using (HttpWebResponse resp =(HttpWebResponse) req.GetResponse())
{
using (Stream stream = resp.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
reader.Close();
}
}
}
GC.Collect();
return result;
}
I agree it does behave like the connection is still in use by a resource that has not been closed. The documentation for HttpWebResponse mentions:
You must call either the Stream.Close or the HttpWebResponse.Close method to close the response and release the connection for reuse. It is not necessary to call both Stream.Close and HttpWebResponse.Close, but doing so does not cause an error.
I was hoping for a more straightforward description like "you must either close the stream returned by GetResponseStream or call the HttpWebResponse.Close method - but if my interpretation of the documentation is correct, your code is fine.
We use HttpWebRequest in our CE applications as well, and always put the response in a using block as well - you could try this:
using(HttpWebResponse response = (HttpWebResponse)req.GetResponse())
using(Stream stream = response.GetResponseStream())
{
// ...
}
Also have you checked your code for other HttpWebRequest usages, just to be sure?
I have applicaiton which is the combination of MVC 4 + Web Api + SQL server.
I am trying to download the doc file to MVC but i have tried the below step.
I have Web API where i have written the below code. when i send the rowid it has the value stored in the DB as varbinary. file format can be any thing like .doc,pdf etc ... but however I am looking for the first doc or PDF file format.
When I call the Web api it will create the PDF file and download it , but the file is completely corrupted.
[ResponseType(typeof(MandateExceptionDO))]
[HttpGet]
[Route("api/DealingMandate/GetExceptionDoc/{rowId}")]
public HttpResponseMessage GetExceptionDoc(int rowId)
{
IDealingMandates repository = new DealingMandatesRepository();
List<MandateExceptionDO> mandateexceptiondoc =new List<MandateExceptionDO>();
mandateexceptiondoc = repository.GetExceptionDoc(rowId);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
//response.Content = new ByteArrayContent(mandateexceptiondoc[0].Content);
//response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data");
//byte[] fileBytes = System.IO.File.ReadAllBytes(mandateexceptiondoc[0].Content);
response.Content = new ByteArrayContent(mandateexceptiondoc[0].Content);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = "testing.pdf";
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
//return Ok(mandateexceptiondoc);
return response;
}
I am able to fix this issue on the web api i made the byte as string as show below
String doc = Convert.ToBase64String(customermandate.Content);
and for the MVC side i converted back to byte from the string
var doc = restClient.Execute(request);
var response = doc.Content.Substring(1, doc.Content.Length - 2).Replace(#"\/", "/");
byte[] docBytes = Convert.FromBase64String(response);
if (doc.Content != null && doc.Content.Length > 0 && !string.IsNullOrEmpty(doc.Content))
{
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=" + FileName);
Response.BinaryWrite(docBytes);
Response.End();
}
I tried to upload file, but then file is called "untitle".
byte[] fileBytes = System.IO.File.ReadAllBytes(fileName);
string UploadURI = String.Format("https://www.googleapis.com/upload/drive/v2/files?uploadType=media&access_token={0}", accessToken);
var request = (HttpWebRequest)HttpWebRequest.Create(UploadURI);
request.Method = "POST";
request.ContentLength = fileBytes.Length;
using (var dataStream = request.GetRequestStream())
{
dataStream.Write(fileBytes, 0, fileBytes.Length);
}
string status = (((HttpWebResponse)request.GetResponse()).StatusDescription);
if (status.ToLower() == "created" || status.ToLower()=="ok")
{
Uploaded = true;
}
And how can I upload a file into a specific folder?
The answer to both the "untitle" and "parent folder" questions is the same. Meta Data. When you POST you should provide a meta data object containing a title:"title" and parents: [{id:"parent_id"}]
Am using below url to upload a file to dropbox using oauth and am getting an error
{"error": "Call requires one of the following methods: PUT, POST, got GET!"}
am passing httpmethod as PUT but still asking the error.
Signature am using to upload is
https://api-content.dropbox.com/1/files_put/dropbox/test?oauth_consumer_key=twcek2m7cxtantc&oauth_signature_method=PLAINTEXT&oauth_token=918v4lxg2w23car&oauth_version=1.0&oauth_signature=fbs34nykryouuj1%26rbbprgh95tjzf22
using this am getting the error
{"error": "Call requires one of the following methods: PUT, POST, got GET!"}
please tell me anyone what to do for resolve this error.
public FileSystemInfo UploadFile(string root, string path, string file)
{
var uri = new Uri(new Uri(DropboxRestApi.ApiContentServer),
String.Format("files_put/{0}/{1}",
root, UpperCaseUrlEncode(path)));
var oauth = new OAuth();
//var requestUri = oauth.DownloadSignRequest(uri, _consumerKey, _consumerSecret, "POST", _accessToken);
var requestUri = oauth.SignRequest(uri, _consumerKey, _consumerSecret, _accessToken, "PUT");
var request = (HttpWebRequest) WebRequest.Create(requestUri);
request.Method = WebRequestMethods.Http.Post;
request.KeepAlive = true;
byte[] buffer;
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
int length = (int) fileStream.Length;
buffer = new byte[length];
fileStream.Read(buffer, 0, length);
}
request.ContentLength = buffer.Length;
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(buffer, 0, buffer.Length);
}
// request.Method = "POST";
var response = request.GetResponse();
var reader = new StreamReader(response.GetResponseStream());
var json = reader.ReadToEnd();
return ParseJson<FileSystemInfo>(json);
}
I made a mistaken in saving path of the file where i want to upload it.
Give the same file name for save in path.
that's all.