Upload local file to SharePoint Online using HttpWebRequest - rest

I'm trying to upload a file to a SharePoint online site that I have permissions for, I have tried using an HttpWebRequest to get an XDocument to allow me to upload a file but when I call an HttpWebResponse I get the error "The underlying connection was closed: An unexpected error occurred on a receive."
I'm unable to use SharePoint client object model as this app is to be used on PCs that don't have a SharePoint installation.

You will need to create a digest:
HttpClient client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
client.BaseAddress = new System.Uri(url);
string cmd = "_api/contextinfo";
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
client.DefaultRequestHeaders.Add("ContentType", "application/json");
client.DefaultRequestHeaders.Add("ContentLength", "0");
StringContent httpContent = new StringContent("");
var response = client.PostAsync(cmd, httpContent).Result;
if (response.IsSuccessStatusCode)
{
string content = response.Content.ReadAsStringAsync().Result;
JsonObject val = JsonValue.Parse(content).GetObject();
JsonObject d = val.GetNamedObject("d");
JsonObject wi = d.GetNamedObject("GetContextWebInformation");
retVal = wi.GetNamedString("FormDigestValue");
}
Then you can use the following example to upload the file and retrieve its metadata from the http response:
HttpClient client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
client.BaseAddress = new System.Uri(url);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
client.DefaultRequestHeaders.Add("X-RequestDigest", digest);
client.DefaultRequestHeaders.Add("X-HTTP-Method", "POST");
client.DefaultRequestHeaders.Add("binaryStringRequestBody", "true");
IRandomAccessStream fileStream = await path.OpenAsync(FileAccessMode.Read);
var reader = new DataReader(fileStream.GetInputStreamAt(0));
await reader.LoadAsync((uint)fileStream.Size);
Byte[] content = new byte[fileStream.Size];
reader.ReadBytes(content);
ByteArrayContent file = new ByteArrayContent(content);
HttpResponseMessage response = await client.PostAsync(String.Concat("_api/web/lists/getByTitle('Project Photos')/RootFolder/Files/add(url='", filename, ".jpg',overwrite='true')?$expand=ListItemAllFields"), file);
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
var info = response.Content.ReadAsStringAsync();
JsonObject d = JsonValue.Parse(info.Result).GetObject();
string id = d["d"].GetObject()["ListItemAllFields"].GetObject().GetNamedValue("ID").Stringify();
}

Related

VSTS Web Api gives 403 unauthoratative response

I have created a native app in Azure using App Registration and added required permissions for VSTS Agent
Now, I am able to login using oauth authentication with "ADAL" and able to get the token but when trying to access the web api request it gives Http 403 Response
Here is the code example below
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(vstsCollectionUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("X-TFS-FedAuthRedirect", "Suppress");
client.DefaultRequestHeaders.Authorization = authHeader;
HttpResponseMessage res = client.GetAsync(webapiURL).Result;
}
Please let me know what i am missing
thanks in advance
Seems it's an authentication issue, Just check the value of authHeader.
You can reference below samples for the authentication with header:
Sample 1- auth-samples here ;
Sample 2 - REST API
Post the auth sample as reference here:
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
namespace DeviceProfileSample
{
public class Program
{
//============= Config [Edit these with your settings] =====================
internal const string vstsCollectionUrl = "https://myaccount.visualstudio.com"; //change to the URL of your VSTS account; NOTE: This must use HTTPS
internal const string clientId = "872cd9fa-d31f-45e0-9eab-6e460a02d1f1"; //update this with your Application ID from step 2.6 (do not change this if you have an MSA backed account)
//==========================================================================
internal const string VSTSResourceId = "499b84ac-1321-427f-aa17-267ca6975798"; //Static value to target VSTS. Do not change
public static void Main(string[] args)
{
AuthenticationContext ctx = GetAuthenticationContext(null);
AuthenticationResult result = null;
try
{
DeviceCodeResult codeResult = ctx.AcquireDeviceCodeAsync(VSTSResourceId, clientId).Result;
Console.WriteLine("You need to sign in.");
Console.WriteLine("Message: " + codeResult.Message + "\n");
result = ctx.AcquireTokenByDeviceCodeAsync(codeResult).Result;
var bearerAuthHeader = new AuthenticationHeaderValue("Bearer", result.AccessToken);
ListProjects(bearerAuthHeader);
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Something went wrong.");
Console.WriteLine("Message: " + ex.Message + "\n");
}
}
private static AuthenticationContext GetAuthenticationContext(string tenant)
{
AuthenticationContext ctx = null;
if (tenant != null)
ctx = new AuthenticationContext("https://login.microsoftonline.com/" + tenant);
else
{
ctx = new AuthenticationContext("https://login.windows.net/common");
if (ctx.TokenCache.Count > 0)
{
string homeTenant = ctx.TokenCache.ReadItems().First().TenantId;
ctx = new AuthenticationContext("https://login.microsoftonline.com/" + homeTenant);
}
}
return ctx;
}
private static void ListProjects(AuthenticationHeaderValue authHeader)
{
// use the httpclient
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(vstsCollectionUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("User-Agent", "VstsRestApiSamples");
client.DefaultRequestHeaders.Add("X-TFS-FedAuthRedirect", "Suppress");
client.DefaultRequestHeaders.Authorization = authHeader;
// connect to the REST endpoint
HttpResponseMessage response = client.GetAsync("_apis/projects?stateFilter=All&api-version=2.2").Result;
// check to see if we have a succesfull respond
if (response.IsSuccessStatusCode)
{
Console.WriteLine("\tSuccesful REST call");
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
throw new UnauthorizedAccessException();
}
else
{
Console.WriteLine("{0}:{1}", response.StatusCode, response.ReasonPhrase);
}
}
}
}
}
Aren't you missing what authentication,
string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", token)));
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(vstsCollectionUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials)
HttpResponseMessage response = client.GetAsync(uri).Result;
response.EnsureSuccessStatusCode();
var responseStream = await response.Content.ReadAsStreamAsync();
}
I hope this helps.

How to add image file in Adobe AEM JCR using rest API from .Net

I googled alot but not getting any documentation of Adobe AEM for restfull API. I tried the .Net code from
https://helpx.adobe.com/experience-manager/using/using-net-client-application.html.
But it creates folder instead of uploading content.
What are the parameters we need to pass to upload any image, mp4, pdf etc. Below is my c# code.
protected void Button1_Click(object sender, EventArgs e)
{
string fileName=FileUpload1.FileName;
String postURL = "http://localhost:4502/content/dam/geometrixx/" + fileName;
System.Uri uri = new System.Uri(postURL);
HttpWebRequest httpWReq = (HttpWebRequest)WebRequest.Create(uri);
NetworkCredential nc = new NetworkCredential("admin", "admin");
httpWReq.Method = "POST";
httpWReq.Credentials = nc;
httpWReq.ContentType = "application/x-www-form-urlencoded";
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] data = FileUpload1.FileBytes;
httpWReq.ContentLength = data.Length;
using (System.IO.Stream stream = httpWReq.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
string responseText = string.Empty;
using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
{
responseText = reader.ReadToEnd();
}
TextBox1.Text = responseText;
}
I'm not familar with .Net, but the question is more about how to create an asset in AEM. You didn't specify any version, so I tested my code only on AEM 5.6.1, but it should work also on AEM 6.X. In the following snippet you can see how you can upload new file using curl into a folder of your choice in dam, so you have only to make the call from your .Net code:
curl -u admin:admin -X POST -F file=#"/absolute/path/to/your/file.ext" http://localhost:4502/content/dam/the/path/you/wish/to/upload/myfolder.createasset.html
You are sending a POST request to the dam path where the file have to be uploaded with the selector "createasset" and the extension "html".
.net code for uploading files on Aem. Try below code.
var filelocation = AppDomain.CurrentDomain.BaseDirectory + "Images\\YourFile with Extension";
FileStream stream = File.OpenRead(filelocation);
byte[] fileBytes = new byte[stream.Length];
stream.Read(fileBytes, 0, fileBytes.Length);
stream.Close();
var httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential("admin", "Your Password"),
};
//var httpClient = new HttpClient(httpClientHandler);
using (var httpClient = new HttpClient(httpClientHandler))
{
var requestContent = new MultipartFormDataContent();
var imageContent = new ByteArrayContent(fileBytes);
requestContent.Add(imageContent, "file", "file nmae with extension");
var response1 = httpClient.PostAsync("http://siteDomain/content/dam/yourfolder.createasset.html", requestContent);
var result = response1.Result.Content.ReadAsStringAsync();
}

C# WebApi HttpClient Unauthorized

I have an issue about webapi2 and Authorization.
If I call web api with the old .Net 2.0 client (WebClient) there are not problems and the code is here:
//old 2.0 client
using (WebClient oldClient = new WebClient())
{
oldClient.UseDefaultCredentials = true;
oldClient.Credentials = CredentialCache.DefaultCredentials;
oldClient.Headers[HttpRequestHeader.ContentType] = "application/json";
oldClient.Headers[HttpRequestHeader.Accept] = "application/json";
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
javaScriptSerializer.MaxJsonLength = 2147483644;
ASCIIEncoding encoding = new ASCIIEncoding();
string objectToSendJson = javaScriptSerializer.Serialize(objectToSend);
byte[] objectToSendByte = encoding.GetBytes(objectToSendJson);
byte[] serviceOutput = oldClient.UploadData(uri + actionController, "POST", objectToSendByte);
string jsonStr = Encoding.UTF8.GetString(serviceOutput);
toReturn = JsonConvert.DeserializeObject<T>(jsonStr);
return toReturn;
}
but if I use the new 4.5 HttpClient WebApi return me Unauthorized
and the code is here:
HttpClientHandler httpWebApiClienthandler = new HttpClientHandler
{
UseDefaultCredentials = true,
Credentials = CredentialCache.DefaultCredentials,
};
System.Net.Http.HttpClient newHttpClient = new System.Net.Http.HttpClient(httpWebApiClienthandler)
//new 4.5 client
JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
if (objectToSend == null)
throw new Exception("object to send is null");
HttpContent httpContent = new ObjectContent<object>(objectToSend, jsonFormatter);
httpContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
response = newHttpClient.PostAsync(actionController, httpContent).Result;
Any help is highly appreciated.

How to add new account in Quickbooks

Below is the code I am using to try to add a new account to QuickBooks online. I am getting a (400) Bad Request. Can anyone help me with this.
HttpWebRequest httpWebRequest =
WebRequest.Create("https://sandbox-quickbooks.api.intuit.com/v3/company/xxxxxxxxxxx/account")
as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(httpWebRequest, ConsumerKeyQb, ConsumerSecQb, AccessKey, AccessSec));
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "application/xml";
string json = "{\"AccountType\":\"Accounts Receivable\",\"Name\":\"MySampleAccount\"}";
byte[] bytes = Encoding.UTF8.GetBytes(json);
httpWebRequest.ContentLength = bytes.Length;
using (Stream putStream = httpWebRequest.GetRequestStream())
{
putStream.Write(bytes, 0, bytes.Length);
}
HttpWebResponse httpWebResponse = null;
try
{
httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
}
catch (Exception e)
{
//return null;
var x = "Stop";
}
Thanks
400 response suggests that your API request payload is not correct.
You can try this call using IPP provided .net devkit.
https://developer.intuit.com/docs/0025_quickbooksapi/0055_devkits/0150_ipp_.net_devkit_3.0/0002_synchronous_calls/0001_data_service_apis
Using Dev-defined lib( sample call ) -
https://gist.github.com/IntuitDeveloperRelations/0913b4c224de758fde0a
Thanks

How to add new header to jersey client to upload multipart file

Please find below jersey client code to upload multipart file:
String url = "http://localhost:7070"
Client client = Client.create();
WebResource webresource = client.resource(url);
File file = new File("C://Data//image1.jpg");
File thumbnail = new File("C://Data/image2.jpg");
InputStream isthumbnail = new FileInputStream(thumbnail);
InputStream isfile = new FileInputStream(file);
FormDataMultiPart multiPart = new FormDataMultiPart();
FormDataBodyPart bodyPart1 = new FormDataBodyPart(FormDataContentDisposition.name("Thumbnail").fileName("thumbnail").build(), isthumbnail, MediaType.APPLICATION_OCTET_STREAM_TYPE);
FormDataBodyPart bodyPart2 = new FormDataBodyPart(FormDataContentDisposition.name("File").fileName("file").build(), isfile, MediaType.APPLICATION_OCTET_STREAM_TYPE);
multiPart.bodyPart(bodyPart);
multiPart.bodyPart(bodyPart1);
//New Headers
String fileContentLength = "form-data; contentLength=\""+Long.toString(file.length())+ "\"";
String thumbnailContentLength = "form-data; contentLength=\""+Long.toString(file.length())+ "\"";
final ClientResponse clientResp = webresource.type(MediaType.MULTIPART_FORM_DATA_TYPE).accept(MediaType.APPLICATION_XML).post(ClientResponse.class, multiPart);
System.out.println("File Upload Success with Response"+clientResp.getStatus());
I need to add the String fileContentLength and thumbnailContentLength as header
Content-Length.
How do i add the headers as part of multipart and post the request?Any help would be appreciated
Use a FormDataContentDisposition as an argument to FormDataBodyPart(FormDataContentDisposition formDataContentDisposition, Object entity, MediaType mediaType).
final FormDataMultiPart formDataMultiPart = new FormDataMultiPart();
final String value = "Hello World";
final FormDataContentDisposition dispo = FormDataContentDisposition
.name("file")
.fileName("test.txt")
.size(value.getBytes().length)
.build();
final FormDataBodyPart bodyPart = new FormDataBodyPart(dispo, value);
formDataMultiPart.bodyPart(bodyPart);