eBay API - getCategories timeout - c#

Trying to get all the categories from Ebay to shove into the database. I've tried increasing the timeout value of the underlying api context, but I still get a timeout after about two minutes - what else do I need to do?
var c = new eBay.Service.Call.GetCategoriesCall(this.apiContext);
c.CategorySiteID = ((int)siteId).ToString(); // siteId is an eBay SiteCode enum value
var version = c.GetCategoriesVersion();
c.DetailLevelList = new DetailLevelCodeTypeCollection();
c.DetailLevelList.Add(DetailLevelCodeType.ReturnAll);
c.ViewAllNodes = !onlyLeafCategories;
c.Timeout = 1000*60*20;
c.GetCategories(); // this causes a connection closed / timeout

Try this code, it works for me :
// get all categories from eBay
ApiContext context = GetApiContext();
GetCategoriesCall apiCall = new GetCategoriesCall(context)
{
EnableCompression = true,
ViewAllNodes = true
};
apiCall.DetailLevelList.Add(DetailLevelCodeType.ReturnAll);
apiCall.GetCategories();
public static ApiContext GetApiContext()
{
//apiContext is a singleton,
//to avoid duplicate configuration reading
if (apiContext != null)
{
return apiContext;
}
else
{
apiContext = new ApiContext();
//set Api Server Url
apiContext.SoapApiServerUrl = "https://api.ebay.com/wsapi";
//set Api Token to access eBay Api Server
ApiCredential apiCredential = new ApiCredential();
apiCredential.eBayToken ="YOUR_TOKEN";
apiContext.ApiCredential = apiCredential;
//set eBay Site target to US
apiContext.Site = eBay.Service.Core.Soap.SiteCodeType.US;
return apiContext;
}
}

Related

ExecuteMultipleResponse Dynamics CRM Unit tests error

Currently I am trying to write tests for Dynamics CRM app using Fake XRM Easy. This code gives me an error.
var executeMultiple = new ExecuteMultipleRequest
{
Settings = new ExecuteMultipleSettings
{
ContinueOnError = true,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
executeMultiple.Requests.AddRange(this.requestBag.Select(x => x.request));
try
{
var batchResponse = (ExecuteMultipleResponse)this.orgService.Execute(executeMultiple);
foreach (var response in batchResponse.Responses)
{
this.requestsPerformedByServiceCounter++;
this.OnResponseReceived(new ResponseReceivedEventArgs
{
Fault = response.Fault,
RequestIndex = response.RequestIndex,
Response = response.Response,
Request = this.requestBag[response.RequestIndex].request,
Identifier = this.requestBag[response.RequestIndex].identifier,
TotalRequestsPerformed = this.requestsPerformedByServiceCounter,
});
}
this.requestBag.Clear();
This method is calling upper method
foreach (var company in this.companies)
{
EntityReference existedAccountRef = null;
if (!string.IsNullOrEmpty(company.id.ToString()))
{
var existedAccount = this.crmService.IsCompanyExistInCrm(company.id);
existedAccountRef = existedAccount != null ? existedAccount.ToEntityReference() : null;
}
if (existedAccountRef != null)
{
bulkExecutionService.Update(new Account()
{
AccountId = existedAccountRef.Id,
Name = company.name,
odx_Bank_Account_Number = company.bank_account_number,
// odx_Company_share_Capital = company.company_share_capital, todo
odx_Is_Foreign = company.is_foreign,
odx_KRS = company.krs,
odx_Legal_form = company.legal_form,
odx_NIP = company.nip,
odx_Paynow_Created_at = company.created_at,
odx_Paynow_Modified_at = company.modified_at,
odx_PaynowID = company.id,
odx_pkd = company.pkd,
odx_regon = company.regon,
odx_Vat_EU = company.vat_eu
}, company.id);
}
else
{
bulkExecutionService.Create(new Account()
{
Name = company.name,
odx_Bank_Account_Number = company.bank_account_number,
// odx_Company_share_Capital = company.company_share_capital, todo
odx_Is_Foreign = company.is_foreign,
odx_KRS = company.krs,
odx_Legal_form = company.legal_form,
odx_NIP = company.nip,
odx_Paynow_Created_at = company.created_at,
odx_Paynow_Modified_at = company.modified_at,
odx_PaynowID = company.id,
odx_pkd = company.pkd,
odx_regon = company.regon,
odx_Vat_EU = company.vat_eu
}, company.id);
}
}
bulkExecutionService.FinalizeExecutor();
Error I am getting is in this line:
var batchResponse = (ExecuteMultipleResponse)this.orgService.Execute(executeMultiple);
FakeXrmEasy.Abstractions.Exceptions.PullRequestException: 'Exception: The organization request type 'Microsoft.Xrm.Sdk.Messages.ExecuteMultipleRequest' is not yet supported...
To be honest i don't know what can I do with it.
Did you try installing FakeXrmEasy.Messages package?
FakeXrmEasy v2 or later now use a modular architecture.
Create, Retrieve, Update, Delete, Upsert, Associate or Dissasociate messages live in the FakeXrmEasy.Core package but other messages live now in that dedicated FakeXrmEasy.Messages package.
This is covered in the Installing section of the docs site
EDIT: After installing the Messages package, please also add a reference to one of the fake message executors in the middleware setup like this:
.AddFakeMessageExecutors(Assembly.GetAssembly(typeof(AddListMembersListRequestExecutor)))
This will use reflection to find any other fake messages. You can call that method as many times as you want in case you have your own messages in your own assembly. This is possible since the 2.1.x and 3.1.x versions.
Please check the release notes here:
https://dynamicsvalue.github.io/fake-xrm-easy-docs/releases/2x/2.1.1/

Renew cridentials for AmazonKinesisClient using AWSSDK

Im creating a on-prem application in .Net that consumes a kinesis stream.
How do I write a method that can renew the cridentials for my KinesisClient (They are only valid for 1 hour) without re-create the client itself. Is that possible? Or am I approching this the wrong way?
This is the factory class that im using to produce the client.
public static AmazonKinesisClient CreateKinesisClient(BasicAWSCredentials credentials, string roleArn, string roleSessionName, RegionEndpoint region, LogWriter logWriter)
{
try
{
var stsClient = new AmazonSecurityTokenServiceClient(credentials);
var ownerRoleReq = new AssumeRoleRequest
{
RoleArn = roleArn,
RoleSessionName = roleSessionName
};
var ownerRoleResp = stsClient.AssumeRoleAsync(ownerRoleReq).Result;
logWriter.LogInfo<AmazonKinesisClient>("Role taken:" + ownerRoleResp.AssumedRoleUser);
return new AmazonKinesisClient(ownerRoleResp.Credentials, region);
}
catch (Exception e)
{
logWriter.LogError<AmazonClientFactory>(e.Message,e);
throw;
}
}
I ended up with saving the latest record id in a concurrent dictionary and while re-creating the client injecting the dictionary containing the latest id for each shard in the KinesisStream.
private string CreateShardIteratorRequestWithSequenceNumber(Shard shard, string sequenceNumber)
{
var iteratorRequest = new GetShardIteratorRequest()
{
ShardId = shard.ShardId,
StreamName = _streamName,
ShardIteratorType = ShardIteratorType.AFTER_SEQUENCE_NUMBER,
StartingSequenceNumber = sequenceNumber
};
return GetShardIterator(iteratorRequest);
}

using IRequiresSessionState, IReadOnlySessionState breaks oauth2 but is required to set cookie

I have a generic handler written in C# - this is called as part of an OAuth2 process to validate users via Google.
Once the correct user is identified I need to set a cookie so the rest of the site can then identify the user.
The trouble is in order to set session variables the handler needs to implement IRequiresSessionState - when I do that - then the OAuth 2 process fails with the following error.
Unexpected OAuth authorization response received with callback and client state that does not match an expected value
So I can implement OAuth or write a session variable but cannot do both. I could get OAuth to call the first page but then the code can be seen in the URL (which I would rather not do - as it gives clues for any nefarious person to break security ). I could get a page to call the handler, return JSON to identify the user and have the page itself set the session variable, then go to the first page - but this page would have no content, as well as requiring two hops - so how can you have an HTML page which is essentially empty, or set the session without IRequiresSessionState breaking the session.
The code for the OAuth handler is shown below.
public void ProcessRequest(HttpContext context)
{
NetworkParameters networkParameters = null;
NetworkParameter networkParameter = null;
WebServerClient consumer = null;
AuthorizationServerDescription server = null;
IAuthorizationState grantedAccess = null;
LoginResult loginResult = null;
String code = String.Empty;
String result = String.Empty;
String consumerSecret = String.Empty;
String consumerKey = String.Empty;
String securityCookieVal = String.Empty;
Uri tokenEndpoint = null;
Uri authorizationEndpoint = null;
Profile profile = null;
Profile profile2 = null;
Profiles profiles = null;
NetworkAuthorizations authorizations = null;
NetworkAuthorization na = null;
try
{
loginResult = new LoginResult();
tokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token");
authorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=auto");
// retrieve network parameters
networkParameters = new NetworkParameters(Properties.Settings.Default.DatabaseConnection);
authorizations = new NetworkAuthorizations(Properties.Settings.Default.DatabaseConnection);
networkParameter = networkParameters.Select("GOOGLE");
code = context.Request["code"];
consumerKey = networkParameter.ClientId;
consumerSecret = networkParameter.ClientSecret;
// set up request
server = new AuthorizationServerDescription();
server.AuthorizationEndpoint = authorizationEndpoint;
server.TokenEndpoint = tokenEndpoint;
server.ProtocolVersion = ProtocolVersion.V20;
// initialise webserver client
consumer = new WebServerClient(server, consumerKey, consumerSecret);
consumer.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(consumerSecret);
// retrieve access
grantedAccess = consumer.ProcessUserAuthorization();
profile = GoogleServices.GetProfile(grantedAccess.AccessToken);
profiles = new Profiles(Properties.Settings.Default.DatabaseConnection);
profile2 = profiles.SelectByNetworkId(profile.Network, profile.NetworkId);
if (profile2 == null)
{
na = new NetworkAuthorization()
{
Id = Guid.NewGuid().ToString(),
AccessToken = grantedAccess.AccessToken,
ExpirationDate = (DateTime)grantedAccess.AccessTokenExpirationUtc,
IssueDate = (DateTime)grantedAccess.AccessTokenIssueDateUtc,
RefreshToken = grantedAccess.RefreshToken,
Network = profile.Network,
NetworkId = profile.NetworkId
};
authorizations.Insert(na);
profiles.Insert(profile);
}
loginResult.UserId = profile.NetworkId;
}
catch (System.Exception e)
{
loginResult.Status.Status = "ERROR";
loginResult.Status.Message = e.Message;
}
finally
{
context.Response.ContentType = "application/json";
context.Response.Write(JsonConvert.SerializeObject(loginResult));
}
}
Not really an answer - but I got around this by passing a randomly generated id to the first page of the website, and storing it against the user - cookie was set when the first page was called.
Not really secure sending such information in the query string but will suffice in what is a prototype - eventual plan is to use Node.js where this will not be an issue.

Aweber API .NET SDK 401 unauthorized exception

I've followed the documentation steps and everything went smooth until step 5.
After successful authorization I've tried to access account data, like in step 5
var api = new API(ConsumerKey, ConsumerSecret);
api.OAuthToken = "My OAuthToken"; // That I've received on step 4
Account account = api.getAccount();
and I've got 401 exception on api.getAccount();
Please tell me what am I missing? What am I doing wrong?
Thanks
I've found a solution. In order someone else has the same issue, here is fully functional code example
public class AWeber
{
public void Authorize()
{
var Session = HttpContext.Current.Session;
var api = new API(AppSettings.AWebberConsumerKey, AppSettings.AWebberConsumerSecret);
api.CallbackUrl = "http://localhost:61006/test.aspx";
api.get_request_token();
Session["OAuthToken"] = api.OAuthToken;
Session["OAuthTokenSecret"] = api.OAuthTokenSecret;
api.authorize();
}
public void InitAccessToken(string OAuthVerifier)
{
var Session = HttpContext.Current.Session;
var api = new API(AppSettings.AWebberConsumerKey, AppSettings.AWebberConsumerSecret);
api.OAuthToken = (string)Session["OAuthToken"];
api.OAuthTokenSecret = (string)Session["OAuthTokenSecret"];
api.OAuthVerifier = OAuthVerifier;
// These two are final token that are needed
Session["OAuthToken"] = api.get_access_token();
Session["OAuthTokenSecret"] = api.adapter.OAuthTokenSecret;
}
public void GetData()
{
var Session = HttpContext.Current.Session;
var api = new API(AppSettings.AWebberConsumerKey, AppSettings.AWebberConsumerSecret);
api.adapter.OAuthToken = (string)Session["OAuthToken"];
api.adapter.OAuthTokenSecret = (string)Session["OAuthTokenSecret"];
Account account = api.getAccount();
}
}

C# Google drive sdk. How to get a list of google drive folders?

I'm writing a program to allow a user to upload files to their Google Drive account. I have the upload part working and am using OAuth2. The issue I'm currently having is getting a list of folders from the users Drive account.
I found some code that is supposed to do this using the .setUserCredentials method, but it doesn't work:
DocumentsService service1 = new DocumentsService("project");
service1.setUserCredentials("user","pass");
FolderQuery query1 = new FolderQuery();
// Make a request to the API and get all documents.
DocumentsFeed feed = service1.Query(query1);
// Iterate through all of the documents returned
foreach (DocumentEntry entry in feed.Entries)
{
var blech = entry.Title.Text;
}
Nothing is returned. Ideally, I want to use OAuth2 to do this. I've been trying with the following code, trying to set the authentication token, but I always get denied access:
String CLIENT_ID = "clientid";
String CLIENT_SECRET = "secretid";
var docprovider = new NativeApplicationClient(GoogleAuthenticationServer.Description, CLIENT_ID, CLIENT_SECRET);
var docstate = GetDocAuthentication(docprovider);
DocumentsService service1 = new DocumentsService("project");
service1.SetAuthenticationToken(docstate.RefreshToken);
FolderQuery query1 = new FolderQuery();
DocumentsFeed feed = service1.Query(query1); //get error here
// Iterate through all of the documents returned
foreach (DocumentEntry entry in feed.Entries)
{
// Print the title of this document to the screen
var blech = entry.Title.Text;
}
..
private static IAuthorizationState GetDocAuthentication(NativeApplicationClient client)
{
const string STORAGE = "storagestring";
const string KEY = "keystring";
string scope = "https://docs.google.com/feeds/default/private/full/-/folder";
// Check if there is a cached refresh token available.
IAuthorizationState state = AuthorizationMgr.GetCachedRefreshToken(STORAGE, KEY);
if (state != null)
{
try
{
client.RefreshToken(state);
return state; // Yes - we are done.
}
catch (DotNetOpenAuth.Messaging.ProtocolException ex)
{
}
}
// Retrieve the authorization from the user.
state = AuthorizationMgr.RequestNativeAuthorization(client, scope);
AuthorizationMgr.SetCachedRefreshToken(STORAGE, KEY, state);
return state;
}
Specifically, I get "Execution of request failed: https://docs.google.com/feeds/default/private/full/-/folder - The remote server returned an error: (401) Unauthorized".
I've also tried:
var docauth = new OAuth2Authenticator<NativeApplicationClient>(docprovider, GetDocAuthentication);
DocumentsService service1 = new DocumentsService("project");
service1.SetAuthenticationToken(docauth.State.AccessToken);
but "State" is always null, so I get a null object error. What am I doing wrong and how is this done?
You should use the Drive SDK, not the Documents List API, which allows you to list folders. You can use "root" as a folderId if you want to list the root directory.
I actually implemented the v3 version of the GDrive SDK for .NET and needed to search for folders as well.
I prefer requesting uniquely all folders instead of getting all files and then performing a LinQ query to keep just the folders.
This is my implementation:
private async Task<bool> FolderExistsAsync(string folderName)
{
var response = await GetAllFoldersAsync();
return response.Files
.Where(x => x.Name.ToLower() == folderName.ToLower())
.Any();
}
private async Task<Google.Apis.Drive.v3.Data.FileList> GetAllFoldersAsync()
{
var request = _service.Files.List();
request.Q = "mimeType = 'application/vnd.google-apps.folder'";
var response = await request.ExecuteAsync();
return response;
}
You could request the name on the Q this way as well:
request.Q = $"mimeType = 'application/vnd.google-apps.folder' and name = '{folderName}'";
Which would lead and simplify things to (obviating null checking):
private async Task<bool> FolderExistsAsync(string folderName)
{
var response = await GetDesiredFolder(folderName);
return response.Files.Any();
}
private async Task<FileList> GetDesiredFolder(string folderName)
{
var request = _service.Files.List();
request.Q = $"mimeType = 'application/vnd.google-apps.folder' and name = '{folderName}'";
var response = await request.ExecuteAsync();
return response;
}
private IEnumerable<DocumentEntry> GetFolders(string id) {
if (IsLogged) {
var query = new FolderQuery(id)
{
ShowFolders = true
};
var feed = GoogleDocumentsService.Query(query);
return feed.Entries.Cast<DocumentEntry>().Where(x => x.IsFolder).OrderBy(x => x.Title.Text);
}
return null;
}
...
var rootFolders = GetFolders("root");
if (rootFolders != null){
foreach(var folder in rootFolders){
var subFolders = GetFolders(folder.ResourceId);
...
}
}
where GoogleDocumentsService is a instance of DocumentsService and IsLogged is a success logged flag.
I got this way to get list of folders from google drive
FilesResource.ListRequest filelist= service.Files.List();
filelist.Execute().Items.ToList().Where(x => x.MimeType == "application/vnd.google-apps.folder").ToList()

Categories

Resources