When I tried to call the web method "QnAMakerQuestionsAnswers", It will only have an infinite loading and will not show the result. I have tried this in a console application and it works perfectly but not for the WebMethod. I am not sure which part of my code I need to modify but this is a little bit frustrating. Please help!!
Code is below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Net;
using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace ChatbotWebService
{
/// <summary>
/// Summary description for ChatbotWebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class ChatbotWebService : System.Web.Services.WebService
{
// NOTE: Replace this with a valid host name.
static string host = "<Host Name>";
// NOTE: Replace this with a valid endpoint key.
// This is not your subscription key.
// To get your endpoint keys, call the GET /endpointkeys method.
static string endpoint_key = "<End Point Key>";
// NOTE: Replace this with a valid knowledge base ID.
// Make sure you have published the knowledge base with the
// POST /knowledgebases/{knowledge base ID} method.
static string kb = "<KB ID>";
static string service = "/qnamaker";
static string method = "/knowledgebases/" + kb + "/generateAnswer/";
static string question = #"
{
'question': 'Who are you?'
}
";
async static Task<string> Post(string uri, string body)
{
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(uri);
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
request.Headers.Add("Authorization", "EndpointKey " + endpoint_key);
//SUPER IMPORTANT LINE. PLEASE DO IT FOR .NET Framework v4.5.
//Explanation at https://blogs.perficient.com/2016/04/28/tsl-1-2-and-net-support/
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var response = await client.SendAsync(request);
return await response.Content.ReadAsStringAsync();
}
}
async static Task<string> GetAnswers()
{
var uri = host + service + method;
Console.WriteLine("Calling " + uri + ".");
string response = "NULL";
try
{
response = await Post(uri, question);
Console.WriteLine(response);
Console.WriteLine("Press any enter to continue.");
}
catch (HttpRequestException e)
{
Console.WriteLine(e.InnerException.Message);
}
return response;
}
[WebMethod]
public string QnAMakerQuestionsAnswers()
{
return GetAnswers().Result;
}
}
}
Related
I send a request on the API, the request and the response are successful, but I want to get the value equivalent to the authentication keyword through the response. How can I do that? I tried this way on the examples I found, but it doesn't give any results .Net 6.0
using LoggerApi.Login;
using System;
using System.Net.Http;
using System.Text;
using Newtonsoft.Json;
using System.Linq;
using Microsoft.Extensions.Primitives;
namespace LoggerApi.Login
{
public class AdminLogin
{
public async static Task<object> GetAuthenticationCode()
{
var client = new HttpClient();
var loginEndpoint = new Uri("https://admin.com/login");
var loginPayload = new LoginPayload()
{
Username = "admin",
Password= "admin",
};
var requestJson = JsonConvert.SerializeObject(loginPayload);
var payload = new StringContent(requestJson, Encoding.UTF8, "application/json");
var res = await client.PostAsync(loginEndpoint, payload).Result.Headers.TryGetValues("authentication");
return res;
}
}
}
We have a console application that uses Aspose email dll for sending mails and various other functionalities.
Since it uses basic authentication that is getting deprecated soon by microsoft so we are planning to have authentication using Microsoft Graph API.
So I have done below steps
1)Registered the app in Microsoft Azure active directory and gave permissions under Microsoft Graph. PFA(AzureAPP_permissions.png)
2)I added code for generating token using graph API and then tried fetching email,sending email using Aspose dll but every time it throws below error.
**Aspose.Email.AsposeBadServerResponceException: 'Server error Status: BadRequest
Description: /me request is only valid with delegated authentication flow.
Details:
POST: https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages
---------------------------------------**
Please help what is going wrong here
PFB the code part
Graph_code
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Aspose.Email.Clients;
using Aspose.Email.Clients.Graph;
using Aspose.Email.Mapi;
using EASendMail;
namespace Email
{
internal class Graph_API
{
private static string _clientId = ConfigurationManager.AppSettings["ClientId"];
private static string _tenantId = ConfigurationManager.AppSettings["TenantId"];
private static string _secretValue = ConfigurationManager.AppSettings["SecretValue"];
static string _postString(string uri, string requestData)
{
HttpWebRequest httpRequest = WebRequest.Create(uri) as HttpWebRequest;
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
using (Stream requestStream = httpRequest.GetRequestStream())
{
byte[] requestBuffer = Encoding.UTF8.GetBytes(requestData);
requestStream.Write(requestBuffer, 0, requestBuffer.Length);
requestStream.Close();
}
try
{
HttpWebResponse httpResponse = httpRequest.GetResponse() as HttpWebResponse;
var responseText = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();
Console.WriteLine(responseText);
return responseText;
}
catch (WebException ep)
{
if (ep.Status == WebExceptionStatus.ProtocolError)
{
var responseText = new StreamReader(ep.Response.GetResponseStream()).ReadToEnd();
Console.WriteLine(responseText);
}
throw ep;
}
}
public string GenerateToken()
{
string client_id = _clientId;
string client_secret = _secretValue;
string tenant = _tenantId;
string requestData =
string.Format("client_id={0}&client_secret={1}" + "&scope=https://graph.microsoft.com/.default&grant_type=client_credentials",
client_id, client_secret);
string tokenUri = string.Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", tenant);
string responseText = _postString(tokenUri, requestData);
OAuthResponseParser parser = new OAuthResponseParser();
parser.Load(responseText);
var vv = parser.AccessToken;
return vv;
}
public void Generatemail()
{
interface_class bb = new interface_class();
IGraphClient client = GraphClient.GetClient(bb, _tenantId);
MapiMessage mm = new MapiMessage();
mm.Subject = "EMAILNET-39318 " + Guid.NewGuid().ToString();
mm.Body = "EMAILNET-39318 REST API v1.0 - Create Message";
mm.SetProperty(KnownPropertyList.DisplayTo, "xxx#outlook.com");
mm.SetProperty(KnownPropertyList.SenderName, "xxx#outlook.com");
mm.SetProperty(KnownPropertyList.SentRepresentingEmailAddress, "xxx#outlook.com");
// Create message in inbox folder
MapiMessage createdMessage = client.CreateMessage(Aspose.Email.Clients.Graph.KnownFolders.Inbox, mm);
}
public void FetchMail()
{
try
{
interface_class bb = new interface_class();
using (IGraphClient client = GraphClient.GetClient(bb, _tenantId))
{
FolderInfoCollection folderInfoCol1 = client.ListFolders();
FolderInfo inbox = null;
foreach (FolderInfo folderInfo in folderInfoCol1)
{
if (folderInfo.DisplayName.Equals("Inbox", StringComparison.InvariantCultureIgnoreCase))
{
inbox = folderInfo;
break;
}
}
MessageInfoCollection messageInfoCol = client.ListMessages(inbox.ItemId);
MessageInfo messageInfo = messageInfoCol[0];
MapiMessage message = client.FetchMessage(messageInfo.ItemId);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Itokenimplementor_class code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aspose.Email.Clients;
using Aspose.Email.Clients.Graph;
namespace Email
{
internal class interface_class : ITokenProvider
{
Graph_API obj = new Graph_API();
DateTime expirationDate = DateTime.Today.AddDays(1);
public void Dispose()
{
throw new NotImplementedException();
}
public OAuthToken GetAccessToken()
{
string token = obj.GenerateToken();
return new OAuthToken(token, expirationDate);
}
public OAuthToken GetAccessToken(bool ignoreExistingToken)
{
throw new NotImplementedException();
}
}
}
https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages This endpoint is used to query inbox messages for a user right? Then who is /me here? And this is the issue.
In your code snippet, I noticed that you set the grant_type=client_credentials so you are using client credential flow. It's correct but pls note that you need to give application api permission. Application api permission is for client credential flow. And this api require Mail.ReadBasic.All, Mail.Read, Mail.ReadWrite permissions.
If you can generate access token successfully, you may decode the token the check if the roles claim contained correct permissions.
When you get a correct token, then pls use Get: /users/{id | userPrincipalName}/mailFolders/inbox/messages instead of /me. If you want to query emails for user1#yourtenant.onmicrosoft.com, then the url can be /users/user1#yourtenant.onmicrosoft.com/mailFolders/inbox/messages.
I also notice that you had GraphClient in your code. So you may also try my code below:
using Azure.Identity;
using Microsoft.Graph;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_client_id";
var clientSecret = "client_secret_for_the_azuread_app";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var messages = await graphClient.Users["user_id/PrincipalName"].Messages
.Request()
.GetAsync();
I am currently trying to make an api call in c# using a MultiPartFormDataContent but I keep
getting the following error:
"Response: {"statusCode":400,"error":"Bad Request","message":""Image file" must be of type object","validation":{"source":"payload","keys":["images"]}}"
This is my Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace Example
{
public class Test
{
public static void Main(string[] args)
{
Task<string> test = testFunction();
Console.WriteLine("Result: " + test.Result);
}
public static async Task<string> testFunction()
{
const string file = "C:\\ExamplePath\\image_1.jpeg";
const string URL = "https://example-api?api-key=example-key";
string boundary = "---8d0f01e6b3b5dafaaadaad";
MultipartFormDataContent multipartContent = new MultipartFormDataContent(boundary);
var streamContent = new StreamContent(File.Open(file, FileMode.Open));
var stringContent = new StringContent("flower");
multipartContent.Add(stringContent, "organs");
multipartContent.Add(streamContent, "images");
try
{
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.PostAsync(URL, multipartContent);
Console.WriteLine("Response: " + await response.Content.ReadAsStringAsync());
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine("IN METHIOD: " + content);
return content;
}
return null;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
}
}
It's obviously a problem with how I am trying to do the api call but I don't know how to do it with an object instead like mentioned the error message.
This link has some good examples and where I actually got my code snippet from below.
Here's a basic example of using MultiFormDataContent:
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StringContent(username), "username");
form.Add(new StringContent(useremail), "email");
form.Add(new StringContent(password), "password");
form.Add(new ByteArrayContent(file_bytes, 0, file_bytes.Length), "profile_pic", "hello1.jpg");
HttpResponseMessage response = await httpClient.PostAsync("PostUrl", form);
response.EnsureSuccessStatusCode();
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;
I hope this helps or points you in the right direction.
I am trying to download string from discord webhook :("https://discordapp.com/api/webhooks/704770710509453432/GdR4absQHKDKjUiNMpw3aIpX2tx-9Z7nmPE2Sn3TUkQDM12zUczaV-m80orh7WGVzvGK")
When I normally open the site with browser string is : {"message": "Unknown Webhook", "code": 10015}
But when I do that with WebClient:
WebClient wc = new WebClient();
string site = "https://discordapp.com/api/webhooks/704770710509453432/GdR4absQHKDKjUiNMpw3aIpX2tx-9Z7nmPE2Sn3TUkQDM12zUczaV-m80orh7WGVzvGK";
string x = wc.DownloadString(site);
It gives an "404 Error". Is there a way to get that {"message": "Unknown Webhook", "code": 10015} string with c#?
A rough guess would be that it's to do with the accept header. Check the documentation for the api, but my browser sent an additional 17 headers along with the request.
The simple answer would be, use HttpClient. It's recommended for new development and also gives the correct response here:
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace discordapi_headers
{
class Program
{
static async Task Main(string[] args)
{
var client = new HttpClient();
var response = await client.GetAsync("https://discordapp.com/api/webhooks/704770710509453432/GdR4absQHKDKjUiNMpw3aIpX2tx-9Z7nmPE2Sn3TUkQDM12zUczaV-m80orh7WGVzvGK");
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
}
However that doesn't help if you can't. Also I'm intrigued now...
Ha! I should have listened to my own advice. For web service related stuff, you can't beat fiddler and postman. It turns out that the api is returning a custom 404 to the browser that has json content.
Unfortunately DownloadString sees the 404 and throws a WebException.
Here's an updated version that works, using HttpClient and WebClient.
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace discordapi_headers
{
class Program
{
static readonly string url = "https://discordapp.com/api/webhooks/704770710509453432/GdR4absQHKDKjUiNMpw3aIpX2tx-9Z7nmPE2Sn3TUkQDM12zUczaV-m80orh7WGVzvGK";
static async Task Main(string[] args)
{
Console.WriteLine(await UseHttpClient(url));
Console.WriteLine(await UseWebClient(url));
}
private static async Task<string> UseHttpClient(string url)
{
var client = new HttpClient();
var response = await client.GetAsync(url);
return await response.Content.ReadAsStringAsync();
}
private static async Task<string> UseWebClient(string url)
{
var client = new WebClient();
try
{
var response = await client.DownloadStringTaskAsync(url);
return response;
}
catch (WebException wex)
{
using (var s = wex.Response.GetResponseStream())
{
var buffer = new byte[wex.Response.ContentLength];
var contentBytes = await s.ReadAsync(buffer, 0, buffer.Length);
var content = Encoding.UTF8.GetString(buffer);
return content;
}
}
}
}
}
I need to retrieve the list of wallets of a Coinbase account. In order to to it, I need to use RestSharp (no third library allowed), using the API private keys.
I've tried to retrieve them but when I run the code, as response I obtain a invalid response, with an error message that says
"The URI prefix is not recognized."
How can I retrieve the list of wallets?
This is my code:
using RestSharp;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace WCoinBase
{
class Program
{
private const string apiKey = "MyPrivateKey";
static void Main(string[] args)
{
RestClient restClient = new RestClient
{
BaseUrl = new Uri("https://api.coinbase.com/v2/")
};
string timestamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
string path = "wallet:accounts:read";
var request = new RestRequest
{
Method = Method.GET,
Resource = path
};
string accessSign = GetAccessSign(timestamp, "GET", path, "");
request.AddHeader("CB-ACCESS-KEY", apiKey);
request.AddHeader("CB-ACCESS-SIGN", accessSign);
request.AddHeader("CB-ACCESS-TIMESTAMP", timestamp);
request.AddHeader("CB-VERSION", "2017-08-07");
request.AddHeader("Accept", "application/json");
var response = restClient.Execute(request);
Console.WriteLine("Status Code: " + response.StatusCode);
}
static private string GetAccessSign(string timestamp, string command, string path, string body)
{
var hmacKey = Encoding.UTF8.GetBytes(apiKey);
string data = timestamp + command + path + body;
using (var signatureStream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
{
var hex = new HMACSHA256(hmacKey).ComputeHash(signatureStream)
.Aggregate(new StringBuilder(), (sb, b) => sb.AppendFormat("{0:x2}", b), sb => sb.ToString());
return hex;
}
}
}
}
The reason you're getting this error is the URL is composed as https://api.coinbase.com/v2/wallet:accounts:read, which isn't a valid URL.
You're setting the scope as the path, which is incorrect.
You should be hitting GET https://api.coinbase.com/v2/accounts
See: https://developers.coinbase.com/api/v2#list-accounts
Path should be "accounts", not wallet:accounts:read.
Documentation on scopes can be found here.