I have an asp.net web API. I have a filter attribute and OnAuthorization I am returning HttpResponseMessage as follows.
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
//Check Request Start-End Period
if (!CheckRequestTime())
{
var response = new HttpResponseMessage
{
StatusCode = (HttpStatusCode) 429,
ReasonPhrase = "Invalid Request Time",
Content = new StringContent("Requests are permitted between " +
WebConfigurationManager.AppSettings["TimeStart"].ToString() +
" AM and " + WebConfigurationManager.AppSettings["TimeEnd"].ToString() +
" PM.")
};
actionContext.Response = response;
}
}
A Client wants me to return ResponseMessageResult which means adding Message property to the response as follows:
{
"Message": "Requests are permitted between 11:00 AM and 22:30 PM."
}
UPDATE
This solved my problem.
Content = new StringContent("{\"Message\":\"Requests are permitted between " +
WebConfigurationManager.AppSettings["TimeStart"].ToString() +
" AM and " + WebConfigurationManager.AppSettings["TimeEnd"].ToString() +
" PM.\"}", System.Text.Encoding.UTF8, "application/json"),
Related
I'm new to working with async and I'm trying to build a Cefsharp application that collects data from an external API, stores it in local variables and then exports these through JavaScript to HTML. It's not a beautiful implementation and I'm sure my code is pretty awful but here goes:
My application performs a tick every 5 seconds, where it executes a HTTP Post request and stores the result in a QuickType (app.quicktype.io) list. This is the tick:
private async void timer1_Tick(object sender, EventArgs e)
{
await chromeBrowser.WaitForInitialLoadAsync();
if (httpPost.ConnectionSuccesful())
{
var devtoolsContext = await chromeBrowser.CreateDevToolsContextAsync();
var postResult = await httpPost.SendPost("robot_info");
try {
var result = Welcome.FromJson(postResult);
foreach (var robot in result.Result.Robots.Select((value, i) => (value, i)))
{
Console.WriteLine(robot.value.Id);
if (robot.value.ChargingStateCode == 9 || robot.value.ChargingStateCode == 12)
await devtoolsContext.EvaluateFunctionAsync("function setBatteryCharge() { var batteryLevel = jQuery('#robot" + robot.i + "Charge'); batteryLevel.css('width', "+ robot.value.StateOfCharge + " + '%'); batteryLevel.text('Charging'); batteryLevel.addClass('high'); batteryLevel.removeClass('medium'); batteryLevel.removeClass('low'); }");
else if (robot.value.StateOfCharge > 75)
await devtoolsContext.EvaluateFunctionAsync("function setBatteryHigh() { var batteryLevel = jQuery('#robot" + robot.i + "Charge'); batteryLevel.css('width', " + robot.value.StateOfCharge + " + '%'); batteryLevel.text(" + robot.value.StateOfCharge + " + '%'); batteryLevel.addClass('high'); batteryLevel.removeClass('medium'); batteryLevel.removeClass('low'); }");
else if (robot.value.StateOfCharge >= 50)
await devtoolsContext.EvaluateFunctionAsync("function setBatteryMedium() { var batteryLevel = jQuery('#robot" + robot.i + "Charge'); batteryLevel.css('width', " + robot.value.StateOfCharge + " + '%'); batteryLevel.text(" + robot.value.StateOfCharge + " + '%'); batteryLevel.addClass('medium'); batteryLevel.removeClass('high'); batteryLevel.removeClass('low'); }");
else
await devtoolsContext.EvaluateFunctionAsync("function setBatteryLow() { var batteryLevel = jQuery('#robot" + robot.i + "Charge'); batteryLevel.css('width', " + robot.value.StateOfCharge + " + '%'); batteryLevel.text(" + robot.value.StateOfCharge + " + '%'); batteryLevel.addClass('low'); batteryLevel.removeClass('high'); batteryLevel.removeClass('medium'); }");
}
}
catch (ArgumentNullException Nex) {
Console.Write("[Error] - " + Nex.Message);
}
catch (Exception ex)
{
Console.WriteLine("[Error] - " + ex.Message);
}
}
else
Console.WriteLine("[Error] - Check connection or access to API server.");
}
I'm currently trying to update the battery level and it successfully does this for the first tick (the JavaScript works as intended and both the css, classes and text is changed). Then it stops working. I've checked that the correct results are coming in from the HTTP Post and that the data is stored properly in the local variables. The problem seems to occur in the foreach. I've tried to read up about async a bit but I can't seem to find the culprit. After the first execution of the code, something seems to be blocking the iteration of the for each. I'm using Cefsharp.Winforms and Cefsharp.Puppeteer.
Any idea on why this is happening? Also thankful for any pointers or tips on how to improve the code.
EDIT: This is the Console Output
[Query] Sending post request to xxx with method 'robot_info'
[Success] - API Post Request was succesful.
PR1#11
PR1#15
[Query] Sending post request to xxx with method 'robot_info'
[Success] - API Post Request was succesful.
PR1#11
[Query] Sending post request to xxx with method 'robot_info'
[Success] - API Post Request was succesful.
PR1#11
The first iteration goes through fine.
EDIT2: This is the timer
public void InitTimer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 5000;
timer1.Start();
}
EDIT3: Method SendPost
public async Task<string> SendPost(string method)
{
HttpClient httpClient = new HttpClient();
string data = new JavaScriptSerializer().Serialize(new
{
jsonrpc = "2.0",
method = method,
id = Guid.NewGuid().ToString()
});
StringContent content = new StringContent(data, System.Text.Encoding.UTF8, "application/json");
try
{
Console.WriteLine("[Query] Sending post request to " + url.ToString() + " with method '" + method + "'");
HttpResponseMessage response = await httpClient.PostAsync(url, content).ConfigureAwait(false);
string result = await response.Content.ReadAsStringAsync();
if (IsValidJson(result))
{
Console.WriteLine("[Success] - API Post Request was succesful.");
return result;
}
else
return null;
} catch (HttpRequestException hre)
{
Console.WriteLine("[Error]: " + hre);
return null;
}
}
EDIT4: Structure of Welcome
public partial class Welcome
{
[JsonProperty("jsonrpc")]
public string Jsonrpc { get; set; }
[JsonProperty("result")]
public Result Result { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
}
public partial class Result
{
[JsonProperty("timestamp")]
public long Timestamp { get; set; }
[JsonProperty("robots")]
public List<Robot> Robots { get; set; }
}
Robots is a list with a bunch of longs and ints.
I am working on Azure Function (Http Trigger), and came across with this task.
I am trying to display the output of method (ListVendors.Run(logger)) into inside variable (responseMessage) so that the values would be carried into Http post.
public static class Function1
{
[FunctionName("HttpTrigger_1111_1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
///Calling from other method starts:
ILogger logger = Bootstrap.Logger("Program");
ListVendors.Run(logger);
///Calling from other method ends:
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
string responseMessage = string.IsNullOrEmpty(name)
? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
: $"Hello, {name}. This HTTP triggered function executed successfully.";
return new OkObjectResult(responseMessage);
}
}
Basically, I am trying to insert the output of:
ListVendors.Run(logger);
Inside "responseMessage".
return new OkObjectResult(responseMessage);
How do I modify the code to do that?
Bottom is code for ListVendors:
public static class ListVendors
{
public static void Run(ILogger logger)
{
OnlineClient client = Bootstrap.Client(logger);
ReadByQuery query = new ReadByQuery()
{
ObjectName = "VENDOR",
PageSize = 2, // Keep the count to just 2 for the example
Fields =
{
"RECORDNO",
"VENDORID",
}
};
logger.LogInformation("Executing query to Intacct API");
Task<OnlineResponse> task = client.Execute(query);
task.Wait();
OnlineResponse response = task.Result;
Result result = response.Results[0];
try
{
dynamic json = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(result.Data));
string jsonString = json.ToString();
logger.LogDebug(
"Query successful - page 1 [ Total count={0}, Data={1} ]",
result.TotalCount,
jsonString
);
Console.WriteLine("Page 1 success! Number of vendor objects found: " + result.TotalCount + ". Number remaining: " + result.NumRemaining);
} catch (NullReferenceException e)
{
logger.LogDebug("No response in Data. {0}", e);
}
LogManager.Flush();
int i = 1;
while (result.NumRemaining > 0 && i <= 3 && !string.IsNullOrEmpty(result.ResultId))
{
i++;
ReadMore more = new ReadMore()
{
ResultId = result.ResultId
};
Task<OnlineResponse> taskMore = client.Execute(more);
taskMore.Wait();
OnlineResponse responseMore = taskMore.Result;
Result resultMore = responseMore.Results[0];
try
{
dynamic resultMoreJson =
JsonConvert.DeserializeObject(JsonConvert.SerializeObject(resultMore.Data));
string resultMoreJsonString = resultMoreJson.ToString();
logger.LogDebug(
"Read More successful - page " + i + " [ Total remaining={0}, Data={1} ]",
resultMore.NumRemaining,
resultMoreJsonString
);
Console.WriteLine("Page " + i + " success! Records remaining: " + resultMore.NumRemaining);
}
catch (NullReferenceException e)
{
logger.LogDebug("No response in Data. {0}", e);
}
finally
{
LogManager.Flush();
}
}
Console.WriteLine("Successfully read " + i + " pages");
}
}
}
I'm trying to change my Restsharp Client to work async instead of sync.
Each of my API-Calls referes to the GetAsync<T> method. When I try now to change the Client to call ExecuteAsync<T> instead of Execute i got this error:
Delegate 'Action, RestRequestAsyncHandle>' does not take 1 Arguments
I'm using RestSharp Version 106.6.10 currently.
Here is my GetAsyncMethod:
public async Task<T> GetAsync<T>(string url, Dictionary<string, object> keyValuePairs = null)
{
try
{
// Check token is expired
DateTime expires = DateTime.Parse(Account.Properties[".expires"]);
if (expires < DateTime.Now)
{
// Get new Token
await GetRefreshTokenAsync();
}
// Get AccessToken
string token = Account.Properties["access_token"];
if (string.IsNullOrEmpty(token))
throw new NullReferenceException("AccessToken is null or empty!");
// Create client
var client = new RestClient()
{
Timeout = 3000000
};
//Create Request
var request = new RestRequest(url, Method.GET);
request.RequestFormat = DataFormat.Json;
request.AddHeader("Authorization", "Bearer " + token);
// Add Parameter when necessary
if (keyValuePairs != null)
{
foreach (var pair in keyValuePairs)
{
request.AddParameter(pair.Key, pair.Value);
}
}
// Call
var result = default(T);
var asyncHandle = client.ExecuteAsync<T>(request, restResponse =>
{
// check respone
if (restResponse.ResponseStatus == ResponseStatus.Completed)
{
result = restResponse.Data;
}
//else
// throw new Exception("Call stopped with Status: " + response.StatusCode +
// " Description: " + response.StatusDescription);
});
return result;
}
catch (Exception ex)
{
Crashes.TrackError(ex);
return default(T);
}
}
Here one of the calling Methods:
public async Task<List<UcAudit>> GetAuditByHierarchyID(int hierarchyID)
{
string url = AuthSettings.ApiUrl + "/ApiMethod/" + hierarchyID;
List<UcAudit> auditList = await GetAsync<List<UcAudit>>(url);
return auditList;
}
When I Change the T in ExecuteAsync<T> in one of my classes the error is gone. How can I change the method to work async with <T>???
With the info from Lasse Vågsæther Karlsen I found the solution.
This is the start:
var asyncHandle = client.ExecuteAsync<T>(request, restResponse =>
{
// check respone
if (restResponse.ResponseStatus == ResponseStatus.Completed)
{
result = restResponse.Data;
}
//else
// throw new Exception("Call stopped with Status: " + response.StatusCode +
// " Description: " + response.StatusDescription);
});
Worked for me :
client.ExecuteAsync<T>(request, (response, asyncHandle )=>
{
//check respone
if (response.StatusCode == HttpStatusCode.OK)
{
result = response.Data;
}
else
throw new Exception("Call stopped with Status: " + response.StatusCode +
" Description: " + response.StatusDescription);
});
Thank you!
How to send parameter in REST api in xamarin.forms ?
I have created REST API Project in xamarin using PCL.
When I call Simple REST api using Below code in Xamarin.forms (Portable Class Library) then I have Successfully receive json Response.
using (var cl = new HttpClient())
{
var result = await cl.GetStringAsync("http://192.168.1.100/apps/jara/web/api/user/test");
jsonResponseClass des = JsonConvert.DeserializeObject<jsonResponseClass>(result);
lbl1.Text = des.code + " " + des.status + " " + des.message;
}
public class jsonResponseClass
{
public string code { get; set; }
public string status { get; set; }
public string message { get; set; }
}
Using above code I got a response
{
code: 200,
status: "ok",
message: "hello"
}
REST API response type is JSON and type is POST
Now, I want to call below Login Api using paramater.
http://192.168.1.100/apps/jara/web/api/user/login
Paramater : email_id and Password
this api success response type is....
{
code: 200,
status: "Success",
User: {
userid: 126,
token: "d154s4d54s654df5s4df56s4df564s5df4",
email: "shahbuddin#gmail.com",
mobile_number: "9898989898"
},
message: "Successfully logged in"
}
What can i do ?
Finally i can do this using below code....
using (var cl = new HttpClient())
{
var formcontent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string,string>("email_id","shahbuddin#peerbits.com"),
new KeyValuePair<string, string>("password","shah")
});
var request = await cl.PostAsync("http://192.168.1.100/apps/jara/web/api/user/login", formcontent);
request.EnsureSuccessStatusCode();
var response = await request.Content.ReadAsStringAsync();
jsonResponselogin res = JsonConvert.DeserializeObject<jsonResponselogin>(response);
lbl1.Text = res.code + " " + res.status + " " + res.message;
}
This code helpful for Calling REST API with Parameter
Thank you...
In my application i want users to be able to login with facebook and twitter.
For facebook i see there is a procedure ready for that ParseFacebookUtils but there isn't anything like that for Twitter so im making my own.
I have create an implementation for logging in with twitter:
void LoginToTwitter ()
{
var auth = new OAuth1Authenticator(
"<authkey>",
"<authsecret>",
new Uri("https://api.twitter.com/oauth/request_token"),
new Uri("https://api.twitter.com/oauth/authorize"),
new Uri("https://api.twitter.com/oauth/access_token"),
new Uri("http://twitter.com/"));
auth.Completed += GetTwitterData;
var ui = auth.GetUI(Activity);
StartActivity(ui);
}
async public void GetTwitterData( object sender, AuthenticatorCompletedEventArgs e )
{
var request = new OAuth1Request(
"GET",
new Uri("https://api.twitter.com/1.1/account/verify_credentials.json "),
null,
e.Account);
await request.GetResponseAsync().ContinueWith(t =>
{
var res = t.Result;
var resString = res.GetResponseText();
Console.WriteLine("Result Text: " + resString);
var jo = Newtonsoft.Json.Linq.JObject.Parse(resString);
var imageUrl = new Java.Net.URL((string)jo["profile_image_url"]);
var twitterId = jo["id"];
var accessToken = e.Account.Properties["access_token"].ToString();
var expiresIn = Convert.ToDouble(e.Account.Properties["expires_in"]);
var expiryDate = DateTime.Now + TimeSpan.FromSeconds( expiresIn );
var userRealName = e.Account.Properties["screen_name"];
}, UIScheduler);
}
And now the only thing left is to associate there data With a new user or if the user exist to logg him in.
I see ParseFacebookUtils creates a randomly username for each user. In order for me to do something like that i must first check if the random generated username doesn't already exist, is it a good idea to use twitter username for that?
Also facebook stores something called authData of type authData with content like this:
{"facebook": {"access_token":"some_token","expiration_date":"some_date","id":"some_id"}}
How i can create something like that for twitter? i have already generate the required fields
I have successfully Login with twitter on Xamarin.Android with Parse.com
Here is how i manage to do it in case is useful to someone else, you will need components Xamarin.auth and RestSharp:
void LoginToTwitter ()
{
var auth = new OAuth1Authenticator(
"some_key",
"some_key",
new Uri("https://api.twitter.com/oauth/request_token"),
new Uri("https://api.twitter.com/oauth/authorize"),
new Uri("https://api.twitter.com/oauth/access_token"),
new Uri("https://mobile.twitter.com/"));
//save the account data in the authorization completed even handler
auth.Completed += GetTwitterData;
var ui = auth.GetUI(Activity);
StartActivity(ui);
}
public async void GetTwitterData( object sender, AuthenticatorCompletedEventArgs e )
{
//use the account object and make the desired API call
if (e.IsAuthenticated)
Console.WriteLine("Logged in");
var request = new OAuth1Request(
"GET",
new Uri("https://api.twitter.com/1.1/account/verify_credentials.json"),
null,
e.Account, true);
await request.GetResponseAsync().ContinueWith(t =>
{
if (!t.IsFaulted && !t.IsCanceled){
var res = t.Result;
var resString = res.GetResponseText();
//Console.WriteLine("Result Text: " + resString);
var jo = Newtonsoft.Json.Linq.JObject.Parse(resString);
imageUrl = new Java.Net.URL((string)jo["profile_image_url"]);
var twitterId = jo["id"];
}
}, UIScheduler);
var userID = e.Account.Properties["user_id"];
var name = e.Account.Properties["screen_name"];
var oauth_consumer_key = e.Account.Properties["oauth_consumer_key"];
var oauth_consumer_secret = e.Account.Properties["oauth_consumer_secret"];
var oauth_token = e.Account.Properties["oauth_token"];
var oauth_token_secret = e.Account.Properties["oauth_token_secret"];
var authData = new Dictionary<string,string>();
authData.Add("user_id",userID.ToString());
authData.Add("screen_name",name.ToString());
authData.Add("oauth_consumer_key",oauth_consumer_key.ToString());
authData.Add("oauth_consumer_secret",oauth_consumer_secret.ToString());
authData.Add("oauth_token",oauth_token.ToString());
authData.Add("oauth_token_secret",oauth_token_secret.ToString());
await ParseLoginOrCreate(authData);
}
public async Task<ParseUser> ParseLoginOrCreate(Dictionary<string,string> authInfo)
{
var rest = new RestSharp.RestClient ("https://api.parse.com");
var req = new RestSharp.RestRequest ("1/users/", RestSharp.Method.POST);
req.AddHeader ("X-Parse-Application-Id", "some_key");
req.AddHeader ("X-Parse-REST-API-Key", "some_key");
req.AddHeader ("Content-Type", "application/json");
var payload = "{ \"authData\": { \"twitter\": { ";
payload += "\"id\": \"" + authInfo["user_id"] + "\", ";
payload += "\"screen_name\": \"" + authInfo["screen_name"] + "\", ";
payload += "\"consumer_key\": \"" + authInfo["oauth_consumer_key"] + "\", ";
payload += "\"consumer_secret\": \"" + authInfo["oauth_consumer_secret"] + "\", ";
payload += "\"auth_token\": \"" + authInfo["oauth_token"] + "\", ";
payload += "\"auth_token_secret\": \"" + authInfo["oauth_token_secret"] + "\" ";
payload += "} } }";
req.AddParameter("application/json", payload, RestSharp.ParameterType.RequestBody);
RestSharp.IRestResponse res = null;
var result = await Task<JContainer>.Run(()=>{
res = rest.Execute(req);
var content = res.Content;
return JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JContainer>(content);
});
var sessionToken = (String)result["sessionToken"];
var objectId = (String)result["objectId"];
if (res.StatusCode == System.Net.HttpStatusCode.Created)
{
req = new RestSharp.RestRequest ("1/users/" + objectId, RestSharp.Method.PUT);
req.AddHeader ("X-Parse-Application-Id", "some_key");
req.AddHeader ("X-Parse-REST-API-Key", "some_key");
req.AddHeader ("X-Parse-Session-Token", sessionToken);
req.AddHeader ("Content-Type", "application/json");
req.AddParameter("application/json", "{ \"username\": \"" + authInfo["screen_name"] + "\" }", RestSharp.ParameterType.RequestBody);
result = await Task<JContainer>.Run(() => {
res= rest.Execute(req);
var content = res.Content;
return JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JContainer>(content);
});
}
await ParseUser.BecomeAsync (sessionToken);
return ParseUser.CurrentUser;
}