Preface:
This is a part of my personal project of building a control GUI for several communication devices - using WinForms unfortunately.
The part of code running into trouble is rested inside the Constructor of a Form.
Additional NuGet packages installed are: Newtonsoft.Json, RestSharp, SpecFlow and SpecFlow.Assist.Dynamic.
LoginForm and SeatsInfo are two basic classes created only to store and organize my data, they have no additional coding besides properties declartions.
Execution code:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CONTROL_UI
{
public partial class RunningConfig : Form
{
public RunningConfig()
{
InitializeComponent();
var client = new RestClient("CLIENT_URL");
var loginRequest = new RestRequest("api/login", Method.POST);
loginRequest.RequestFormat = DataFormat.Json;
loginRequest.AddHeader("Content-type", "application/json");
loginRequest.AddJsonBody(new LoginForm() { username = "admin", password = "", #override = true });
var loginRespone = client.Execute(loginRequest);
JObject sessionInfo = JObject.Parse(loginRespone.Content);
var sessionID = sessionInfo["sid"];
var seatAvailRequest = new RestRequest("api/seats", Method.GET);
seatAvailRequest.AddHeader("sid", sessionID.ToString());
seatAvailRequest.AddHeader("Cookie", "sid = " + sessionID.ToString());
var seatResponse = client.Execute(seatAvailRequest);
List<SeatsInfo> seatsInfo = JsonConvert.DeserializeObject<List<SeatsInfo>>(seatResponse.Content);
//Further Implementation
}
}
}
Expected packet view in WireShark:
Actual packet view in WireShark:
sids are generated each time I successfully authorized to connect to the device, so they obviously differ.
The screenshot of my expected view is taken from the exact same block of codes in a plain console app. Everything works fine there. All the NuGet packages installed on the two programmes are of the same version, I even tried running them side-by-side but it did not help.
Debugging screenshots showed that the Parameters did, in fact, contain the Cookie header:
The header just did not go through for some reason. Would love to hear some thoughts in regards to this issue, many thanks in advance!
Current solution, just add another AddCookie() method:
seatAvailRequest.AddHeader("sid", sessionID.ToString());
seatAvailRequest.AddHeader("Cookie","sid = " + sessionID.ToString());
seatAvailRequest.AddCookie("sid", sessionID.ToString());
This somehow does not work with just AddCookie() or AddHeader(), so for now they are both going in. Hope this helps someone, and thank yall for reading!
So, in recap I was lacking the Cookie Header in the API call thus making the call being unsuccessful (the device did not authorized it).
After messing around with the AddCookie() method, particularly:
seatAvailRequest.AddCookie("sid", sessionID.ToString());
The device gave me a different error - 404 Not Found, before was 401 Unauthorized:
Finally my dumb mind resorted using both the AddCookie() along with AddHeader() and voilà:
It works! Only after 5 hours of painful debugging and mind-numbing searches. Although the new packet is a bit larger, but I do not have to worry about that for now, or in the future realistically speaking.
Thanks you all for just following along, still open for suggestions and improvements!
Related
Hi all hoping someone can help me with this,
I'm trying to build my Unity project in WebGL but I've come to the realisation that using System.Net/System.Net.Sockets isn't supported and I need some alternative functions that do the same things (My Knowledge is pretty lacking on the subject of handling async calls in Unity but got the Google sample code working to my delight)
Now in my Windows build the code is (reduced as much as I could but here is the link to the google sample which has the full code (excluding minor changes to make it work in Unity -> Google Oauth example
using System.Net;
using System.Net.Sockets;
public void btnclickWindows(){
button_Click_Windows("hello");
}
public async void button_Click_Windows(object sender){
string redirectURI = string.Format("http://localhost:8887/", IPAddress.Loopback, GetRandomUnusedPort());
var http = new HttpListener();
http.Prefixes.Add(redirectURI);
http.Start();
string authorizationRequest = string.Format("{0}?access_type=offline&prompt=consent&response_type=code&scope=openid%20profile%20email&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}",
authorizationEndpoint,
System.Uri.EscapeDataString(redirectURI),
clientID,
state,
code_challenge,
code_challenge_method
);
// Opens request in the browser.
System.Diagnostics.Process.Start(authorizationRequest);
var context = await http.GetContextAsync();
var response = context.Response;
}
So this works perfect in Windows etc but not WebGL, the main functions that aren't supported are
IPAddress.Loopback var http = new HttpListener(); System.Diagnostics.Process.Start(authorizationRequest); var context = await http.GetContextAsync();
Does anyone know of a way or library that I can use within WebGL that runs each one of these functions?
Me and a friend had an idea to build some kind of web-scraping software and eventually we settled for a mobile app (Android). The main idea is: We provide the user with a list of music festivals, the user selects one and when he does, a list of the current confirmed artists for that festival is displayed (we want it to display an up-to-date list). The list is retrieved via python scripts (note that the goal is not deployment or profit (at least right now), thus this very summarized explanation).
My question is, how would I go about integrating the python scripts with the mobile application? At this moment I know you can call them with C# but I'm not sure if that would work on a mobile environment. Plus I saw someone saying one should host the scripts on a web server and then execute them via API calls but the person didn't expand and I'm not sure how to do that.
Any insight on the matter or useful references would be helpful.
Thanks!
You can do it in C# using HttpClient and HtmlAgilityPack;
You would need:
using System.Net.Http;
using HtmlAgilityPack;
Make methods like this:
public static HtmlNode GetNodeById(HttpClient client, string url, string divId)
{
string pageHtml = "";
using (HttpResponseMessage response = client.GetAsync(url).Result)
{
using (HttpContent content = response.Content)
{
pageHtml = content.ReadAsStringAsync().Result;
}
}
var doc = new HtmlDocument();
doc.LoadHtml(pageHtml);
HtmlNode node = doc.GetElementbyId(divId);
return node;
}
And call like this (where "musiciansDiv" is the div that contains the info your app needs):
static HttpClient client = new HttpClient();
var musicians = GetNodeById(client, "http://gigs.example.com", "musiciansDiv");
I have developed an Android game which successfully gets a ServerAuthCode from the Google Play API. I want to send this ServerAuthCode to my custom game server, which I have wrote in C# and validate it to authenticate the player.
There is a documentation by Google for Java available (part "Exchange the server auth code for an access token on the server"): https://developers.google.com/games/services/android/offline-access
Unfortunately I can not adapt this for C#.
I have the client_secret.json which seems to include all API authentication data and I have the ServerAuthCode (which seems to be a token).
There is also a NuGet package available for C#, but it does not contain all the classes from the above documentation: https://www.nuget.org/packages/Google.Apis.AndroidPublisher.v3/
How can I validate the token? I would also welcome a simple Postman example.
I figured it out by trial and error. One important thing to note is that the Server Auth Code expires fast. In case you are debugging and copy & pasting by hand, it may happen that until you run the code, the Server Auth Code is already expired. In this case, Google API returns "invalid_grant" as error, which for me was misleading.
In my example solution you need to have a file "client_secret.json" in your project, which is copied on build to the output directory (file properties -> "Build Action" = "Content", "Copy to Output Directory" = "Copy always").
You get your client_secret.json file from the Google API console (https://console.developers.google.com/apis/credentials?project=, click on the download icon on the right side of your project, under "OAuth 2.0-Client-IDs").
Important: The redirect url must match the redirect url configured in your project. For me, it was just empty, so just use an empty string.
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Requests;
using System;
using System.IO;
using System.Reflection;
using System.Text;
namespace GoogleApiTest
{
// Source: https://developers.google.com/identity/sign-in/android/offline-access
class Program
{
static void Main(string[] args)
{
var authCode = "YOUR_FRESH_SERVER_AUTH_CODE";
var path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), #"client_secret.json");
var config = File.ReadAllText(path, Encoding.UTF8);
GoogleClientSecrets clientSecrets = GoogleClientSecrets.Load(new FileStream(path, FileMode.Open));
var request = new AuthorizationCodeTokenRequest()
{
ClientId = clientSecrets.Secrets.ClientId,
ClientSecret = clientSecrets.Secrets.ClientSecret,
RedirectUri = "",
Code = authCode,
GrantType = "authorization_code"
};
var tokenResponse = request.ExecuteAsync(new System.Net.Http.HttpClient(), "https://www.googleapis.com/oauth2/v4/token", new System.Threading.CancellationToken(), Google.Apis.Util.SystemClock.Default).GetAwaiter().GetResult();
Console.ReadLine();
}
}
}
I`m relatively new to programming and I´m completely new to Stack overflow, so please be patient with me! Currently I work on a ASP.NET MVC project including the Ebay finding API.
The goal i want to accomplish is to create a Website on which you can search for different articles on Ebay and being able to use certain filters using the Ebay finding API. This is a training projekt for me, as the C# part of the whole thing is a good practice in my opinion. Unfortunately I´m stuck with the whole API connection to ebay part and havent done any C# programming myself.
Frankly i have no idea what im doing and I hope some of you may have an idea or some tips for me. I know I might be vague and I´m sorry, but i´m just at the beginning of programming.
What have i done so far?
I already registered on the ebay developers program and I already have my App ID, the Dev IDm the Cert ID and a Token.
Important: I currently only work with the sandbox!
I found a piece of code online which I´m using, but now im stuck. Obisously i filled in the IDs and the token but deleted it for this post. In the "Index" class at the end of my piece of code I entered the ID of a random Ebay article for testing purposes. When i debug I get this Exception:
"eBay.Service.Core.Sdk.ApiException: 'This item cannot be accessed because the listing has been deleted, is a Half.com listing, or you are not the seller."
I would really appreciate if someone can show me how to do it correctly or push me in the right direction. I have to admit that i find the whole Ebay API documentation etc. to be very confusing and I dind´t find any advice on how to start. I take any advice you guys can give me!
Here is the code I found and used so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Windows.Forms;
using System.Resources;
using eBay.Service.Call;
using eBay.Service.Core.Sdk;
using eBay.Service.Core.Soap;
namespace Ebay_API_Neu.Controllers
{
public class HomeController : Controller
{
public GetItemCall getItemDataFromEbay(String itemId)
{
ApiContext oContext = new ApiContext();
oContext.ApiCredential.ApiAccount.Developer = "//dev ID"; // use your dev ID
oContext.ApiCredential.ApiAccount.Application = "//App ID"; // use your app ID
oContext.ApiCredential.ApiAccount.Certificate = "//cert ID"; // use your cert ID
oContext.ApiCredential.eBayToken = "//Token"; //set the AuthToken
oContext.SoapApiServerUrl = "https://api.sandbox.ebay.com/wsapi";
//set the Site of the Context
oContext.Site = eBay.Service.Core.Soap.SiteCodeType.Germany;
//the WSDL Version used for this SDK build
oContext.Version = "735";
//very important, let's setup the logging
ApiLogManager oLogManager = new ApiLogManager();
oLogManager.ApiLoggerList.Add(new eBay.Service.Util.FileLogger("GetItem.log", true, true, true));
oLogManager.EnableLogging = true;
oContext.ApiLogManager = oLogManager;
GetItemCall oGetItemCall = new GetItemCall(oContext);
//' set the Version used in the call
oGetItemCall.Version = oContext.Version;
//' set the Site of the call
oGetItemCall.Site = oContext.Site;
//' enable the compression feature
oGetItemCall.EnableCompression = true;
oGetItemCall.DetailLevelList.Add(eBay.Service.Core.Soap.DetailLevelCodeType.ReturnAll);
oGetItemCall.ItemID = itemId;
try
{
oGetItemCall.GetItem(oGetItemCall.ItemID);
}
catch (Exception E)
{
Console.Write(E.ToString());
oGetItemCall.GetItem(itemId);
}
GC.Collect();
return oGetItemCall;
}
public ActionResult Index()
{
getItemDataFromEbay("173354849991");
return View();
}
From the error you are getting I would guess that you are trying to get information regarding a "random listing" you have not entered yourself on the eBay sandbox. In order to use GetItem the listing you are retrieving has to have been created using your sandbox user id.
Take a look at the below link to API doc for GetItem() - specifically the requirements for "Testing GetItem". If you think I might be correct then try creating a listing in the sandbox using either the Web Interface or eBay API AddItem() before retrieving it with GetItem().
https://developer.ebay.com/devzone/xml/docs/reference/ebay/getitem.html
UPDATE: I still haven't solved it, my my current work around is to not do a desktop client. I've switched back to a web app for now, and everything is working again. I don't know, I'm stumped.
I've been able to get my Twitter web app working just fine, but I've recently decided to add Tweeting functionality from a Windows Form, but I'm having no luck sending tweets. No errors are thrown or anything. Mind looking over my code?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TweetSharp;
namespace TwitterAdvirtiser
{
public partial class Form1 : Form
{
private string cKey = "xxx";
private string cSecret = "xxx";
private string oToken = "xxx";
private string aToken = "xxx";
public Form1()
{
InitializeComponent();
OnStart();
}
private void OnStart()
{
//Authenticate with Twitter
TwitterService service = new TwitterService(cKey, cSecret);
service.AuthenticateWith(oToken, aToken);
service.SendTweet("testing");
}
}
}
It seems like I'm authenticating just fine, I can walk through debug mode and see all my details in the TwitterUser structure, and yet my tweets never show up on my feed. Whats up?
By the way, I'm using Visual Studios 2010, and .NET 4.0. I have verified that the oToken and aToken strings have my developer tokens.
As far as I can see you're only authenticating using the Consumer Key, Consumer Secret, Token Key and Token Secret. You also need to include the verifier pin with the signature base.