C# WebApi HttpClient Unauthorized - httpclient

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.

Related

upgrade to HttpClient with .Net (C#)

I'm using this code to read response from paypal transaction.
Can you please help me to upgrade this code using HttpClient?
public static PDTHolder Success(string tx)
{
PayPalConfig payPalConfig = PayPalService.getPayPalConfig();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
authToken = payPalConfig.AuthToken;
txToken = tx;
query = string.Format("cmd=_notify-sync&tx={0}&at={1}", txToken, authToken);
string url = payPalConfig.PostUrl;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = query.Length;
StreamWriter stOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
stOut.Write(query);
stOut.Close();
StreamReader stIn = new StreamReader(req.GetResponse().GetResponseStream());
strResponse = stIn.ReadToEnd();
stIn.Close();
if (strResponse.StartsWith("SUCCESS"))
return PDTHolder.Parse(strResponse);
return null;
}

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();
}

Upload local file to SharePoint Online using HttpWebRequest

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();
}

ASP.NET MVC Web API 4 REST Webservice: PUT/POST - ing a List of objects

Wondering if its possible and/or supported to put/post an entire object to REST Webservice, as opposed to just some name/value pairs ?
If so, can a List of objects be put/post-ed as well ?
I figured it may be possible, since a GET request is able to return a List of objects, I'd like to do the "reverse" operation with the updated objects (and not send them one at a time, or worse, in individual pieces via name/value pairs) ?
I understand this is a very basic question, but the approach I've taken so far was to just try and code the PUT and get it working (which works if the PUT function has no arguments, like:
public class AObjectController : ApiController
{
public List<int[]> Put()
{
List<int[]> ret = new List<int[]>();
ret.Add(new int[] {-1, 1111});
ret.Add(new int[] {-2, 2222});
return ret;
}
If I specify a single object, or list of objects, I get exceptions:
public List<int[]> Put(AObject object) **CASE 1**
public List<int[]> Put(List<AObject> objects) **CASE 2**
{
List<int[]> ret = new List<int[]>();
ret.Add(new int[] { -1, 1111 });
ret.Add(new int[] { -2, 2222 });
return ret;
}
CASE 1: public List(int[]) Put(AObject object)
CASE 2: public List(int[]) Put(List(AObject) objects)
Heres the code on the client side that is making the call:
public int writeAll(List<T> data)
{
_sendBuffer =
JsonConvert.SerializeObject(
tabletData,
new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }
);
byte[] b = StringHelper.GetBytes(_sendBuffer);
string url = ContructUrlRequest(null, null);
WebRequest request = WebRequest.Create(url);
request.Method = "PUT";
request.ContentType = "application/json";
request.ContentLength = b.Length;
request.Credentials = CredentialCache.DefaultCredentials;
((HttpWebRequest)request).UserAgent = "...";
//((HttpWebRequest)request).AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(b, 0, b.Length);
requestStream.Flush();
requestStream.Close();
}
WebResponse response = request.GetResponse();
if (response == null)
{
return -1;
}
StreamReader sr = new StreamReader(response.GetResponseStream()); ;
_recieveBuffer = sr.ReadToEnd();
List<int[]> _resultData = JsonConvert.DeserializeObject<List<int[]>>(
_recieveBuffer,
new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }
);
return data.Count;
}
Thank you.
Used the serialization write code from server on my client side and it worked
public int writeAll(List<AObject> aObjects)
{
string url = ContructUrlRequest(null, null);
WebRequest request = WebRequest.Create(url);
request.Method = WebRequestMethods.Http.Put;
request.ContentType = "application/json; charset=utf-8";
request.Credentials = CredentialCache.DefaultCredentials;
((HttpWebRequest)request).UserAgent = "going insane";
JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
serializerSettings.TypeNameHandling = TypeNameHandling.Objects | TypeNameHandling.Arrays;
serializerSettings.Converters.Add(new IsoDateTimeConverter());
JsonSerializer serializer = JsonSerializer.Create(serializerSettings);
using (Stream requestStream = request.GetRequestStream())
{
using (StreamWriter streamWriter = new StreamWriter(requestStream, new UTF8Encoding(false, true)))
{
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter))
{
serializer.Serialize(jsonTextWriter, aObjects);
}
}
}
WebResponse response = request.GetResponse();
if (response == null)
{
Log.Info(FIDB.TAG_WSBUFFER, "WSBuffer.writeAll: response = NULL");
return -1;
}
StreamReader sr = new StreamReader(response.GetResponseStream());
_recieveBuffer = sr.ReadToEnd();
_resultData = JsonConvert.DeserializeObject<List<int[]>>(
_recieveBuffer,
new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }
);
return tabletData.Count;
}