Search code examples
c#gittfstfs-sdk

How do I create a TFS 2013 Git repository via Web Api?


I'm trying to automate creating git repositories for my team. I need to use the Web Api, NOT the .NET API. The call I'm trying to use is this one which responds, but returns the following error body within a HTTP/1.1 400 Bad Request:

{"$id":"1","innerException":null,"message":"Bad parameters. A repository with a team project and a name are required.","typeName":"System.ArgumentException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","typeKey":"ArgumentException","errorCode":0,"eventId":0}

The error message is: Bad parameters. A repository with a team project and a name are required.

Here's my code:

    var projectName = "testing";
    var url = ConfigurationManager.AppSettings["TFS-Url"] + "/_apis/git/repositories/?api-version=1.0";
    var data = "{ \"name\": \"" + projectName + "\", \"project\": { \"id\": \"" + ConfigurationManager.AppSettings["TFS-Parent-Project-Guid"] + "\", \"name\": \"" + ConfigurationManager.AppSettings["TFS-Parent-Project-Name"] + "\" } }";

    var wc = new WebClient();
    wc.Credentials = new NetworkCredential("user", "pass");
    var res = wc.UploadString(url, data);

I have tried this without the "name" of the project - (like the example does), without the "id", with varying "id" guids gathered from the Get Repositories Api.

No matter what I try, the same error is returned. Any ideas?


Solution

  • I know this is old, but hopefully someone else stumbles here for an answer...

    The documentation on MS's website is incorrect. Id is a required property for the Project object when submitting the postdata via the WebApi for creating a new repository in TFS (tested on TFS 2015 Update 2, Update 3, and VSTS).

    A code solution for this, should you not have a list of the GUIDs of your projects available is:

    public static TfsProject GetTfsProjectGuid(string projectName, string collectionName)
    {
        var tfsInstance = ConfigurationManager.AppSettings["TFSInstance"];
        using (var client = new WebClient())
        {
            client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
            client.UseDefaultCredentials = true;
    
            var tfsUri = new Uri(tfsInstance + collectionName + "/_apis/projects/" + projectName + "?api-version=1.0");
            var response = client.DownloadString(tfsUri);
    
            JavaScriptSerializer jss = new JavaScriptSerializer();
            return jss.Deserialize<TfsProject>(response.ToString());
        }
    }
    

    TfsProject looks like:

    public class TfsProject
    {
        public string id { get; set; }
        public string name { get; set; }
        public string description { get; set; }
        public string url { get; set; }
        public string state { get; set; }
        public int revision { get; set; }
    }
    

    For actually creating the repo, I'm using:

    public static OperationResult CreateTfsGitRepository(string projectName, string repositoryName, string collectionName)
    {
        var tfsInstance = ConfigurationManager.AppSettings["TFSInstance"];
        using (var client = new WebClient())
        {
            client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
            client.UseDefaultCredentials = true;
    
            var tfsNewRepository = new TfsRepository();
            tfsNewRepository.name = repositoryName;
            tfsNewRepository.project.id = TfsHelper.GetTfsProjectGuid(projectName, collectionName).id;
            var tfsUri = new Uri(tfsInstance + collectionName + "/_apis/git/repositories/?api-version=1.0");
    
            JavaScriptSerializer jss = new JavaScriptSerializer();
            var jsonValues = jss.Serialize(tfsNewRepository);
            try
            {
                var response = client.UploadString(tfsUri, "POST", jsonValues);
            }
            catch (WebException ex)
            {
                //Handle WebExceptions here.  409 is the error code for a repository with the same name already exists within the specified project
            }
            return new OperationResult { ReturnValue = 0, Message = "Repository created successfully." };
        }
    }
    

    OperationResult object is:

    public class OperationResult
    {
        public int ReturnValue { get; set; }
        public string Message { get; set; }
    }
    

    Thanks!