C# TFS SDK Get Items from changeset - c#

I want to get the Content from an item from a specific Changeset. With my code, I get the correct number of items, but every property of the item is empty, only the correct URL is filled up. All other properties are set to null.
How can I solve this?
string collectionUri = #"https://tfs.myServer.de/MyProject";
using (TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri(collectionUri)))
{
TfvcHttpClient tfvcClient = tpc.GetClient<TfvcHttpClient>();
var changedItems = tfvcClient.GetChangesetAsync(125453).Result;
IEnumerable<TfvcChange> changesetChanges=tfvcClient.GetChangesetChangesAsync(changedItems.ChangesetId).Result;
foreach (var itemsChange in changesetChanges)
{
Console.WriteLine(itemsChange.NewContent.Content);
}
}

This gets you the contents of the items of a changeset
private static async Task ReadContent(TfvcHttpClient tfvcClient)
{
var changesetId = 123456;
var changesetChanges = await tfvcClient.GetChangesetChangesAsync(changesetId);
var tfvcVersionDescriptor = new TfvcVersionDescriptor(null, TfvcVersionType.Changeset, changesetId.ToString());
foreach (var changesetChange in changesetChanges)
{
var path = changesetChange.Item.Path;
Stream contentStream = await tfvcClient.GetItemContentAsync(path, versionDescriptor: tfvcVersionDescriptor);
using (StreamReader streamReader = new StreamReader(contentStream))
{
var content = streamReader.ReadToEnd();
}
}
}

Related

System.ObjectDisposedException: 'Cannot read from a closed TextReader.'

For my homework I have to make a XAML project using a csv file to show pictures of zoo animals along with other info which is included in the code.
It's almost done but when I run the program it gives me this error:
System.ObjectDisposedException: 'Cannot read from a closed TextReader.'
private async void Button_Click(object sender, RoutedEventArgs e)
{
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.FileTypeFilter.Add(".csv");
var file = await picker.PickSingleFileAsync();
if (file == null)
{
tbFileStatus.Text = "(not a valid file chosen)";
return;
}
tbFileStatus.Text = file.Path;
using (var fileAccess = await file.OpenReadAsync())
{
using (var stream = fileAccess.AsStreamForRead())
{
using (var reader = new StreamReader(stream))
{
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var lvAnimals = csv.GetRecords<Animal>();
}
while (!reader.EndOfStream)
{
var row = reader.ReadLine();
var parts = row.Split(',');
var number = (parts[0]);
var name = parts[1];
var species = parts[2];
var latin_name = parts[3];
var cage = parts[4];
var picture = parts[5];
var llvAnimals = new Animal
{
Number = number,
Name = name,
Species = species,
Latin_Name = latin_name,
Cage = cage,
Picture = picture
};
lvAnimals.ItemsSource = llvAnimals;
}
}
}
}
}
You are passing your StreamReader to the CsvReader.
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
...
}
while (!reader.EndOfStream)
...
By making use of using, you are disposing the CsvReader after its usage. Keep in mind, that some implementations like this also disposing their readers. This can be seen in the corresponding implementation. This means, the passed StreamReader gets also closed and can't be used afterwards. This causes the System.ObjectDisposedException.
To solve this, extend the usage scope like this:
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
...
while (!reader.EndOfStream)
...
}

csvhelper: how to write a specific "cell" on an existing csv on C#?

I have a customer list in csv format which I'm using to send out emails. I would like to write to the CSV after each row has been executed in order to place a conditional rule. I'm using csvhelper to manipulate the file. Here's the code:
var scan = new StreamReader(myBlob);
var csvv = new CsvReader(scan, CultureInfo.InvariantCulture);
var records = csvv.GetRecords<Records>().ToList();
var scanwriter = new StreamWriter(myBlob4);
var csvwriter = new CsvWriter(scanwriter, CultureInfo.InvariantCulture);
foreach (Records record in records)
{
var from = new EmailAddress("example.com", "John");
var to = new EmailAddress(record.Email, record.Name);
var subject = "exapmple";
var msg = MailHelper.CreateSingleEmail(from, to, subject, txtf, htmlf);
StringBuilder text = new StringBuilder();
text.AppendFormat("sent", record.EmailSent);
csvwriter.WriteField(record.EmailSent);
csvwriter.NextRecord();
var response = await client.SendEmailAsync(msg);
}
However my csv is not appending the "sent" value to the file under the emailsent column. I'm using StringBuilder which might not be helpful in this scenario.
It seems like you are trying to do something more like this.
void Main()
{
var records = new List<SendEmail>
{
new SendEmail{ Email = "example.com", Name = "John" },
new SendEmail{ Email = "example2.com", Name = "Jenny" }
};
var csvwriter = new CsvWriter(Console.Out, CultureInfo.InvariantCulture);
foreach (var record in records)
{
// var from = new EmailAddress("example.com", "John");
// var to = new EmailAddress(record.Email, record.Name);
//
// var subject = "exapmple";
//
// var msg = MailHelper.CreateSingleEmail(from, to, subject, txtf, htmlf);
record.EmailSent = "sent";
csvwriter.WriteRecord(record);
csvwriter.NextRecord();
//var response = await client.SendEmailAsync(msg);
}
}
public class SendEmail
{
public string Email { get; set; }
public string Name { get; set; }
public string EmailSent { get; set; }
}
//using blocks will make sure the streams and disposed and file handles are closed properly,
// **even if an exception is thrown **
using(var scan = new StreamReader(myBlob))
using (var csvv = new CsvReader(scan, CultureInfo.InvariantCulture))
using (var scanwriter = new StreamWriter(myBlob4))
using (var csvwriter = new CsvWriter(scanwriter, CultureInfo.InvariantCulture))
{
var records = csvv.GetRecords<Records>(); //ToList() was not needed or helpful here
foreach (var record in records)
{
var from = new EmailAddress("example.com", "John");
var to = new EmailAddress(record.Email, record.Name);
var subject = "example";
var msg = MailHelper.CreateSingleEmail(from, to, subject, txtf, htmlf);
csvwriter.WriteField($"sent {record.EmailSent}");
csvwriter.NextRecord();
var response = await client.SendEmailAsync(msg);
}
}

Add and remove Ektron content items from taxonomies? (C#)

I have content items stored in Ektron that are assigned to taxonomies. I'm trying to create a method that will allow me to programmatically change the taxonomies. So far I find the content item by ID, and I'm able to retrieve its taxonomies, but I'm not sure how to change them.
var ektronItem = contentManager.GetItem((long) item.tctmd_id);
if (ektronItem != null) // item exists in Ektron
{
var newTaxonomies = item.taxonomy_ids;
var taxonomyAPI = new Taxonomy();
var taxData = taxonomyAPI.ReadAllAssignedCategory(ektronItem.Id);
foreach (var tax in taxData)
{
taxonomyAPI.RemoveTaxonomyItem(???);
// here I'm trying to remove the content item from the taxonomy
}
}
taxonomyAPI.RemoveTaxonomyItem() takes a Ektron.Cms.TaxonomyRequest object, but I'm not sure how to create this. I'm also not sure if this is even the method I should be using.
In case anyone else wants to know how to do this, here's the solution I came up with:
var contentManager = new Ektron.Cms.Framework.Content.ContentManager();
var criteria = new Ektron.Cms.Content.ContentCriteria(ContentProperty.Id, EkEnumeration.OrderByDirection.Ascending);
criteria.AddFilter(ContentProperty.FolderId, CriteriaFilterOperator.EqualTo, toUpdate.folder_id);
criteria.OrderByDirection = Ektron.Cms.Common.EkEnumeration.OrderByDirection.Descending;
criteria.OrderByField = Ektron.Cms.Common.ContentProperty.GoLiveDate;
criteria.FolderRecursive = true;
criteria.PagingInfo = new Ektron.Cms.PagingInfo(50, 1);
var ektronItem = contentManager.GetItem((long) item.tctmd_id);
if (ektronItem != null) // item exists in Ektron
{
// update taxonomy in Ektron
var taxIds = item.taxonomy_ids;
var taxonomyAPI = new Taxonomy();
var taxData = taxonomyAPI.ReadAllAssignedCategory(ektronItem.Id);
var taxManager = new Ektron.Cms.Framework.Organization.TaxonomyItemManager();
var taxCriteria = new TaxonomyItemCriteria();
// create a taxonomy criteria of the item ID
taxCriteria.AddFilter(TaxonomyItemProperty.ItemId, CriteriaFilterOperator.EqualTo, item.tctmd_id);
// get all taxonomy items with item ID
var taxItems = taxManager.GetList(taxCriteria);
// determine taxonomyItemType
var type = taxItems.FirstOrDefault().ItemType;
foreach (var tax in taxData)
{
// delete from old taxonomies
taxManager.Delete(tax.Id, (long)item.tctmd_id, type);
}
foreach (var tax in taxIds)
{
// add to new taxonomies
var taxonomyItemData = new TaxonomyItemData()
{
TaxonomyId = tax,
ItemType = type,
ItemId = (long)item.tctmd_id
};
try
{
taxManager.Add(taxonomyItemData);
}
catch (Exception ex)
{
}
}
}

Reading existing field value from SharePoint Custom List fails

I am trying to read the value of a particular field in a SharePoint Custom List.
The Custom List has the following fields: Field1, Field2 and Field3
When I call the code below:
public static string GetLastTargetColumnValue(string sharePointSiteUrl, string sharePointListName, string targetColumnName)
{
string targetColumnValue = string.Empty;
using (var clientContext = new ClientContext(sharePointSiteUrl))
{
clientContext.Credentials = new NetworkCredential("userName", "password");
var list = clientContext.Web.Lists.GetByTitle(sharePointListName);
var query = CamlQuery.CreateAllItemsQuery(100);
var items = list.GetItems(query);
clientContext.Load(items);
clientContext.ExecuteQuery();
var listItem = items.Last();
foreach (var fieldValue in listItem.FieldValues)
{
Console.WriteLine(fieldValue.Key + ":" + fieldValue.Value + Environment.NewLine);
}
}
targetColumnValue = listItem[targetColumnName] as string;
return targetColumnValue;
}
The error message is:
Additional information: The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
The fields which are displayed in the foreach show "Field1" and "Field2". Do I have to explicitly request "Field3". If yes how?
I had to get the internal name before querying the value for some reason. Here is the code that worked:
public static string GetLastTargetColumnValue(string sharePointSiteUrl, string sharePointListName, string targetColumnName)
{
string targetColumnValue = string.Empty;
using (var clientContext = new ClientContext(sharePointSiteUrl))
{
clientContext.Credentials = new NetworkCredential("userName", "password");
var list = clientContext.Web.Lists.GetByTitle(sharePointListName);
var field = list.Fields.GetByInternalNameOrTitle(targetColumnName);
var textField = clientContext.CastTo<FieldText>(field);
var query = CamlQuery.CreateAllItemsQuery(100);
var items = list.GetItems(query);
clientContext.Load(textField);
clientContext.Load(items);
clientContext.ExecuteQuery();
var listItem = items.Last();
targetColumnValue = listItem[textField.InternalName] as string;
}
return targetColumnValue;
}

Creating a blank document in a document library using client object model

I'm creating a function where you can provide a content type name and target either a list or document library and create a default item. Im using the client object model for office 2013
public void MyFunction()
{
//clientContext must be authenticated already on your sharepoint site
var listName = "Default Document Set";
var docSetContentTypeName = "Document";
var newDocSetName = string.Format("Item {0}", Guid.NewGuid());
Web web = clientContext.Web;
List list = clientContext.Web.Lists.GetByTitle(listName);
clientContext.Load(clientContext.Site);
ContentTypeCollection listContentTypes = list.ContentTypes;
clientContext.Load(listContentTypes, types => types.Include
(type => type.Id, type => type.Name,
type => type.Parent));
var result = clientContext.LoadQuery(listContentTypes.Where
(c => c.Name == docSetContentTypeName));
clientContext.ExecuteQuery();
ContentType targetDocumentSetContentType = result.FirstOrDefault();
ListItemCreationInformation newItemInfo = new ListItemCreationInformation();
newItemInfo.UnderlyingObjectType = FileSystemObjectType.Folder;
newItemInfo.LeafName = newDocSetName;
ListItem newListItem = list.AddItem(newItemInfo);
newListItem["ContentTypeId"] = targetDocumentSetContentType.Id.ToString();
newListItem["Title"] = newDocSetName;
newListItem.Update();
clientContext.Load(list);
clientContext.ExecuteQuery();
}
The function works fine on ContentTypes like Item and Document Set but when I use Document, it creates an item with a content type "Document" but it has an icon of folder and acts like a folder.
Is there something I need to add?
Thanks in advance.
FileSystemObjectType.Folder is used for creating a Folder object and therefore could not be specified for creating File object. At the same time List.AddItem Method could not be used for creating a File object.
You could consider the following example that demonstrates how to create(upload) a file into Documents library:
public static void UploadFile(List list,string filePath,IDictionary<string,object> itemProperties)
{
var ctx = list.Context;
var fileInfo = new FileCreationInformation();
fileInfo.Url = Path.GetFileName(filePath);
fileInfo.Overwrite = true;
fileInfo.Content = System.IO.File.ReadAllBytes(filePath);
var file = list.RootFolder.Files.Add(fileInfo);
var listItem = file.ListItemAllFields;
foreach (var p in itemProperties)
{
listItem[p.Key] = p.Value;
}
listItem.Update();
ctx.ExecuteQuery();
}
Using Open XML SDK 2.0 for Microsoft Office you could create an empty document and upload it into Documents library:
public static void CreateAndUploadFile(List list, string filePath, IDictionary<string, object> itemProperties)
{
using (var document = WordprocessingDocument.Create(filePath, WordprocessingDocumentType.Document))
{
var mainPart = document.AddMainDocumentPart();
mainPart.Document = new Document(new Body());
}
UploadFile(list, filePath, itemProperties);
}
Usage:
var list = web.Lists.GetByTitle(listTitle);
var itemProperties = new Dictionary<string,object>();
itemProperties["Title"] = "SharePoint User Guide";
CreateAndUploadFile(list, "./SharePoint User Guide.docx", itemProperties);

Categories

Resources