Bot work in local but not in azure - c#

I'm working on a chat bot that help users of a SharePoint on premise network to upload a file. The bot works on local but returns code 500 when tested in Azure.
I'm using Csom library to navigate in the site tree and the SharePoint _api to get all site collections. I have done some test and I don't think that is the Csom that causes this bug, but rather it is the NetworkCredential that doesn't work in Azure.
So can I use credential in Azure ?
I know that the problem comes from this function
public void GetAllSiteCollections(string url)
{
HttpWebRequest endpointRequest = (HttpWebRequest)HttpWebRequest.Create(url + "/_api/search/query?querytext='contentclass:sts_site'&trimduplicates=false&rowlimit=100");
endpointRequest.Method = "GET";
endpointRequest.Accept = "application/json;odata=verbose";
NetworkCredential cred = new NetworkCredential(Login, Mdp, DomaineUser);
endpointRequest.Credentials = cred;
HttpWebResponse endpointResponse = (HttpWebResponse)endpointRequest.GetResponse();
WebResponse webResponse = endpointRequest.GetResponse();
Stream webStream = webResponse.GetResponseStream();
StreamReader responseReader = new StreamReader(webStream);
string response = responseReader.ReadToEnd();
JObject jobj = JObject.Parse(response);
for (int ind = 0; ind < jobj["d"]["query"]["PrimaryQueryResult"]["RelevantResults"]["Table"]["Rows"]["results"].Count(); ind++)
{
string urlCollection = jobj["d"]["query"]["PrimaryQueryResult"]["RelevantResults"]["Table"]["Rows"]["results"][ind]["Cells"]["results"][6]["Value"].ToString();
string nomCollection = jobj["d"]["query"]["PrimaryQueryResult"]["RelevantResults"]["Table"]["Rows"]["results"][ind]["Cells"]["results"][3]["Value"].ToString();
if (urlCollection.Contains("myLocalDomain/sites/") == true)
{
string[] split = urlCollection.Split('/');
ClientCtx = new ClientContext(Domaine + "/sites/" + split[4]);
using (ClientCtx = new ClientContext(ClientCtx.Url))
{
ClientCtx.Credentials = new NetworkCredential(Login, Mdp, DomaineUser);
Web rootWeb = ClientCtx.Site.RootWeb;
ClientCtx.Load(rootWeb);
BasePermissions bp = new BasePermissions();
bp.Set(PermissionKind.AddListItems);
ClientResult<bool> viewListItems = rootWeb.DoesUserHavePermissions(bp);
ClientCtx.ExecuteQuery();
if (viewListItems.Value)
{
ListDesSiteCollections.Add(nomCollection, split[4]);
}
}
}
}
responseReader.Close();
}
When I check the logs at http://botName.azurewebsites.net/api/messages I get the response "The requested resource does not support http method 'GET'"

Related

OneDrive upload files with REST API via resumable session

Hi there currently I am trying to make files uploading to one drive trough REST API. But every time I am getting Exception with 401 code for non authorized
The remote server returned an error: (401) Unauthorized.
My code snippet
public async Task<string> UploadFileAsync(Account account, StorageFile file)
{
var publicClientApplication = PublicClientApplicationBuilder.Create(MicrosoftConstants.ClientId)
.WithRedirectUri(MicrosoftConstants.RedirectUri)
.Build();
var scopes = new string[]
{
"files.readwrite.all"
};
AuthenticationResult authToken = null;
try
{
authToken = await publicClientApplication.AcquireTokenInteractive(scopes).ExecuteAsync();
}
catch (Exception)
{
}
if (authToken != null)
{
var postData = new
{
item = new
{
name = file.Name
}
};
var json = JsonConvert.SerializeObject(postData);
var request = (HttpWebRequest)WebRequest.Create($"https://graph.microsoft.com/v1.0/me/drive/items/root:/{file.Name}:/createUploadSession");
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength= json.Length;
request.Headers["Authorization"] = "bearer" + authToken.AccessToken;
using (var requestStream = await request.GetRequestStreamAsync())
using (var streamWriter = new StreamWriter(requestStream))
{
streamWriter.Write(json);
}
var response = (HttpWebResponse)await request.GetResponseAsync();
}
return string.Empty;
}
Do anybody know what am I doing wrong?
To make it work I had to change header with authorization to
request.Headers["Authorization"] = "Bearer " + authToken.AccessToken;

EWS GetUserPhoto switch from Basic Auth to OAuth

I have been using Basic Auth to get user photo as below.
string email = "SomeEmail#email.com";
HttpWebRequest request = WebRequest.Create(string.Format("https://outlook.office365.com/EWS/Exchange.asmx/s/GetUserPhoto?email={0}&size=HR648x648", email)) as HttpWebRequest;
request.Credentials = new NetworkCredential("SomeID", "SomePwd");
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
Stream stream = response.GetResponseStream();
using (MemoryStream ms = new MemoryStream())
{
string encodedPhoto = Convert.ToBase64String((ms.ToArray()));
}
}
But since Basic Authentication for EWS will be decommissioned, I'm trying to use OAuth 2.0 for the same request. This is what I've tried so far.
var pcaOptions = new PublicClientApplicationOptions
{
ClientId = ConfigurationManager.AppSettings["appId"],
TenantId = ConfigurationManager.AppSettings["tenantId"]
};
var pca = PublicClientApplicationBuilder.CreateWithApplicationOptions(pcaOptions).Build();
var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };
var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();
var ewsClient = new ExchangeService();
string email = "SomeEmail#Email.com";
ewsClient.Url = new Uri(string.Format("https://outlook.office365.com/EWS/Exchange.asmx/s/GetUserPhoto?email={0}&size=HR648x648", email));
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
How can I proceed to get user photo from here? Any help or information will be very much appreciated.
You don't need to use the EWS Managed API you can just modify you existing code to include the Access token eg
string email = "SomeEmail#email.com";
HttpWebRequest request = WebRequest.Create(string.Format("https://outlook.office365.com/EWS/Exchange.asmx/s/GetUserPhoto?email={0}&size=HR648x648", email)) as HttpWebRequest;
request.Headers.Add("Authorization", "Bearer " + authResult.AccessToken);
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
Stream stream = response.GetResponseStream();
using (MemoryStream ms = new MemoryStream())
{
string encodedPhoto = Convert.ToBase64String((ms.ToArray()));
}
}
or if you do want to use the EWS managed API you can use something like
String ETag = "";
GetUserPhotoResults grPhoto = service.GetUserPhoto("user#domain.com", "HR240x240", ETag);
if (grPhoto.Status == GetUserPhotoStatus.PhotoReturned)
{
ETag = grPhoto.EntityTag;
}
grPhoto = service.GetUserPhoto("user#domain.com", "HR240x240", ETag);
switch (grPhoto.Status)
{
case GetUserPhotoStatus.PhotoReturned: ETag = grPhoto.EntityTag;
break;
case GetUserPhotoStatus.PhotoUnchanged:
Console.WriteLine("Photo Unchanged");
break;
}
I would recommend you to use Microsoft Graph API to get User Photo. Refer, https://learn.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0
Try it out using Graph Explorer
https://developer.microsoft.com/en-us/graph/graph-explorer?request=me%2Fphoto%2F%24value&method=GET&version=v1.0&GraphUrl=https://graph.microsoft.com
Get started with Graph .Net SDK
https://learn.microsoft.com/en-us/graph/sdks/sdks-overview
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var stream = await graphClient.Me.Photo.Content
.Request()
.GetAsync();

I'm looking for to generate access token using azure credentials in c#

I'm looking for to generate access token using azure credentials in c#. This is my code but its not working.With this i'm facing Unexpected character '<' error.
var uri = $"https://login.microsoftonline.com/common/oauth2/token";
var parameters = new Dictionary<string, dynamic>()
{
["grant_type"] = "password",
["client_id"] ="Azure client id"
["username"] = "CRM User name",
["password"] = "CRM Passowrd",
["client_secret"] ="Azure Client app scret"
["resource"] = "Your CRM Url",
};
var request = WebRequest.CreateHttp(uri);
request.Method = "POST";
var body = Encoding.ASCII.GetBytes(parameters.UrlEncode());
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = body.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(body, 0, body.Length);
}
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
{
var serializer = new DataContractJsonSerializer(typeof(Token));
return serializer.ReadObject(stream) as Token;
}
Here is an example of how a crm token is retreived using postman < you can applythis in your c# code. but get this right first:
also make sure that Azure Active directory > application has the above reply url and dynamics security assigned (api permissions).

How to redirect call to API from particular proxy server?

I have an API which i want to get access from one of my proxy server only. As that server have given all access to access that particular API. So I have single endpoint.
I have proxy server URL and Port and i want to add proxy settings in my app settings file and implement it so when call is given to API, that particular call pass through the Proxy server.
Please assist me how can I achieve this?
Current Call to API as below.
PushMessageAndroidRequest req = new PushMessageAndroidRequest();
req.registration_ids = list.Select(x => x.Token).ToList();
req.data = new AndroidData() { Payload = CommonLib.ConvertObjectToJson(payload) };
response = await RequestHandler.PostDataAsync<PushMessageResponse>(_appConfig.pushMessageConfigs.Url, req, new List<KeyValue>() { new KeyValue("Authorization", "key=" + _appConfig.pushMessageConfigs.Key) });
Sample code have written
public static async Task<ResJsonOutput> ProxyDataAsync(string ApiPath,string obj, List<KeyValue> Headers = null)
{
ResJsonOutput result = new ResJsonOutput();
HttpResponseMessage response = new HttpResponseMessage();
var requestUri = string.Format(ApiPath);
var request = (HttpWebRequest)WebRequest.Create(requestUri);
WebProxy myproxy = new WebProxy(Settings.ProxyAddress, Settings.ProxyPort);
myproxy.BypassProxyOnLocal = false;
request.Proxy = myproxy;
using (WebResponse response = request.GetResponse())
{
using (StreamReader stream = new StreamReader(response.GetResponseStream()))
{
//JObject jResponse = JObject.Parse(stream.ReadToEnd());
//var isSuccess = jResponse.Value<bool>("success");
//result = (isSuccess) ? true : false;
}
}
return result;
}

401 Authentication issue with BeanStream Payment Gateway API

I have been trying to integrate BeanStream payment gateway with my product from last three days. But unfortunately I am getting 401 authentication error every time. I have performed following steps.
1) Created a test account.
2) Generated API Pass Code from Configuration -> Payment Profile Configuration -> Security Settings.
3) Got merchant Id from top section.
4) Created an HttpWeb request using the sample code provided on BeanStream developer portal. Below is the code for that.
string url = "https://www.beanstream.com/api/v1/payments";
BeanStreamRequest req = new BeanStreamRequest
{
order_number = "10000123",
amount = 100.00m,
payment_method = "",
card = new Card {
name = "abc",
number = "5100000010001004",
expiry_month = "02",
expiry_year = "18",
cvd = "642"
}
};
JavaScriptSerializer js = new JavaScriptSerializer();
string jsonString = js.Serialize(req);
string merchantId = "MERCHANT_ID";
string apiPassCode = "API_PASS_CODE";
string base64_encode = String.Format("{0}{1}{2}",merchantId,":",apiPassCode);
string authorization = String.Format("{0}{1}", "Passcode ", Convert.ToBase64String(Encoding.ASCII.GetBytes(base64_encode)));
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.Accept = "*/*";
webRequest.Headers[HttpRequestHeader.Authorization] = authorization;
//webRequest.Headers.Add("Authorization ", authorization);
webRequest.ContentType = "application/json";
webRequest.ContentLength = jsonString.Length;
StreamWriter writer = null;
writer = new StreamWriter(webRequest.GetRequestStream());
writer.Write(jsonString);
writer.Close();
string responseString;
try
{
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
using (StreamReader responseStream = new StreamReader(webResponse.GetResponseStream()))
{
responseString = responseStream.ReadToEnd();
}
}
}
catch (WebException ex)
{
if (ex.Response != null)
{
using (HttpWebResponse errorResponse = (HttpWebResponse)ex.Response)
{
using (StreamReader reader = new StreamReader(errorResponse.GetResponseStream()))
{
string remoteEx = reader.ReadToEnd();
}
}
}
}
Any help?
The issue you are having is that you are creating an API Key (Passcode) for a Payment Profile API (http://developer.beanstream.com/documentation/tokenize-payments/) and then using it in a Payments API (http://developer.beanstream.com/documentation/take-payments/). These two resources use different API Keys (Passcodes). See "Where is my API Passcode?" on http://developer.beanstream.com/documentation/your-first-integration/. Create an API Key for Payments API and everything should work as expected.

Categories