C# OctoKit CreateFile Not found issue - c#

I trying to commit a file to a github repo using C# and OctoKit using the following code:
static async void CommitFile()
{
var ghClient = new GitHubClient(new ProductHeaderValue("Octokit-Test"));
ghClient.Credentials = new Credentials("//...//");
// github variables
var owner = "owner";
var repo = "repo";
var branch = "main";
// create file
var createChangeSet = await ghClient.Repository.Content.CreateFile(owner,repo, "file2.txt",new CreateFileRequest("File creation", "Hello World!", branch));
}
Whenever I execute it I get:
Octokit.NotFoundException: 'Not Found'
Here are the following things I want to mention:
I generated a personal access token
The repo is private
If I put incorrect personal access token I get "Bad Credentials" error. If I
put the correct credentials I get the not found error.

var gitHubClient = new GitHubClient(new ProductHeaderValue(repoName));
gitHubClient.Credentials = new Credentials(authorizedKey);
var path = "test.txt";
var resp = await gitHubClient.Repository.Content.CreateFile(owner, repoName, path, new CreateFileRequest($"First commit ", "Hello World" , "BranchName"))

I have decided to use LibGit2Sharp. I was able to get up and running after a few mins.

Related

Nethereuem SendTransactionAsync from my C# Web API fails with transaction type not supported: eth_sendRawTransaction

I'm working on integrating Nethereum into my .NET 5 C# API and can do read queries against my chosen blockchain (BSC), but cannot get a SendTransactionAsync or SendRequestAsync to successfully execute. I'm consistently getting the following exception:
Nethereum.JsonRpc.Client.RpcResponseException: 'transaction type not supported: eth_sendRawTransaction'.
Here are code snippets of what I have tried:
// Setup
var account = new Account(privateKey, chainId);
var rpcUrl = "https://data-seed-prebsc-2-s2.binance.org:8545/";
var client = new RpcClient(new Uri(rpcUrl));
var web3 = new Web3(account, client);
var mediaTokenAddress = "0x1E4d1BFDa5d55C2176E9E3e8367BAe720525a8e0";
var mtSvc = new MediaTokenService(web3, mediaTokenAddress);
var mintMsg = new MintNftFunction
{
FromAddress = account.Address,
Recipient = "REDACTED",
MetadataHash = "TestMetaDataHash",
MediaHash = "TestMediaHash",
SeasonId = 1
};
// Attempt #1: Using C# classes generated by the Nethereum CodeGen library
var txReceipt = await mtSvc.MintNftRequestAndWaitForReceiptAsync(mintMsg);
// Attempt #2
var txHandler = web3.Eth.GetContractTransactionHandler<MintNftFunction>();
var signedTx = await txHandler.SignTransactionAsync(mediaTokenAddress, mintMsg);
var txReceipt = await web3.Eth.Transactions.SendTransaction.SendRequestAsync(signedTx);
// Attempt #3
var txInput = mintMsg.CreateTransactionInput(mediaTokenAddress);
var txReceipt = await web3.Eth.TransactionManager.SendTransactionAsync(txInput);
Is there a configuration step I'm missing? Any help is appreciated!
EDIT: I want to call a contract method that will change values within the contract, rather than sending currency. So I need help figuring out how to do that.
For those that come across this issue, I resolved it by setting the following flag on my web3 instance:
web3.TransactionManager.UseLegacyAsDefault = true;
If there is a way to do what I need without setting this flag, please feel free to leave a comment.
Here is an example of how I do this with Nethereum
var web3 = new Nethereum.Web3.Web3("YOUR_NODE_ADDRESS");
var privateKey = "someprivatekey";
var senderAddress = "0x..."; // put actual sender address
var receiveAddress = "0x..."; //put actual receiver address
var txCount = await web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(senderAddress);
double sendAmount = 5.09540000; //this is ETH
var amountInWei = Web3.Convert.ToWei(sendAmount);
//600 GWEI = 0.000000600
//60 GWEI = 0.000000060
var gwei = 147; // this is 0.000000147 ETH. You will want to calculate this based on network fees
var gasPrice = Web3.Convert.ToWei(0.000000001 * gwei);
var gasLimit = Web3.Convert.ToWei(0.000000000000021);
var encoded = Web3.OfflineTransactionSigner.SignTransaction(privateKey, receiveAddress, amountInWei, txCount.Value, gasPrice, gasLimit);
//This is what prompts the transactions
Web3.OfflineTransactionSigner.GetSenderAddress(encoded).Dump();
//TX Returns from this action
var txId = await web3.Eth.Transactions.SendRawTransaction.SendRequestAsync("0x" + encoded);
//Dump out the TX if successful
txId.Dump();
I've used this many times and it has worked for me just fine.

Programmatically retrieve list of source folders and create one if not present - C# + VSTS 2017

I am trying to automate some processes to make life a bit easier. We have multiple requests from the team to create a folder in TFS 2017 (they do not have permissions) and then set up the associated builds for that source control folder.
The build creation part I think I have a way to do, but querying our on premise TFS 2017 server to get a list of folders under a certain path is proving tricky. So far I am having trouble even connecting to the server in the first place with this :
var collectionUri = "http://tfs-server:8080/tfs/DefaultCollection/";
var teamProjectName = "MYPROJECT";
Uri uri = new Uri(collectionUri);
var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "COLLECTIONNAME")));
var connection = new VssConnection(uri, clientCredentials);
var sourceControlServer = connection.GetClient<TfvcHttpClient>();
That throws an exception : Error converting value "System.Security.Principal.WindowsIdentity;" to type 'Microsoft.VisualStudio.Services.Identity.IdentityDescriptor'
Can someone help me to get connected to the server first please! Documentation on this is very hard to find, and I dont see any examples that actually work.
What I was going to look at next was creating the folder if it doesn't exist. No idea how to do that yet, maybe using
sourceControlServer.GetBranchAsync(teamProjectName + FolderName);
Thanks!
EDIT:
Ok I got it to not error creating the connection by doing this instead :
Uri uri = new Uri("http://tfs-server:8080/tfs/DefaultCollection/");
var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN")));
var buildServer = new BuildHttpClient(uri, clientCredentials);
var sourceControlServer = new TfvcHttpClient(uri, clientCredentials);
So now to just figure out how to list and create folders from TFS and to create builds!
EDIT:
So I have got the querying working, so I can check if a folder exists under a path like this :
var teamProjectName = "USA";
Uri uri = new Uri("http://tfs-server:8080/tfs/DefaultCollection/");
var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN")));
TfvcHttpClient sourceControlServer = new TfvcHttpClient(uri, clientCredentials);
List<TfvcItem> branchItems;
using (sourceControlServer) {
branchItems = sourceControlServer.GetItemsAsync("$/USA/Development/NewFolder", VersionControlRecursionType.OneLevel).Result;
}
return branchItems.Count > 0;
That will find all the items under that folder. So if there isnt a folder, it will return 0, so I can go ahead and create that folder.
So next problem, is how to create the folder. Using CreateChangesetAsync.
Update:
To use Client API and CreateChangesetAsync method to create files in TFVC, you could refer below sample console app:
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
internal static async Task Main(string[] args)
{
var orgUrl = new Uri(args[0]);
string serverPath = args[1];
string localPath = args[2];
string contentType = args[3];
string pat = args[4];
var changes = new List<TfvcChange>()
{
new TfvcChange()
{
ChangeType = VersionControlChangeType.Add,
Item = new TfvcItem()
{
Path = serverPath,
ContentMetadata = new FileContentMetadata()
{
Encoding = Encoding.UTF8.WindowsCodePage,
ContentType = contentType,
}
},
NewContent = new ItemContent()
{
Content = Convert.ToBase64String(File.ReadAllBytes(localPath)),
ContentType = ItemContentType.Base64Encoded
}
}
};
var changeset = new TfvcChangeset()
{
Changes = changes,
Comment = $"Added {serverPath} from {localPath}"
};
var connection = new VssConnection(orgUrl, new VssBasicCredential(string.Empty, pat));
var tfvcClient = connection.GetClient<TfvcHttpClient>();
await tfvcClient.CreateChangesetAsync(changeset);
}
}
}
Besides, instead of using tf command line, please kindly check solution here:
C# TFS API: show project structure with folders and files, including their ChangeType (checked out, deleted,renamed) like in visual studio

Azure DevOps: Wiki page with WikiHttpClient not found

I created a project wiki in Azure DevOps and want to get the wiki markdown pages in my .NET application. When using the link
https://dev.azure.com/company/project/_apis/wiki/wikis/KIS.wiki/pages/News
The markdown gets shown in the browser. When I try to do that in code, I am getting
"Wiki page ‘/News/_apis/connectionData’ could not be found. Ensure that the path of the page is correct and the page exists."
My code looks like this:
var url = new Uri("https://dev.azure.com/company/project/_apis/wiki/wikis/KIS.wiki/pages/News");
var personalAccessToken = "xxxxxxxxxxxxxxxx";
var credentials = new VssCredentials(new VssBasicCredential("", personalAccessToken));
using (var connection = new VssConnection(url, credentials))
{
var wikiClient = connection.GetClient<WikiHttpClient>();
var markdown = wikiClient.GetWikiAsync("KIS.wiki").Result;
}
The error appears on GetClient().
What am I doing wrong?
I see a couple problems with how you're trying to get the page content.
The url given to the connection should be the "project base path"
private static string BasePath = $"https://dev.azure.com/{Organization}";
You're using the GetWikiAsync(...) method when you want to be using the GetPageAsync(...) method
Here's an example
private readonly IVssCredentialsFactory _credentialsFactory;
private const string ApiVersion = "5.1";
private static string BasePath = $"https://dev.azure.com/{Organization}";
private const string Organization = "company";
private const string Project = "project";
public AzureRepository(IVssCredentialsFactory credentialsFactory)
{
_credentialsFactory = credentialsFactory;
}
public void GetWikiPage()
{
using (var connection = new VssConnection(new Uri(BasePath), _credentialsFactory.GetCredentials()))
{
var wikiClient = connection.GetClient<WikiHttpClient>();
var wikiId = "KIS.wiki";
var path = "/News";
var page = wikiClient.GetPageAsync(Project, wikiId, path, includeContent : true).Result;
var content = page.Page.Content;
}
}
notes about this sample:
IVssCredentialsFactory is my creation, so don't look for it in the lib
The injection of the factory is were the PAT or oAuth token is, so don't think you're doing anything wrong there. You're not.
I hope it's obvious that the method isn't doing anything with the result, b/c let's face it, it's a sample.
If you're not already
You should look at the c# client samples. It's not exhaustive, but can be helpful.

creating a github issue in octokit.net

I am trying to write a script that will open an issue typed in the console.
For some reason the issue variable comes back empty in the debugger.
class Program
{
public async static Task Main()
{
var client = new GitHubClient(new ProductHeaderValue("test-app"));
var user = await client.User.Get("medic17");
var tokenAuth = new Credentials(APIKeys.GithubPersinalAccessToken);
client.Credentials = tokenAuth;
var exampleIssue = new NewIssue("test body");
var issue = await client.Issue.Create("owner","name", exampleIssue);
}
}
APIKeys holds my token.
Thanks
I found a solution hope this helps someone else as well.
class Program
{
public async static Task Main()
{
// client initialization and authentication
var client = new GitHubClient(new ProductHeaderValue("<anything>"));
var user = await client.User.Get("<user>");
var tokenAuth = new Credentials(APIKeys.GithubPersinalAccessToken);
client.Credentials = tokenAuth;
// user input
Console.WriteLine("Give a title for your issue: ");
string userIssueTitle = Console.ReadLine().Trim();
Console.WriteLine("Describe your issue:", Environment.NewLine);
string userIssue = Console.ReadLine().Trim();
// input validation
while (string.IsNullOrEmpty(userIssue) || string.IsNullOrEmpty(userIssueTitle))
{
Console.WriteLine("ERROR: Both fields must contain text");
Console.ReadLine();
break;
}
var newIssue = new NewIssue(userIssueTitle) { Body = userIssue };
var issue = await client.Issue.Create(<owner>, <repo> newIssue);
var issueId = issue.Id;
Console.WriteLine($"SUCCESS: your issue id is {issueId} ");
Console.ReadLine();
}
}
Note
You need to store your keys in a separate file and write a class for it so your authentication flow might be different.
Note 2
You must replace all text with real values.
Still a little confused the app is OpenSource for transport since it deals with HIPPA data, users who want to use it need GitHub account if they want to do any error reporting. I assume I don’t share the authToken in the source of the project but the desktop Binary needs it plus the users GitHub login and password. Any pointers? I have tried just using username password that gets entered when creating issue but that fails with “not found”. It seems like any secret that gets deployed with binary app is potentially an issue.

How does one connect to the RootDSE and/or retrieve highestCommittedUSN with System.DirectoryServices.Protocols?

Using System.DirectoryServices, one can get the highestCommittedUSN this way:
using(DirectoryEntry entry = new DirectoryEntry("LDAP://servername:636/RootDSE"))
{
var usn = entry.Properties["highestCommittedUSN"].Value;
}
However, I need to get this information from a remote ADLDS using System.DirectoryServices.Protocols, which does not leverage ADSI. Following is a simplified code sample of what I'm attempting to do:
using(LdapConnection connection = GetWin32LdapConnection())
{
var filter = "(&(highestCommittedUSN=*))";
var searchRequest = new SearchRequest("RootDSE", filter, SearchScope.Subtree, "highestCommittedUSN");
var response = connection.SendRequest(searchRequest) as SearchResponse;
var usn = response.Entries[0].Attributes["highestCommittedUSN"][0];
}
Unfortunately this kicks back a "DirectoryOperationException: The distinguished name contains invalid syntax." At first I thought there might be something wrong in GetWin32LdapConnection() but that code is called in numerous other places to connect to the directory and never errors out.
Any ideas?
Thanks for the idea, Zilog. Apparently to connect to the RootDSE, you have to specify null for the root container. I also switched the filter to objectClass=* and the search scope to "base." Now it works!
using(LdapConnection connection = GetWin32LdapConnection())
{
var filter = "(&(objectClass=*))";
var searchRequest = new SearchRequest(null, filter, SearchScope.Base, "highestCommittedUSN");
var response = connection.SendRequest(searchRequest) as SearchResponse;
var usn = response.Entries[0].Attributes["highestcommittedusn"][0];
}
I hope this saves someone else some time in the future.

Categories