Unity app not responding and get "request time out" when call to WebAPI - api

I'm having a Unity app call to a Like() method in DLL, which connect to a WebAPI to do the job. However, when I debug the application and code run to
string liked = SocialConnector.LikePost(token, postID);
It got stuck there, unity became not responding and after work normal again, the debug show Request time out.
Below are my detail code in DLL
public static String LikePost(String token, String postID)
{
HttpCommon common = new HttpCommon();
string url = Constant.ApiURL + Constant.API_LINK_POST_LIKE_UNLIKE + "?postID=" + postID;
String result = common.HttpPost<String>(url, token);
return result;
}
Code in HTTPCommon
public T HttpPost<T>(String url, String token)
{
var request = (HttpWebRequest)WebRequest.Create(url);
//var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
//request.ContentLength = data.Length;
request.Headers["Authorization"] = "Bearer " + token;
var stream = request.GetRequestStream();
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
try
{
var responseData = JsonConvert.DeserializeObject<T>(responseString);
return responseData;
}
catch (Exception e)
{
throw new Exception(responseString);
}
}
Error log:
WebException: The request timed out
System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult)
System.Net.HttpWebRequest.GetResponse ()
GSEP_DLL.Connectors.HttpCommon.HttpPost[String] (System.String url, System.String token)
GSEP_DLL.Connectors.SocialConnector.LikePost (System.String token, System.String postID)
Like.onClick () (at Assets/Scripts/Like.cs:39)
UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:110)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:574)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:716)
UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:Update()
Update: Problem solved. The WebAPI return type of bool but my DLL forced to return String.

Problem solved. The WebAPI return type of bool but my DLL forced to return String.

Related

blazor wasm using Cryptography.Algorithms Error

Unhandled exception rendering component: System.Security.Cryptography.Algorithms is not supported on this platform.
System.PlatformNotSupportedException: System.Security.Cryptography.Algorithms is not supported on this platform.
at System.Security.Cryptography.Aes.Create()
at AutoTradingWebAppV2.Helper.Crypto.Encryptstring(String text, String keyString) in D:\Web\AutoTradingApp-BWASM\AutoTradingWebAppV2\Helper\Crypto.cs:line 12
at AutoTradingWebAppV2.Handler.CustomUpbitAuthHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in D:\Web\AutoTradingApp-BWASM\AutoTradingWebAppV2\Handler\CustomUpbitAuthHandler.cs:line 31
at System.Net.Http.DelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.<>n__0(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__13`1[[System.Collections.Generic.IEnumerable`1[[DTOs.AccountDTO, DTOs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
at Services.UpbitService.GetAccounts() in D:\Web\AutoTradingApp-BWASM\Services\UpbitService.cs:line 31
at AppViewModels.UpbitTradingViewModel.GetAccounts() in D:\Web\AutoTradingApp-BWASM\AppViewModels\UpbitTradingViewModel.cs:line 156
at AutoTradingWebAppV2.Pages.TradingInfoBoard.TryConnectToWebsocket() in D:\Web\AutoTradingApp-BWASM\AutoTradingWebAppV2\Pages\TradingInfoBoard.razor.cs:line 48
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/5.0/cryptography-apis-not-supported-on-blazor-webassembly
then how to create JWT at blazor ? or use AES?
how to fix it or when they update blazor?
var jwtToken = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA256Algorithm())
.WithSecret(SecretKey)
.AddClaim("access_key",AccessKey)
.AddClaim("nonce", Guid.NewGuid().ToString())
.Encode();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
I Added this code to httpclient handler, but can not use this code on blazor...
+
here is the open API sampleCode. I have to create JWT Token at Client and send request to api
C# CODE.
public class OpenAPISample {
public static void Main() {
var payload = new JwtPayload
{
{ "access_key", "Access Key" },
{ "nonce", Guid.NewGuid().ToString() },
{ "query_hash", queryHash },
{ "query_hash_alg", "SHA512" }
};
byte[] keyBytes = Encoding.Default.GetBytes("Secret Key");
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyBytes);
var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, "HS256");
var header = new JwtHeader(credentials);
var secToken = new JwtSecurityToken(header, payload);
var jwtToken = new JwtSecurityTokenHandler().WriteToken(secToken);
var authorizationToken = "Bearer " + jwtToken;
}
}
JAVA Example CODE (there is no C# CODE in web site)
public static void main(String[] args) {
String accessKey = System.getenv("OPEN_API_ACCESS_KEY");
String secretKey = System.getenv("OPEN_API_SECRET_KEY");
String serverUrl = System.getenv("OPEN_API_SERVER_URL");
Algorithm algorithm = Algorithm.HMAC256(secretKey);
String jwtToken = JWT.create()
.withClaim("access_key", accessKey)
.withClaim("nonce", UUID.randomUUID().toString())
.sign(algorithm);
String authenticationToken = "Bearer " + jwtToken;
try {
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(serverUrl + "/v1/accounts");
request.setHeader("Content-Type", "application/json");
request.addHeader("Authorization", authenticationToken);
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity, "UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
}
how to create JWT at blazor ?
A JWT is created on the Server. And consumed by a Client app.
The APIs are unsupported for technical reasons but you shouldn't want to use them on a Client. Your client is not able to hide any credentials, it would only give false security.
That holds for AES as well. You can't hide the key.
they only give me accesskey and secret key and ask me make jwt
You should do this on your own Server. Your SPA client calls your Server that calls the Open API server.
Make sure the secret key never ends up in the SPA client.

Azure web api Unauthorized 401

I have some code that used to call Azure Scheduler to get a token, then using that token, make restful calls. Works a treat.
So i decided to adopt the code into a new app but this time call my own web api hosted on azure. The API is registered in Active directory I have created a secret key etc. When i initiliaze my static httpclient it fetches a token succesfully.
But when i make a call to the API using the token for auth, the response is a 401 "unauthorized", below is the code.
public static class SchedulerHttpClient
{
const string SPNPayload = "resource={0}&client_id={1}&grant_type=client_credentials&client_secret={2}";
private static Lazy<Task<HttpClient>> _Client = new Lazy<Task<HttpClient>>(async () =>
{
string baseAddress = ConfigurationManager.AppSettings["BaseAddress"];
var client = new HttpClient();
client.BaseAddress = new Uri(baseAddress);
await MainAsync(client).ConfigureAwait(false);
return client;
});
public static Task<HttpClient> ClientTask => _Client.Value;
private static async Task MainAsync(HttpClient client)
{
string tenantId = ConfigurationManager.AppSettings["AzureTenantId"];
string clientId = ConfigurationManager.AppSettings["AzureClientId"];
string clientSecret = ConfigurationManager.AppSettings["AzureClientSecret"];
string token = await AcquireTokenBySPN(client, tenantId, clientId, clientSecret).ConfigureAwait(false);
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); //TODO ssmith: const or localization
}
private static async Task<string> AcquireTokenBySPN(HttpClient client, string tenantId, string clientId, string clientSecret)
{
var payload = String.Format(SPNPayload,
WebUtility.UrlEncode(ConfigurationManager.AppSettings["ARMResource"]),
WebUtility.UrlEncode(clientId),
WebUtility.UrlEncode(clientSecret));
var body = await HttpPost(client, tenantId, payload).ConfigureAwait(false);
return body.access_token;
}
private static async Task<dynamic> HttpPost(HttpClient client, string tenantId, string payload)
{
var address = String.Format(ConfigurationManager.AppSettings["TokenEndpoint"], tenantId);
var content = new StringContent(payload, Encoding.UTF8, "application/x-www-form-urlencoded");
using (var response = await client.PostAsync(address, content).ConfigureAwait(false))
{
if (!response.IsSuccessStatusCode)
{
Console.WriteLine("Status: {0}", response.StatusCode);
Console.WriteLine("Content: {0}", await response.Content.ReadAsStringAsync().ConfigureAwait(false));
}//TODO: start removing tests
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsAsync<dynamic>().ConfigureAwait(false);
}
}
}
The above code is the class that creates a httpclient and gets its authorization.
public virtual async Task<T> GetAsync(string apiURL)
{
try
{
_client = await SchedulerHttpClient.ClientTask;
var response = await _client.GetAsync(apiURL);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsAsync<T>().ConfigureAwait(false);
return responseContent;
}
catch (Exception e)
{
return default(T);
}
}
The above code is a quick lift of my old code simply to test if i can get any results. but as stated it returns a 401.
My question is, is my old code to get authorization incorrect?
<add key="ARMResource" value="https://management.core.windows.net/" />
<add key="TokenEndpoint" value="https://login.windows.net/{0}/oauth2/token" />
<add key="BaseAddress" value="https://mysite.azurewebsites.net" />
As suspected, This particular issue was cause by the incorrect "ARMresource" in the case of a web api it required me to change it to the client id.
Source of answer
Seems my issue was the same, however i suspect i may be able to omit the resource entirely from my SPNPayload string.

HttpWebRequest.GetResponse() times out after some time

I have application that sends requests to same REST server constantly and after some time HttpWebRequest.GetResponse() starts timing out i've noticed that whenever i increase System.Net.ServicePointManager.DefaultConnectionLimit it takes it longer to start timing out again, which should mean that those requests are staying active, but as far as i know i'm closing all of them.
Here is method i'm using for my requests.
Current DefaultConnectionLimit is set to 10.
Also there is 1 request that is going on throughout most of applications lifetime.
I'm using .NET Compact framework and REST server is written using WCF (.NET 4.5)
public static string HttpRequest(string request, string method, string contentType, int timeout)
{
string result = "";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(PodesavanjaManager.TrenutnaPodesavanja.PutanjaServisa + "/" + request);
req.Method = method;
req.ContentType = contentType;
req.Timeout = timeout;
req.KeepAlive = false;
if(method == "POST")
req.ContentLength = 0;
using(Stream stream = req.GetResponse().GetResponseStream())
{
using(StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
reader.Close();
}
stream.Close();
stream.Flush();
}
return result;
}
EDIT new version of method:
public static string HttpRequest(string request, string method, string contentType, int timeout)
{
string result = "";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(PodesavanjaManager.TrenutnaPodesavanja.PutanjaServisa + "/" + request);
req.Method = method;
req.ContentType = contentType;
req.Timeout = timeout;
req.KeepAlive = false;
if(method == "POST")
req.ContentLength = 0;
using (HttpWebResponse resp =(HttpWebResponse) req.GetResponse())
{
using (Stream stream = resp.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
reader.Close();
}
}
}
GC.Collect();
return result;
}
I agree it does behave like the connection is still in use by a resource that has not been closed. The documentation for HttpWebResponse mentions:
You must call either the Stream.Close or the HttpWebResponse.Close method to close the response and release the connection for reuse. It is not necessary to call both Stream.Close and HttpWebResponse.Close, but doing so does not cause an error.
I was hoping for a more straightforward description like "you must either close the stream returned by GetResponseStream or call the HttpWebResponse.Close method - but if my interpretation of the documentation is correct, your code is fine.
We use HttpWebRequest in our CE applications as well, and always put the response in a using block as well - you could try this:
using(HttpWebResponse response = (HttpWebResponse)req.GetResponse())
using(Stream stream = response.GetResponseStream())
{
// ...
}
Also have you checked your code for other HttpWebRequest usages, just to be sure?

Saving data in windows phone received from WCF/web service .

Saving data in windows phone received from WCF/web service .
The response may be received after sometime so how to handle this situation.
Saving data is no problem but How to handel if data is received late
You can use this code (show the code from my project):
public void sendPost(string postData, Action<MyResponse, Exception> callback, CreateResponse creater)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(UrlRequest);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Accept = "application/json";
webRequest.AllowAutoRedirect = true;
webRequest.BeginGetRequestStream(new AsyncCallback(getRequestStreamCallback), new Request()
{
HttpRequest = webRequest,
PostData = postData,
Url = UrlRequest,
CallBack = callback,
Creater = creater
});
}
private void getRequestStreamCallback(IAsyncResult asynchronousResult)
{
var request = (Request)asynchronousResult.AsyncState;
// End the stream request operation
Stream postStream = request.HttpRequest.EndGetRequestStream(asynchronousResult);
byte[] byteArray = Encoding.UTF8.GetBytes(request.PostData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
request.HttpRequest.BeginGetResponse(new AsyncCallback(getResponseCallback), request);
}
private void getResponseCallback(IAsyncResult asynchronousResult)
{
var request = (Request)asynchronousResult.AsyncState;
try
{
HttpWebResponse response;
// End the get response operation
response = (HttpWebResponse)request.HttpRequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
var myResponse = streamReader.ReadToEnd();
streamResponse.Close();
streamReader.Close();
response.Close();
MyResponse response_obj = request.Creater.CreateResponseObj();
using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(myResponse)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(response_obj.GetType());
response_obj = (GYResponse)serializer.ReadObject(stream);
if (request.CallBack != null)
{
request.CallBack.Invoke(response_obj, null);
}
}
}
catch (WebException e)
{
if (request.CallBack != null)
{
request.CallBack.Invoke(null, e);
}
}
}
public void getInfo(string uid, Action<MyResponse, Exception> callback)
{
CreateResponse creater = new CreateResponseGetInfo();
string model = "User";
string method = "getInfo";
Params parametrs = new Params();
parametrs.Uid = uid;
//create yor request
string request = getRequestString(model, method, parametrs, Atoken);
sendPost(request, callback, creater);
}
So, you call method, which send request to web service postRequester.getInfo(uid, ResponseHandler) and use delegate for processing result.
private void ResponseHandler(MyResponse result, Exception error)
{
if (error != null)
{
string err = error.Message;
return;
}
else
{
var infoResponse = result as ResponseGetInfo;
if (infoResponse != null)
{
//result processing..
}
}
}
All the web requests you make in a Windows Phone app are Asynchronous. That means, you make a web request from your app and attach a handler to handle the response when it comes. In the response handler, you will have to take care of the response and do whatever you want with it.
Check this link Using WebClient and HttpWebRequest

Why return 500 error while calling another controller using WebClient?

I'm testing example on this link: http://msdn.microsoft.com/en-us/vs11trainingcourse_aspnetmvc4_topic5#_Toc319061802 but I have 500 error calling another controller using WebClient.
When I access to "http://localhost:2323/photo/gallery directly is running, but I'm trying from action using WebClient it return 500 error? Why?"
public ActionResult Index()
{
WebClient client = new WebClient();
var response = client.DownloadString(Url.Action("gallery", "photo", null, Request.Url.Scheme));
var jss = new JavaScriptSerializer();
var result = jss.Deserialize<List<Photo>>(response);
return View(result);
}
500 error created by below exception:
[ArgumentNullException: Value cannot be null.
Parameter name: input]
System.Text.RegularExpressions.Regex.Match(String input) +6411438
Microsoft.VisualStudio.Web.Runtime.Tracing.UserAgentUtilities.GetEurekaVersion(String userAgent) +79
Microsoft.VisualStudio.Web.Runtime.Tracing.UserAgentUtilities.IsRequestFromEureka(String userAgent) +36
Microsoft.VisualStudio.Web.Runtime.Tracing.SelectionMappingExecutionListenerModule.OnBeginRequest(Object sender, EventArgs e) +181
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69
It's hard to tell. Maybe the controller action that you are calling requires authorization? Or uses session? When you send your WebClient request it doesn't delegate any of the client cookies that were sent by the client to the Index action.
Here's how you can debug your code and see the exact response returned by the server:
WebClient client = new WebClient();
try
{
var response = client.DownloadString(Url.Action("gallery", "photo", null, Request.Url.Scheme));
}
catch (WebException ex)
{
using (var reader = new StreamReader(ex.Response.GetResponseStream()))
{
string responseText = reader.ReadToEnd(); // <-- Look here to get more details about the error
}
}
And if it turns out that the problem is related to the ASP.NET Session that your target controller action depends upon, here's how you could delegate the client cookies with the request:
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.Cookie] = Request.Headers["Cookie"];
error occurred because of the User-Agent Header
Resolution is:
public ActionResult Index()
{
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.UserAgent] = Request.Headers["User-Agent"];
var response = client.DownloadString(Url.Action("gallery", "photo", null, Request.Url.Scheme));
var jss = new JavaScriptSerializer();
var result = jss.Deserialize<List<Photo>>(response);
return View(result);
}