How do I display REST data from an api in a simple list? - rest

I am trying to pull all the names of teams and place them in a simple list. I have tried so doing this
private void ParseAndDisplay(JsonValue json)
{
dynamic teamData = json["teams"];
//TextView name = FindViewById<TextView>(Resource.Id.txtName);
string[] teams;
foreach (var team in teamData)
{
var name = team["name"];
Console.Out.WriteLine("\r\n {0}", name);
teams = new string[] { name };
//TextView name = FindViewById<TextView>(Resource.Id.txtName);
//name.Text = team["name"];
ListAdapter = new ArrayAdapter<String>(this, Android.Resource.Layout.SimpleListItem1, teams);
}
However on my device it only displays the name of the last team in the data whereas in the output it shows all of them.

Related

Working on pre-operation plug-in to update "Modified By" field in MSCRM -- Need help fixing code

I am trying to update the "Modified By" field based on a text field called "Prepared By", which contains the name of a user. I've created a pre-operation plug-in to do this and believe I am close to done. However, the "Modified By" field is still not successfully getting updated. I am relatively new to coding and CRM, and could use some help modifying the code and figuring out how I can get this to work.
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Linq;
namespace TimClassLibrary1.Plugins
{
public class CreateUpdateContact : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = factory.CreateOrganizationService(context.UserId);
tracingService.Trace("Start plugin");
tracingService.Trace("Validate Target");
if (!context.InputParameters.Contains("Target") || !(context.InputParameters["Target"] is Entity))
return;
tracingService.Trace("Retrieve Target");
var target = (Entity)context.InputParameters["Target"];
String message = context.MessageName.ToLower();
SetCreatedByAndModifiedBy(tracingService, service, target, message);
}
private void SetCreatedByAndModifiedBy(ITracingService tracingService, IOrganizationService service, Entity target, string message)
{
tracingService.Trace("Start SetPriceList");
tracingService.Trace("Validate Message is Create or Update");
if (!message.Equals("create", StringComparison.OrdinalIgnoreCase) && !message.Equals("update", StringComparison.OrdinalIgnoreCase))
return;
tracingService.Trace("Retrieve Attributes");
var createdByReference = target.GetAttributeValue<EntityReference>("new_createdby");
var modifiedByReference = target.GetAttributeValue<EntityReference>("new_modifiedby");
tracingService.Trace("Retrieve And Set User for Created By");
RetrieveAndSetUser(tracingService, service, target, createdByReference, "createdby");
tracingService.Trace("Retrieve And Set User for Modified By");
RetrieveAndSetUser(tracingService, service, target, modifiedByReference, "modifiedby");
}
private void RetrieveAndSetUser(ITracingService tracingService, IOrganizationService service, Entity target, EntityReference reference, string targetAttribute)
{
tracingService.Trace("Validating Reference");
if (reference == null)
return;
tracingService.Trace("Retrieving and Validating User");
var user = RetrieveUserByName(service, reference.Name, new ColumnSet(false));
if (user == null)
return;
tracingService.Trace("Setting Target Attribute");
target[targetAttribute] = user.ToEntityReference();
}
private Entity RetrieveUserByName(IOrganizationService service, string name, ColumnSet columns)
{
var query = new QueryExpression
{
EntityName = "systemuser",
ColumnSet = columns,
Criteria = new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression
{
AttributeName = "fullname",
Operator = ConditionOperator.Equal,
Values = { name }
}
}
}
};
var retrieveResponse = service.RetrieveMultiple(query);
if (retrieveResponse.Entities.Count == 1)
{
return retrieveResponse.Entities.FirstOrDefault();
}
else
{
return null;
}
}
}
}
If you do get use from method Retreiveusernyname then you have to use below code
target[“modifiedby”] = new EntityRefrence(user.logicalname,user.id);
I don't see anything obviously wrong with your update, however you are taking a complicated and unnecessary step with your RetrieveUserByName() method. You already have EntityReference objects from your new_createdby and new_modifiedby fields, you can simply assign those to the target:
if (message.Equals("create", StringComparison.OrdinalIgnoreCase))
{
target["createdby"] = target["new_createdby];
}
else if (message.Equals("update", StringComparison.OrdinalIgnoreCase))
{
target["modifiedby"] = target["new_modifiedby];
}
If new_createdby and new_modifiedby are not entity references, then that would explain why your existing code does not work, if they are, then use my approach.

How to find top 10 files changed most frequently in a period from TFS 2015 Version Control?

My team uses TFS 2015 as an ALM and Version Control system,I want to analyse which files change most frequently.
I found TFS didn't have this functionality out of the box, but TFS2015 has a REST API to query Changesets for files, like this below:
http://{instance}/tfs/DefaultCollection/_apis/tfvc/changesets?searchCriteria.itemPath={filePath}&api-version=1.0
There are thousands of files in my Project Repository, querying it one by one is not a good idea, are there any better solution to this question?
I don't think there's a defacto out of the box solution for your question, I've tried two separate approaches to solve your question, I initially focused on the REST API but later switched to the SOAP API to see what features are supported in it.
In all options below the following api should suffice:
Install the client API link
#NuGet
Install-Package Microsoft.TeamFoundationServer.ExtendedClient -Version 14.89.0 or later
In all options the following extension method is required ref
public static class StringExtensions
{
public static bool ContainsAny(this string source, List<string> lookFor)
{
if (!string.IsNullOrEmpty(source) && lookFor.Count > 0)
{
return lookFor.Any(source.Contains);
}
return false;
}
}
OPTION 1: SOAP API
With the SOAP API one is not explicitly required to limit the number of query results using the maxCount parameter as described in this excerpt of QueryHistory method's IntelliSense documentation:
maxCount: This parameter allows the caller to limit the number of
results returned. QueryHistory pages results back from the server on
demand, so limiting your own consumption of the returned IEnumerable
is almost as effective (from a performance perspective) as providing a
fixed value here. The most common value to provide for this parameter
is Int32.MaxValue.
Based on the maxCount documentation I made a decision to extract statistics for each of the products in my source control system since it may be of great value to see how much code flux there is for each system in the codebase independent of each other instead of limiting to 10 files across the entire codebase which could contain hundreds of systems.
C# REST and SOAP (ExtendedClient) api reference
Install the SOAP API Client link
#NuGet
Install-Package Microsoft.TeamFoundationServer.ExtendedClient -Version 14.95.2
limiting criteria are: Only scan specific paths in source
control since some systems in source control are older and possibly only there for historic purposes.
only certain file extensions included e.g. .cs, .js
certain filenames excluded e.g. AssemblyInfo.cs.
items extracted for each path: 10
from date: 120 days ago
to date: today
exclude specific paths e.g. folders containing release branches or
archived branches
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
public void GetTopChangedFilesSoapApi()
{
var tfsUrl = "https://<SERVERNAME>/tfs/<COLLECTION>";
var domain = "<DOMAIN>";
var password = "<PASSWORD>";
var userName = "<USERNAME>";
//Only interested in specific systems so will scan only these
var directoriesToScan = new List<string> {
"$/projectdir/subdir/subdir/subdirA/systemnameA",
"$/projectdir/subdir/subdir/subdirB/systemnameB",
"$/projectdir/subdir/subdir/subdirC/systemnameC",
"$/projectdir/subdir/subdir/subdirD/systemnameD"
};
var maxResultsPerPath = 10;
var fromDate = DateTime.Now.AddDays(-120);
var toDate = DateTime.Now;
var fileExtensionToInclude = new List<string> { ".cs", ".js" };
var extensionExclusions = new List<string> { ".csproj", ".json", ".css" };
var fileExclusions = new List<string> { "AssemblyInfo.cs", "jquery-1.12.3.min.js", "config.js" };
var pathExclusions = new List<string> {
"/subdirToForceExclude1/",
"/subdirToForceExclude2/",
"/subdirToForceExclude3/",
};
using (var collection = new TfsTeamProjectCollection(new Uri(tfsUrl),
new NetworkCredential(userName: userName, password: password, domain: domain)))
{
collection.EnsureAuthenticated();
var tfvc = collection.GetService(typeof(VersionControlServer)) as VersionControlServer;
foreach (var rootDirectory in directoriesToScan)
{
//Get changesets
//Note: maxcount set to maxvalue since impact to server is minimized by linq query below
var changeSets = tfvc.QueryHistory(path: rootDirectory, version: VersionSpec.Latest,
deletionId: 0, recursion: RecursionType.Full, user: null,
versionFrom: new DateVersionSpec(fromDate), versionTo: new DateVersionSpec(toDate),
maxCount: int.MaxValue, includeChanges: true,
includeDownloadInfo: false, slotMode: true)
as IEnumerable<Changeset>;
//Filter changes contained in changesets
var changes = changeSets.SelectMany(a => a.Changes)
.Where(a => a.ChangeType != ChangeType.Lock || a.ChangeType != ChangeType.Delete || a.ChangeType != ChangeType.Property)
.Where(e => !e.Item.ServerItem.ContainsAny(pathExclusions))
.Where(e => !e.Item.ServerItem.Substring(e.Item.ServerItem.LastIndexOf('/') + 1).ContainsAny(fileExclusions))
.Where(e => !e.Item.ServerItem.Substring(e.Item.ServerItem.LastIndexOf('.')).ContainsAny(extensionExclusions))
.Where(e => e.Item.ServerItem.Substring(e.Item.ServerItem.LastIndexOf('.')).ContainsAny(fileExtensionToInclude))
.GroupBy(g => g.Item.ServerItem)
.Select(d => new { File=d.Key, Count=d.Count()})
.OrderByDescending(o => o.Count)
.Take(maxResultsPerPath);
//Write top items for each path to the console
Console.WriteLine(rootDirectory); Console.WriteLine("->");
foreach (var change in changes)
{
Console.WriteLine("ChangeCount: {0} : File: {1}", change.Count, change.File);
}
Console.WriteLine(Environment.NewLine);
}
}
}
OPTION 2A: REST API
(!! problem identified by OP led to finding a critical defect in v.xxx-14.95.4 of api) - OPTION 2B is the workaround
defect discovered in v.xxx to 14.95.4 of api: The TfvcChangesetSearchCriteria type contains an ItemPath property
which is supposed to limit the search to a specified directory. The
default value of this property is $/, unfortunately when used
GetChangesetsAsync will always use the root path of the tfvc source repository irrespective of the value set.
That said, this will still be a reasonable approach if the defect were to be fixed.
One way to limit the impact to your scm system would be to specify limiting criteria for the query/s using the TfvcChangesetSearchCriteria Type parameter of the GetChangesetsAsync member in the TfvcHttpClient type.
You do not particularly need to check each file in your scm system/project individually, checking the changesets for the specified period may be enough. Not all of the limiting values I used below are properties of the TfvcChangesetSearchCriteria type though so I've written a short example to show how I would do it i.e.
you can specify the maximum number of changesets to consider initially and the specific project you want to look at.
Note: The TheTfvcChangesetSearchCriteria type contains some additional properties that you may want to consider using.
In the example below I've used the REST API in a C# client and getting results from tfvc.
If your intention is to use a different client language and invoke the REST services directly e.g. JavaScript; the logic below should still give you some pointers.
//targeted framework for example: 4.5.2
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
public async Task GetTopChangedFilesUsingRestApi()
{
var tfsUrl = "https://<SERVERNAME>/tfs/<COLLECTION>";
var domain = "<DOMAIN>";
var password = "<PASSWORD>";
var userName = "<USERNAME>";
//Criteria used to limit results
var directoriesToScan = new List<string> {
"$/projectdir/subdir/subdir/subdirA/systemnameA",
"$/projectdir/subdir/subdir/subdirB/systemnameB",
"$/projectdir/subdir/subdir/subdirC/systemnameC",
"$/projectdir/subdir/subdir/subdirD/systemnameD"
};
var maxResultsPerPath = 10;
var fromDate = DateTime.Now.AddDays(-120);
var toDate = DateTime.Now;
var fileExtensionToInclude = new List<string> { ".cs", ".js" };
var folderPathsToInclude = new List<string> { "/subdirToForceInclude/" };
var extensionExclusions = new List<string> { ".csproj", ".json", ".css" };
var fileExclusions = new List<string> { "AssemblyInfo.cs", "jquery-1.12.3.min.js", "config.js" };
var pathExclusions = new List<string> {
"/subdirToForceExclude1/",
"/subdirToForceExclude2/",
"/subdirToForceExclude3/",
};
//Establish connection
VssConnection connection = new VssConnection(new Uri(tfsUrl),
new VssCredentials(new Microsoft.VisualStudio.Services.Common.WindowsCredential(new NetworkCredential(userName, password, domain))));
//Get tfvc client
var tfvcClient = await connection.GetClientAsync<TfvcHttpClient>();
foreach (var rootDirectory in directoriesToScan)
{
//Set up date-range criteria for query
var criteria = new TfvcChangesetSearchCriteria();
criteria.FromDate = fromDate.ToShortDateString();
criteria.ToDate = toDate.ToShortDateString();
criteria.ItemPath = rootDirectory;
//get change sets
var changeSets = await tfvcClient.GetChangesetsAsync(
maxChangeCount: int.MaxValue,
includeDetails: false,
includeWorkItems: false,
searchCriteria: criteria);
if (changeSets.Any())
{
var sample = new List<TfvcChange>();
Parallel.ForEach(changeSets, changeSet =>
{
sample.AddRange(tfvcClient.GetChangesetChangesAsync(changeSet.ChangesetId).Result);
});
//Filter changes contained in changesets
var changes = sample.Where(a => a.ChangeType != VersionControlChangeType.Lock || a.ChangeType != VersionControlChangeType.Delete || a.ChangeType != VersionControlChangeType.Property)
.Where(e => e.Item.Path.ContainsAny(folderPathsToInclude))
.Where(e => !e.Item.Path.ContainsAny(pathExclusions))
.Where(e => !e.Item.Path.Substring(e.Item.Path.LastIndexOf('/') + 1).ContainsAny(fileExclusions))
.Where(e => !e.Item.Path.Substring(e.Item.Path.LastIndexOf('.')).ContainsAny(extensionExclusions))
.Where(e => e.Item.Path.Substring(e.Item.Path.LastIndexOf('.')).ContainsAny(fileExtensionToInclude))
.GroupBy(g => g.Item.Path)
.Select(d => new { File = d.Key, Count = d.Count() })
.OrderByDescending(o => o.Count)
.Take(maxResultsPerPath);
//Write top items for each path to the console
Console.WriteLine(rootDirectory); Console.WriteLine("->");
foreach (var change in changes)
{
Console.WriteLine("ChangeCount: {0} : File: {1}", change.Count, change.File);
}
Console.WriteLine(Environment.NewLine);
}
}
}
OPTION 2B
Note: This solution is very similar to OPTION 2A with the exception of a workaround implemented to fix a limitation in the REST client API library at time of writing.
Brief summary - instead of invoking client api library to get changesets this example uses a web request direct to the REST API to fetch changesets, thus additional types were needed to be defined to handle the response from the service.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using System.Text;
using System.IO;
using Newtonsoft.Json;
public async Task GetTopChangedFilesUsingDirectWebRestApiSO()
{
var tfsUrl = "https://<SERVERNAME>/tfs/<COLLECTION>";
var domain = "<DOMAIN>";
var password = "<PASSWORD>";
var userName = "<USERNAME>";
var changesetsUrl = "{0}/_apis/tfvc/changesets?searchCriteria.itemPath={1}&searchCriteria.fromDate={2}&searchCriteria.toDate={3}&$top={4}&api-version=1.0";
//Criteria used to limit results
var directoriesToScan = new List<string> {
"$/projectdir/subdir/subdir/subdirA/systemnameA",
"$/projectdir/subdir/subdir/subdirB/systemnameB",
"$/projectdir/subdir/subdir/subdirC/systemnameC",
"$/projectdir/subdir/subdir/subdirD/systemnameD"
};
var maxResultsPerPath = 10;
var fromDate = DateTime.Now.AddDays(-120);
var toDate = DateTime.Now;
var fileExtensionToInclude = new List<string> { ".cs", ".js" };
var folderPathsToInclude = new List<string> { "/subdirToForceInclude/" };
var extensionExclusions = new List<string> { ".csproj", ".json", ".css" };
var fileExclusions = new List<string> { "AssemblyInfo.cs", "jquery-1.12.3.min.js", "config.js" };
var pathExclusions = new List<string> {
"/subdirToForceExclude1/",
"/subdirToForceExclude2/",
"/subdirToForceExclude3/",
};
//Get tfvc client
//Establish connection
VssConnection connection = new VssConnection(new Uri(tfsUrl),
new VssCredentials(new Microsoft.VisualStudio.Services.Common.WindowsCredential(new NetworkCredential(userName, password, domain))));
//Get tfvc client
var tfvcClient = await connection.GetClientAsync<TfvcHttpClient>();
foreach (var rootDirectory in directoriesToScan)
{
var changeSets = Invoke<GetChangeSetsResponse>("GET", string.Format(changesetsUrl, tfsUrl, rootDirectory,fromDate,toDate,maxResultsPerPath), userName, password, domain).value;
if (changeSets.Any())
{
//Get changes
var sample = new List<TfvcChange>();
foreach (var changeSet in changeSets)
{
sample.AddRange(tfvcClient.GetChangesetChangesAsync(changeSet.changesetId).Result);
}
//Filter changes
var changes = sample.Where(a => a.ChangeType != VersionControlChangeType.Lock || a.ChangeType != VersionControlChangeType.Delete || a.ChangeType != VersionControlChangeType.Property)
.Where(e => e.Item.Path.ContainsAny(folderPathsToInclude))
.Where(e => !e.Item.Path.ContainsAny(pathExclusions))
.Where(e => !e.Item.Path.Substring(e.Item.Path.LastIndexOf('/') + 1).ContainsAny(fileExclusions))
.Where(e => !e.Item.Path.Substring(e.Item.Path.LastIndexOf('.')).ContainsAny(extensionExclusions))
.Where(e => e.Item.Path.Substring(e.Item.Path.LastIndexOf('.')).ContainsAny(fileExtensionToInclude))
.GroupBy(g => g.Item.Path)
.Select(d => new { File = d.Key, Count = d.Count() })
.OrderByDescending(o => o.Count)
.Take(maxResultsPerPath);
//Write top items for each path to the console
Console.WriteLine(rootDirectory); Console.WriteLine("->");
foreach (var change in changes)
{
Console.WriteLine("ChangeCount: {0} : File: {1}", change.Count, change.File);
}
Console.WriteLine(Environment.NewLine);
}
}
}
private T Invoke<T>(string method, string url, string userName, string password, string domain)
{
var request = WebRequest.Create(url);
var httpRequest = request as HttpWebRequest;
if (httpRequest != null) httpRequest.UserAgent = "versionhistoryApp";
request.ContentType = "application/json";
request.Method = method;
request.Credentials = new NetworkCredential(userName, password, domain); //ntlm 401 challenge support
request.Headers[HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(domain+"\\"+userName + ":" + password)); //basic auth support if enabled on tfs instance
try
{
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream))
{
string s = reader.ReadToEnd();
return Deserialize<T>(s);
}
}
catch (WebException ex)
{
if (ex.Response == null)
throw;
using (var responseStream = ex.Response.GetResponseStream())
{
string message;
try
{
message = new StreamReader(responseStream).ReadToEnd();
}
catch
{
throw ex;
}
throw new Exception(message, ex);
}
}
}
public class GetChangeSetsResponse
{
public IEnumerable<Changeset> value { get; set; }
public class Changeset
{
public int changesetId { get; set; }
public string url { get; set; }
public DateTime createdDate { get; set; }
public string comment { get; set; }
}
}
public static T Deserialize<T>(string json)
{
T data = JsonConvert.DeserializeObject<T>(json);
return data;
}
}
Additional References:
C# REST and SOAP (ExtendedClient) api reference
REST API: tfvc Changesets
TfvcChangesetSearchCriteria type #MSDN

How to retrieve all the Groups/Roles a user is member of using SOAP services?

I am trying to collect some user informations using SOAP services.
I was able to get the Job Title for a given user, but I don't understand how to retrieve the list of groups and roles that a user has.
Can I simply use the GroupServiceSoap.getUserPlaces(long userId, String[] classNames, int max) method? Or is there another way I can get these fields?
Currently my code:
private static URL _getURL(String remoteUser, String password, String serviceName) {
final String LIFERAY_PROTOCOL = "http://";
final String LIFERAY_TCP_PORT = "8080";
final String LIFERAY_FQDN = "localhost";
final String LIFERAY_AXIS_PATH = "/api/secure/axis/";
try {
return new URL(LIFERAY_PROTOCOL + URLEncoder.encode(remoteUser, "UTF-8") + ":"
+ URLEncoder.encode(password, "UTF-8") + "#" + LIFERAY_FQDN
+ ":" + LIFERAY_TCP_PORT + LIFERAY_AXIS_PATH + serviceName);
} catch (MalformedURLException e) {
return null;
} catch (UnsupportedEncodingException e) {
return null;
}
}
[...]
public static void main(String[] argv){
public final String LIFERAY_USER_SERVICE="Portal_UserService";
public final String LIFERAY_COMPANY_SERVICE="Portal_CompanyService";
public final String LIFERAY_GROUP_SERVICE = "Portal_GroupService";
//company.default.web.id property
public final String LIFERAY_DEFAULT_COMPANY_ID = "liferay.com";
UserServiceSoap userService = new UserServiceSoapServiceLocator().getPortal_UserService(_getURL(USER_IDENTIFIER,USER_PASSWORD, LIFERAY_USER_SERVICE));
//This code is usefull if you want to use SOAP setter.
//((Portal_UserServiceSoapBindingStub) userService).setUsername(USER_IDENTIFIER);
//((Portal_UserServiceSoapBindingStub) userService).setPassword(USER_PASSWORD);
CompanyServiceSoap companyService = new CompanyServiceSoapServiceLocator().getPortal_CompanyService(_getURL(USER_IDENTIFIER, USER_PASSWORD, LIFERAY_COMPANY_SERVICE));
long companyId = companyService.getCompanyByMx(LIFERAY_DEFAULT_COMPANY_ID).getCompanyId();
// Here I retrieve my user, and can access some properties, but not them all !
UserSoap user = userService.getUserByEmailAddress(companyId, target_user_mail);
//TODO : I got hte JobTittle that I want, later I will do something more util thant just print it, I swear it my precious !
System.out.println(user.getJobTitle());
GroupServiceSoap groupService = new GroupServiceSoapServiceLocator().getPortal_GroupService(_getURL(USER_IDENTIFIER, USER_PASSWORD, LIFERAY_GROUP_SERVICE));
//this one return an empty array
GroupSoap[] userPlaces = groupService.getUserPlaces(new String[]{"Group", "Role"}, 150);
//this return an array of size 1, but the only GroupSoap seems to be a structural groups without any usefull properties to me.
GroupSoap[] userPlaces = groupService.getUserPlaces(null, 150);
}
Use this method to get user role and group user id
UserServiceSoap.getRoleUserIds
UserServiceSoap.getGroupUserIds
HTH
It is only a partial answer.
In order to get all the User Roles one can do this :
RoleServiceSoap roleService = new RoleServiceSoapServiceLocator().getPortal_RoleService(_getURL(USER_IDENTIFIER, USER_PASSWORD, LIFERAY_ROLE_SERVICE));
RoleSoap[] userRoles = roleService.getUserRoles(user.getUserId());
with user variable an instance of UserSoap.
The SOAP access must be done by an Admin user in order to get access to the Role List. The user can't access this himself.

List changed files in TFS but ordered by number of changes applied

Is there a way of listing all the files that have changed on a project, but ordered by the number of changes made to each file?
I want to do a code review but only from a selection of the most active files.
You may try to use Excel as a TFS reporting tool like in this blog post:
http://www.woodwardweb.com/vsts/getting_started.html
ps. I found that link in this question.
I searched different ways and finally I found that best way is using TFS API
here is the code :
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace VControl
{
class Program
{
class SourceElement
{
public string filename;
public int numberOfModification;
}
static void Main(string[] args)
{
TfsTeamProjectCollection projectCollection = new
TfsTeamProjectCollection(new Uri("http://server:8080/tfs/ProjectCollection/"),
new System.Net.NetworkCredential("username", "password"));
projectCollection.EnsureAuthenticated();
Workspace workspace = null;
Boolean createdWorkspace = false;
String newFolder = String.Empty;
VersionControlServer versionControl = projectCollection.GetService<VersionControlServer>();
var teamProjects = new List<TeamProject>(versionControl.GetAllTeamProjects(false));
String workspaceName = String.Format("{0}-{1}", Environment.MachineName, "TestWorkspace");
try
{
workspace = versionControl.GetWorkspace(workspaceName, versionControl.AuthorizedUser);
}
catch (WorkspaceNotFoundException)
{
workspace = versionControl.CreateWorkspace(workspaceName, versionControl.AuthorizedUser);
createdWorkspace = true;
}
var serverFolder = String.Format("$/{0}", teamProjects[0].Name) + "/solutionFolder/";
var localFolder = Path.Combine(Path.GetTempPath(), "localFolder") + "/solutionFolder/";
var workingFolder = new WorkingFolder(serverFolder, localFolder);
// Create a workspace mapping.
workspace.CreateMapping(workingFolder);
if (!workspace.HasReadPermission)
{
throw new SecurityException(
String.Format("{0} does not have read permission for {1}",
versionControl.AuthorizedUser, serverFolder));
}
// Get the files from the repository.
workspace.Get();
string[] directories = Directory.GetDirectories(workspace.Folders[0].LocalItem);
FileStream outputFile = new FileStream("result.txt", FileMode.Create);
StreamWriter writer = new StreamWriter(outputFile);
List<SourceElement> fileLiset = new List<SourceElement>();
foreach (string dir in directories)
{
foreach (string file in Directory.GetFiles(dir))
{
string filenamae = System.IO.Path.GetFileName(file);
Item source = versionControl.GetItem(file);
System.Collections.IEnumerable history = versionControl.QueryHistory(file,
VersionSpec.Latest, 0, RecursionType.Full, null, null, null, 300, true, true, false, false);
int numberOfModification = 0;
foreach (var item in history)
numberOfModification++;
SourceElement fileElement = new SourceElement();
fileElement.filename = filenamae;
fileElement.numberOfModification = numberOfModification;
fileLiset.Add(fileElement);
}
}
var sortedList = fileLiset.OrderBy(x=> x.numberOfModification);
// Loop through keys.
foreach (var key in sortedList)
{
writer.WriteLine("{0}: {1}", key.filename, key.numberOfModification);
}
writer.Close();
}
}
}

Entity Framework not populating Navigation property on savechanges

I am currently trying to build a web front end for a Report editor that allows the user to create different sections that are basically text fields. The first screen I allow the user to see causes them to populate some very minor initial data and I use it to spawn a new Report table record. I am using a t4 to generate my simple repositories:
public Entities.Result Add(ref Report entity) {
Entities.Result result;
try {
this.Context.Reports.AddObject(entity);
this.Context.SaveChanges();
result = new Entities.Result {
Success = true,
Messages = new List<Entities.ResultMessage>()
};
} catch (System.Exception ex) {
this.EventLogger.Error(ex);
List<Entities.ResultMessage> messages = new List<Entities.ResultMessage>();
messages.Add(new Entities.ResultMessage { Message = ex.ToString(), MessageSeverity = 10 });
result = new Entities.Result {
Success = false,
Messages = messages
};
}
return result;
}
and the same thing when they add a new section
public Entities.Result Add(ref ReportSection entity) {
Entities.Result result;
try {
this.Context.ReportSections.AddObject(entity);
this.Context.SaveChanges();
result = new Entities.Result {
Success = true,
Messages = new List<Entities.ResultMessage>()
};
} catch (System.Exception ex) {
this.EventLogger.Error(ex);
List<Entities.ResultMessage> messages = new List<Entities.ResultMessage>();
messages.Add(new Entities.ResultMessage { Message = ex.ToString(), MessageSeverity = 10 });
result = new Entities.Result {
Success = false,
Messages = messages
};
}
return result;
}
I call this from the Index controller in the form of:
Report newReport = new Report() {
ApprovalDate = null,
Approver = string.Empty,
Author = System.Web.Security.Membership.GetUser().UserName,
Created = DateTime.Now,
IsActive = true,
IsSubmitted = false,
ReleaseDate = null,
SerialNumber1 = string.Empty,
SerialNumber2 = string.Empty
};
var result = this._reportRepository.Add(ref newReport);
this goes through just fine and I get the record in the database. I then take some of their entries a populate an initial ReportSection object like so:
var newSection = new ReportSection {
DisplayOrder = 1,
ReportId = newReport.Id,
ReportSectionTypeId = 1,
SectionText = title
};
var r = this._reportSectionRepository.Add(ref newSection);
You'll notice I'm referring to the newReport.Id in there so I have the valid ID returned from the repository add method. The section add method returns to me a valid newSection object that has a valid ID and when I check in the db it exists. However, EF is not populating the navigational property on newSection.Report that lets me get between the two. This is what I'm trying to figure out, why is this not accessible? I have a temporary work around that defeats some of my DAL validation logic, but I can load the Report object then add the ReportSection through Report.ReportSections and then call an update method on the repo that does an ApplyCurrentValues.
A bit more detail:
Visual Studio 2010
C# .Net 4.0
MVC 2.0
EF 4.0 ( or maybe 4.1 )
I am using Ninject to fill in the repositories:
Bind<IReportRepository>().To<ReportRepository>().WithConstructorArgument("connectionString",
ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString);
You could directly set the navigation property instead of the foreign key property:
var newSection = new ReportSection {
DisplayOrder = 1,
Report = newReport,
ReportSectionTypeId = 1,
SectionText = title
};
If the context in _reportRepository and _reportSectionRepository are the same and newReport is still attached to it that's all you need to do.
If the contexts are not the same or newReport is not attached to the context, you must attach newReport first to the context:
public Entities.Result Add(ref ReportSection entity) {
Entities.Result result;
try {
this.Context.Reports.Attach(entity.Report);
this.Context.ReportSections.AddObject(entity);
this.Context.SaveChanges();
// etc.