Wait for user to complete its Authentication C# asp.net MVC - c#

So I Have A project in which I upload a video to daily motion with API and for uploading a video with api I need an authorized access token.
So the problem I am getting is that when my program starts the authorizing process it didn't wait for a user to complete its authorizing and exchange the token it goes to a new step.
hope you understand my problem
[HttpPost]
public ActionResult Add(Video Videos)
{
var accessToken = GetAccessToken();
Authorize(accessToken);//should wait here for user to complete the
// process and then move to the next step
var fileToUpload = #"C:\Users\Hassan\Downloads\SampleVideo_1280x720_1mb.mp4";
var uploadUrl = GetFileUploadUrl(accessToken);
var response = GetFileUploadResponse(fileToUpload, accessToken, uploadUrl);
var uploadedResponse = PublishVideo(response, accessToken,Videos.VideoName,Videos.Tags);
var TEST = Privateid(response, accessToken,uploadedResponse.id);
Videos.PrivateID = TEST.private_id;
Videos.VideoEmbeddedCode = TEST.embed_html;
_context.Videos.Add(Videos);
_context.SaveChanges();
return RedirectToAction("AddVideo", "Admin");
}
GetAccessToken and Authroize Method
private static string GetAccessToken()
{
var request = WebRequest.Create("https://api.dailymotion.com/oauth/token");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var requestString = String.Format("grant_type=password&client_id={0}&client_secret={1}&username={2}&password={3}",
HttpUtility.UrlEncode(ConfigurationManager.AppSettings["Key"]),
HttpUtility.UrlEncode(ConfigurationManager.AppSettings["secret"]),
HttpUtility.UrlEncode(ConfigurationManager.AppSettings["usernameAPI"]),
HttpUtility.UrlEncode(ConfigurationManager.AppSettings["passwordAPI"]));
var requestBytes = Encoding.UTF8.GetBytes(requestString);
var requestStream = request.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
var response = request.GetResponse();
var responseStream = response.GetResponseStream();
string responseString;
using (var reader = new StreamReader(responseStream))
{
responseString = reader.ReadToEnd();
}
var oauthResponse = JsonConvert.DeserializeObject<OAuthResponse>(responseString);
return oauthResponse.access_token;
}
private static void Authorize(string accessToken)
{
var authorizeUrl = String.Format("https://api.dailymotion.com/oauth/authorize?response_type=code&client_id={0}&scope=read+write+manage_videos+delete&redirect_uri={1}",
HttpUtility.UrlEncode(ConfigurationManager.AppSettings["Key"]),
HttpUtility.UrlEncode(ConfigurationManager.AppSettings["callbackurl"]));
Process.Start(authorizeUrl);
var client = new WebClient();
client.Headers.Add("Authorization", "OAuth " + accessToken);
}

Make the Authorize method async like private static async Task Authorize(string accessToken) and insert an await operator like: await Authorize(accessToken);

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;

How to POST data in Dynamics 365 using HttpWebRequest

I have requirement to read data from Dynamics 365 online and to write data as well.
Since my application Target Framework is .Net Core 2.1 so I am unable to use Microsoft.Xrm.Sdk and decided to use Web api instead.
In my code I am using HttpWebRequest with "GET" and "POST" methods, the GET operation works fine and am able to retrieve records from D365 using web api.
When I use the POST operation the code executes properly without any error but when I navigate to D365 entity I do not see any newly created record.
Below is my code
The GetContactDetailsAsync function works fine and returns result but the CreateCaseAsync function is not working
public static async Task<string> GetContactDetailsAsync()
{
string organizationUrl = "https://xxxxx.crmX.dynamics.com";
string clientId = "xxxxxxxx-73aa-xxxx-94cc-8dc7941f6600";
string appKey = "Xxxx81H/7TUFErt5C/xxxxxxxxxxxxxxxxxxxxxxx=";
string aadInstance = "https://login.microsoftonline.com/";
string tenantID = "xxxxxxxx.onmicrosoft.com";
try
{
ClientCredential clientcred = new ClientCredential(clientId, appKey);
AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID);
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(organizationUrl, clientcred);
var requestedToken = authenticationResult.AccessToken;
var webRequest = (HttpWebRequest)WebRequest.Create(new Uri("https://xxxxxxxxxx.api.crmx.dynamics.com/api/data/v9.1/contacts()?$select=fullname,contactid,emailaddress1&$filter=mobilephone eq '"+History.userMobile+"'"));
webRequest.KeepAlive = false;
webRequest.ServicePoint.ConnectionLimit = 1;
webRequest.Method = "GET";
webRequest.ContentLength = 0;
webRequest.Headers.Add("Authorization", String.Format("Bearer {0}", requestedToken));
webRequest.Headers.Add("OData-MaxVersion", "4.0");
webRequest.Headers.Add("OData-Version", "4.0");
webRequest.Accept = "application/json";
webRequest.ContentType = "application/json";
//if contact with user provided phone number found, ask for problem description
try
{
using (var response1 = webRequest.GetResponse() as System.Net.HttpWebResponse)
{
using (var reader = new System.IO.StreamReader(response1.GetResponseStream()))
{
var response = reader.ReadToEnd();
}
}
}
catch (Exception ex)
{
History.isUserFound = false;
string error = ex.Message;
return "Sorry, I found that you are not using any of our services...";
}
}
catch (Exception ex) { return ex.ToString(); }
}
public static async void CreateCaseAsync()
{
string organizationUrl = "https://xxxxx.crmX.dynamics.com";
string clientId = "xxxxxxxx-73aa-xxxx-94cc-8dc7941f6600";
string appKey = "Xxxx81H/7TUFErt5C/xxxxxxxxxxxxxxxxxxxxxxx=";
string aadInstance = "https://login.microsoftonline.com/";
string tenantID = "xxxxxxxx.onmicrosoft.com";
//trying to establish connection with D365 here
try
{
ClientCredential clientcred = new ClientCredential(clientId, appKey);
AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID);
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(organizationUrl, clientcred);
var requestedToken = authenticationResult.AccessToken;
var webRequest = (HttpWebRequest)WebRequest.Create(new Uri("https://xxxxxxxx.api.crmx.dynamics.com/api/data/v9.1/incidents"));
webRequest.KeepAlive = false;
webRequest.ServicePoint.ConnectionLimit = 1;
webRequest.Method = "POST";
webRequest.Headers.Add("Authorization", String.Format("Bearer {0}", requestedToken));
webRequest.Headers.Add("OData-MaxVersion", "4.0");
webRequest.Headers.Add("OData-Version", "4.0");
webRequest.Accept = "application/json";
webRequest.ContentType = "application/json";
string json = "{\"title\":\"title by chat bot\"}";
byte[] byteArray;
byteArray = Encoding.UTF8.GetBytes(json);
webRequest.ContentLength = byteArray.Length;
try
{
Stream requestDataStream = await webRequest.GetRequestStreamAsync();
requestDataStream.Write(byteArray, 0, byteArray.Length);
requestDataStream.Close();
}
catch (Exception ex) { }
}
catch (Exception ex) { }
}
I have tried changing
string json = "{\"title\":\"title by chat bot\"}" to
"{'title':'title by chat bot'}" and "{title:title by chat bot}" as well.
Also I have tried changing
Stream requestDataStream = await webRequest.GetRequestStreamAsync(); to
Stream requestDataStream = webRequest.GetRequestStream(); as well
but nothing worked.
Unable to figure out what I am missing in my code. Any help is highly appriciated.
Actually code looks fine but you should get 400 Bad request exception. Because the json is missing customerid and the basic payload for creating incident should be like below:
{
"title": "title by chat bot",
"customerid_account#odata.bind": "/accounts(f686f062-e542-e811-a955-000d3ab27a43)"
}
You can refer this SO thread for clarity.
Here is the Code for Webapi using Javascript. I just tried below code in my Org and it worked for me.
var entity = {};
entity.title = "CCCCAAAASSSEEEE";
var req = new XMLHttpRequest();
req.open("PATCH", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/incidents(BA8BC3CD-D94F-E911-A82F-000D3A385A1C)", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function() {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 204) {
//Success - No Return Data - Do Something
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send(JSON.stringify(entity));
and Below is the link where you could find exactly how to use PATCH method for CRM using c#
https://learn.microsoft.com/en-us/dynamics365/customer-engagement/developer/webapi/web-api-functions-actions-sample-csharp

411 - Length Required When Attempting to POST

I am developing a mobile application using Xamarin. This makes it so I cannot call webRequest.ContentLength = 0.
Here is how I am attempting to post:
Client calls:
await new AssetEndpoint().UpdateStatus(Authentication, CurrentAsset, ApprovalStatuses[0]);
AssetEndpoint.UpdateStatus:
public Task UpdateStatus(Authentication auth, Asset asset, ApprovalStatus newStatus)
{
return PostResponseAsync(auth, string.Format(
ApiUpdateStatus, asset.UID, newStatus.Id));
}
Endpoint.PostResponseAsync:
protected async Task<string> PostResponseAsync(Authentication auth, string apiCall)
{
var request = WebRequest.Create(string.Concat(BaseUriPath, apiCall)) as HttpWebRequest;
request.ContentType = "application/json";
request.Method = method;
request.Headers["Authorization"] = string.Concat("bearer ", auth.Token.Value);
var response = await request.GetResponseAsync().ConfigureAwait(false);
using (var reader = new StreamReader(response.GetResponseStream()))
{
return await reader.ReadToEndAsync();
}
}
So I do go about fixing this error? I cannot seem to figure out how to set the content length.
It can be the problem in Xamarin version you are using:
http://forums.xamarin.com/discussion/comment/58076#Comment_58076
public class RestClientTest
{
public static async Task<string> Login()
{
try
{
var request = WebRequest.CreateHttp(path);
request.Headers["Username"] = "xxxxxxxxx";
request.Headers["Password"] = "xxxxxxxxxxx";
request.ContentType = "application/json";
request.Method = "POST";
byte[] byteArray = new byte[] { 0x31, 0x32, 0x33, 0x34, 0x35 };
using (Stream dataStream = await request.GetRequestStreamAsync())
{
await dataStream.WriteAsync(byteArray, 0, byteArray.Length);
}
var response = await request.GetResponseAsync().ConfigureAwait(false);
using (var reader = new StreamReader(response.GetResponseStream()))
{
string resp = await reader.ReadToEndAsync();
return resp;
}
}
catch (Exception ex)
{
return "Error";
}
}
}
If that doesn't work for you I can provide HttpClient sample if you want to try. Without knowing what you are posting I cannot help more. I also tested this code without sending any data in the body and it works too.

Handling http response codes in GetStringAsync

i'm very new to C#, let alone Windows Phone development :)
I'm trying to send a request, get the JSON response, but if there is an error (such as 401), be able to tell the user such. Here is my code:
async Task<string> AccessTheWebAsync()
{
//builds the credentials for the web request
var credentials = new NetworkCredential(globalvars.username, globalvars.password);
var handler = new HttpClientHandler { Credentials = credentials };
//calls the web request, stores and returns JSON content
HttpClient client = new HttpClient(handler);
Task<string> getStringTask = client.GetStringAsync("https://www.bla.com/content");
String urlContents = await getStringTask;
return urlContents;
}
I know it must be something I'm doing wrong in the way that I send the request and store the response...but i'm just not sure what.
If there is an error, I get a general:
net_http_message_not_success_statuscode
Thank you!
You could use te GetAsync() method instead of the GetStringAsync().
HttpResponseMessage response = await client.GetAsync("https://www.bla.com/content");
if(!response.IsSuccessStatusCode)
{
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
do something...
}
}
String urlContents = await response.Content.ReadAsStringAsync();
This way you can make use of the HttpStatusCode enumerable to check the returned status code.
Instead of using an HttpClient use a plain good old HttpWebRequest :)
async Task<string> AccessTheWebAsync()
{
HttpWebRequest req = WebRequest.CreateHttp("http://example.com/nodocument.html");
req.Method = "GET";
req.Timeout = 10000;
req.KeepAlive = true;
string content = null;
HttpStatusCode code = HttpStatusCode.OK;
try
{
using (HttpWebResponse response = (HttpWebResponse)await req.GetResponseAsync())
{
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
content = await sr.ReadToEndAsync();
code = response.StatusCode;
}
}
catch (WebException ex)
{
using (HttpWebResponse response = (HttpWebResponse)ex.Response)
{
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
content = sr.ReadToEnd();
code = response.StatusCode;
}
}
//Here you have now content and code.
return content;
}

WP7 Create helper class for easy use HttpWebRequest with POST method

Actually I have something like this:
private void createHttpRequest()
{
System.Uri myUri = new System.Uri("..url..");
HttpWebRequest myHttpRequest = (HttpWebRequest)HttpWebRequest.Create(myUri);
myHttpRequest.Method = "POST";
myHttpRequest.ContentType = "application/x-www-form-urlencoded";
myHttpRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), myHttpRequest);
}
void GetRequestStreamCallback(IAsyncResult callbackResult)
{
HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
// End the stream request operation
Stream postStream = myRequest.EndGetRequestStream(callbackResult);
string hash = HashHelper.createStringHash("123", "TEST", "0216");
// Create the post data
byte[] byteArray = createByteArrayFromHash(hash);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
myRequest.BeginGetResponse(new AsyncCallback(GetResponsetStreamCallback), myRequest);
}
void GetResponsetStreamCallback(IAsyncResult callbackResult)
{
HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
{
string result = httpWebStreamReader.ReadToEnd();
ApiResponse apiResponse = (ApiResponse)JsonConvert.DeserializeObject<ApiResponse>(result);
}
}
It's good, it's working but now I must use these methods in every page and just change method createByteArrayFromHash which creates request. What if I want to create helper class that can help me to do this in something about 3 lines of code in page. How would you do that? I was thinking about this way but how to add request before response? Or would you do it another way? Thanks
Yeah, it's better to use async and await. Here is an example of such a wrapper:
public async Task<string> SendRequestGetResponse(string postData, CookieContainer cookiesContainer = null)
{
var postRequest = (HttpWebRequest)WebRequest.Create(Constants.WebServiceUrl);
postRequest.ContentType = "Your content-type";
postRequest.Method = "POST";
postRequest.CookieContainer = new CookieContainer();
postRequest.CookieContainer = App.Session.Cookies;
using (var requestStream = await postRequest.GetRequestStreamAsync())
{
byte[] postDataArray = Encoding.UTF8.GetBytes(postData);
await requestStream.WriteAsync(postDataArray, 0, postDataArray.Length);
}
var postResponse = await postRequest.GetResponseAsync() as HttpWebResponse;
if (postResponse != null)
{
var postResponseStream = postResponse.GetResponseStream();
var postStreamReader = new StreamReader(postResponseStream);
// Can use cookies if you need
if (cookiesContainer == null)
{
if (!string.IsNullOrEmpty(postResponse.Headers["YourCookieHere"]))
{
var cookiesCollection = postResponse.Cookies;
// App.Session is a global object to store cookies and etc.
App.Session.Cookies.Add(new Uri(Constants.WebServiceUrl), cookiesCollection);
}
}
string response = await postStreamReader.ReadToEndAsync();
return response;
}
return null;
}
You can modify it as you wish

Categories