I am getting a PropertyException on the 2nd part of this code. The 1st part uploads the file as expected. After the context.ExecuteQuery(); I am then getting:
'uploadedFile.CheckInComment' threw an exception of type
'Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException'
I am not sure why as the context should be OKsince it did upload the file.
I am going to try to update some meta data fields on the document I just uploaded.
Folder currentRunFolder = site.GetFolderByServerRelativeUrl(barRootFolderRelativeUrl + "/");
FileCreationInformation newFile = new FileCreationInformation
{
Content = System.IO.File.ReadAllBytes(#p),
Url = Path.GetFileName(#p),
Overwrite = true
};
currentRunFolder.Files.Add(newFile);
currentRunFolder.Update();
context.ExecuteQuery();
newUrl = siteUrl + barRootFolderRelativeUrl + "/" + Path.GetFileName(#p);
// Set document properties
Microsoft.SharePoint.Client.File uploadedFile = context.Web.GetFileByServerRelativeUrl(newUrl);
ListItem listItem = uploadedFile.ListItemAllFields;
listItem["TestEQCode"] = "387074";
listItem.Update();
context.ExecuteQuery();
Could you try this.
currentRunFolder.Files.Add(newFile);
//currentRunFolder.Update();
context.Load(newFile);
context.ExecuteQuery();
//newUrl = siteUrl + barRootFolderRelativeUrl + "/" + Path.GetFileName(#p);
// Set document properties
//Microsoft.SharePoint.Client.File uploadedFile = context.Web.GetFileByServerRelativeUrl(newUrl);
ListItem listItem = newFile.ListItemAllFields;
listItem["TestEQCode"] = "387074";
listItem.Update();
context.ExecuteQuery();
Ok so eventhough the ListItems is NULL I can set the TestEQCode and update and the field is getting updated on the SharePoint side. This whole time I was concerned on the ListItems getting the actual meta data list, but really it doesn't need that. I just will have to Hard Code those items and it will update. –
Related
I got stuck in a situation. I uploaded a file in Sharepoint programmatically in C# using the CSOM library,
FileCreationInformation newfile = new FileCreationInformation();
byte[] FileContent = dstStream.ToArray();
newfile.ContentStream = new MemoryStream(FileContent);
newfile.Url = strfilename;
Microsoft.SharePoint.Client.File uploadfile = destiFolder.Files.Add(newfile);
context.Load(uploadfile);
context.ExecuteQuery();
I used above mentioned approach to upload a file in a particular folder.
Now the thing is I need to update that file's 'Created By'/'Modified By' field with another Username.
So can anybody help me out of this ?
You can update list item field values
// checkout
uploadfile.CheckOut();
// get list item field values
ListItem item = uploadfile.ListItemAllFields;
// ensure User object, specify the correct login name
User anotherUser = context.Web.EnsureUser("Contoso\\JohnDoe");
context.Load(anotherUser);
context.ExecuteQuery();
// update Author and Editor field
item["Editor"] = anotherUser;
item["Author"] = anotherUser;
// update item
item.Update();
// checkin
uploadfile.CheckIn(string.Empty, CheckinType.OverwriteCheckIn);
context.ExecuteQuery();
I'm new in this theme but I search a lot I mean really lot before I asked it here. So my problem is that, when I create ListItem in my app and set the Fields that are required, everything looks all right. I can see the ListItem in my List with proper fields if I go to Sharepoint Online. But when I click on the ListItem the Fields are empty and on the top of the page is an error which says "Object reference not set to an instance of an object." I don't know if the issue is happening cos of my code or there is an issue with Sharepoint settings? I followed most of the guides here to go as far as I'm now. My code below.
SP.List targetList = ctx.Web.Lists.GetByTitle("Documents");
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
ListItem newListItem = targetList.AddItem(itemCreateInfo);
newListItem["Title"] = "Test_title";
newListItem["EAN_x0020_k_x00f3_d"] = "AnotherCodeWhichIsRequired";
newListItem.Update();
string strFilePath = #"PathToMyPDF";
byte[] bytes = System.IO.File.ReadAllBytes(strFilePath);
using (System.IO.MemoryStream mStream = new System.IO.MemoryStream(bytes))
{
SP.AttachmentCreationInformation aci = new SP.AttachmentCreationInformation();
aci.ContentStream = mStream;
aci.FileName = System.IO.Path.GetFileNameWithoutExtension(strFilePath);
newListItem.AttachmentFiles.Add(aci);
newListItem.Update();
ctx.ExecuteQuery();
}
It looks like you are using a document library.The code that you have used is for a sharepoint list.
To upload a file to document library and update its properties, modify your code as below:
string strFilePath = #"PathToMyPDF";
FileCreationInformation newFile = new FileCreationInformation();
newFile.Content = System.IO.File.ReadAllBytes(strFilePath);
newFile.Overwrite = true;
SP.List targetList = ctx.Web.Lists.GetByTitle("Documents");
Microsoft.SharePoint.Client.File uploadFile = targetList.RootFolder.Files.Add(newFile);
ctx.Load(uploadFile);
ctx.ExecuteQuery();
uploadFile.ListItemAllFields["Title"] = "Test_title";
uploadFile.ListItemAllFields["EAN_x0020_k_x00f3_d"] = "AnotherCodeWhichIsRequired";
uploadFile.ListItemAllFields.Update();
ctx.ExecuteQuery();
I'm displaying files from a Sharepoint 2010 document library on my web page. I'm successfully showing a list of the files and their icons. However, some of the files are in subfolders, and instead of showing the file icon, I'd like to show a folder icon.
How do I detect when a file is in a subfolder?
I could parse each file's ServerRelativeUrl to determine the folder structure. I'm hoping there is another way.
Here is the Sharepoint library:
And here is the code which produces the list of files in that library:
using (ClientContext clientContext = new ClientContext(SharepointSite))
{
var query = new CamlQuery
{
ViewXml = "<View Scope='RecursiveAll'>" +
"<Query>" +
"<Where>" +
"<Eq>" +
"<FieldRef Name='FSObjType' />" +
"<Value Type='Integer'>0</Value>" +
"</Eq>" +
"</Where>" +
"</Query>" +
"</View>"
};
var sourceList = clientContext.Web.Lists.GetByTitle("Test Library");
var files = sourceList.GetItems(query);
clientContext.Load(files);
clientContext.ExecuteQuery();
foreach (var file in files)
{
var id = file.Id;
var filename = file["FileLeafRef"].ToString();
var iconName = clientContext.Web.MapToIcon(filename, string.Empty, IconSize.Size16);
clientContext.ExecuteQuery();
var imgUrl = "http://sharepointsite/_layouts/images/" + iconName.Value;
Image iconImage = new Image {ImageUrl = imgUrl};
clientContext.Load(file.ParentList);
clientContext.ExecuteQuery();
var listUrl = file.ParentList.DefaultDisplayFormUrl;
HyperLink docLink = new HyperLink
{
Text = filename,
NavigateUrl = listUrl + "?ID=" + id //ToDo: fix
};
HtmlTableRow row = new HtmlTableRow();
HtmlTableCell cell1 = new HtmlTableCell();
cell1.Controls.Add(iconImage);
HtmlTableCell cell2 = new HtmlTableCell();
cell2.Controls.Add(docLink);
row.Cells.Add(cell1);
row.Cells.Add(cell2);
tbFiles.Rows.Add(row);
}
}
which results in:
Only the first file in the list is actually in the top-most library. The rest are in "Test Folder".
It might helpful to understand the available options for the view scope property of your CAML query:
Default: Gets files and subfolders from a specific folder
RecursiveAll: Gets files and subfolders from all folders
FilesOnly: Gets only files (no folders) from a specific folder
Recursive: Gets only files (no folders) from all folders
If you want to maintain a hierarchical folder structure, you have two options:
Get all files in the library (using a view scope of Recursive or RecursiveAll) and try to reconstruct the file structure yourself by post-processing the results
Get only files and folders from one folder at a time (using a view scope of Default), executing a new query whenever you want to drill down into the contents of a subfolder
Both approaches are equally valid, but in general I'd recommend the second. They both have their downsides: the first requires a larger up-front network request and more post-processing logic to assemble the hierarchy, while the second requires multiple network requests to retrieve all the data.
If taking the second approach, you can limit your CAML query to a specific folder by setting the CamlQuery's FolderServerRelativeUrl property to the URL of the desired folder. When working with the items retrieved from a specific folder, you can check their FileSystemObjectType property to determine if they are files or folders; if they are folders you can access their Folder property to get the associated folder object, from which you can get the ServerRelativeUrl property to use in your next query to get items from that folder.
I've this folder and I want to get a specific file from it, how can I do that given that there could be more than one file in there.
I've tried to use StartsWith but wasn't able to do so, is there any way this could be done?
The file is in the CustomerWorkSheet folder and its name starts with the customer id field value. What should I use if I have this path: .../uploads/attachments/CustomerWorkSheet/**File Name Here**
IWordDocument doc = new WordDocument();
doc.Open(
System.Web.HttpContext.Current.Server.MapPath
("~/Content/uploads/attachments/CustomerWorkSheet/"),
FormatType.Doc);
I need some thing like that
if(file.StartsWith(customerId))
but couldn't get the file
var directoryPath = System.Web.HttpContext.Current.Server.MapPath("~/Content/uploads/attachments/CustomerWorkSheet");
var file = Directory.EnumerateFiles(directoryPath).SingleOrDefault(f => f.Contains("CustomerWorkSheet/" + myCustomerId));
if(file != null){
IWordDocument doc = new WordDocument();
doc.open(file, FormatType.Doc);
}
Based on your comments, you are looking for this:
var filename = myDirectoryFiles.SingleOrDefault(f => f.Contains("CustomerWorkSheet/" + myCustomerId + "."));
I have to upload some XML files to a SharePoint library. I have to do it from a computer that is not one of the SharePoint servers (so object model will not work). Also the library has a custom (integer) column and I have to set it's value for the uploaded file.
How do I upload the file and the the value by using the standard WebServices of SharePoint 2010?
I now solved it by using the Client Object Model (as Doug suggested). Uploading a file using the COM is pretty simple:
public void UploadXmlFile(string xmlContent, int orderNumber)
{
string filename = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + "_" + orderNumber + ".xml";
ClientContext context = new ClientContext(absoluteHostUrl + relativeWebUrl);
using (MemoryStream stream = new MemoryStream())
{
// use a MemoryStream for the file contents
StreamWriter writer = new StreamWriter(stream);
writer.Write(xmlContent);
writer.Flush();
stream.Position = 0;
// ... and upload it.
Microsoft.SharePoint.Client.File.SaveBinaryDirect(
context,
"/" + relativeWebUrl + "Lists/" + libraryName + "/" + filename,
stream,
false);
}
// ...
... but after uploading the file is checked-out, and I still have to set my integer column:
// ...
// get the created entry
Web web = context.Web;
List list = web.Lists.GetByTitle(libraryName);
ListItemCollection itemCol = list.GetItems(new CamlQuery() { ViewXml = "<View/>" });
context.Load(itemCol,
items => items
.Include(i => i[COLUMN_IMPORTORDERNUMBER])
.Where(i => (string)i[COLUMN_FILELEAFREF] == filename)
.Take(1)
);
context.ExecuteQuery();
// ... found it? ...
if (itemCol != null && itemCol.Count > 0)
{
ListItem item = itemCol[0];
// ... set the ImportOrderNumber
item[COLUMN_IMPORTORDERNUMBER] = orderNumber;
item.Update();
// ... and check in
item.File.CheckIn("Checked in by WebService", CheckinType.MajorCheckIn);
context.ExecuteQuery();
}
}
I haven't used it yet, but the Client Object Model may be a good choice for this.
Could you use something as simple as email to a list, and have the item created from that?