I'm trying to upload files to a folder using SharePoint and C#.
I managed to create folders with my code and it works fine.
This is my Document class:
[DataContractAttribute]
public class Document
{
[DataMemberAttribute]
public string Name { get; set; }
[DataMemberAttribute]
public byte[] Content { get; set; }
[DataMemberAttribute]
public bool ReplaceExisting { get; set; }
[DataMemberAttribute]
public string Folder { get; set; }
[DataMemberAttribute]
public Dictionary<string, object> Properties { get; set; }
public Document()
{
Properties = new Dictionary<string, object>();
}
public Document(string name, byte[] content)
{
Name = name;
ReplaceExisting = false;
Content = content;
Properties = new Dictionary<string, object>();
}
public Document(string name, byte[] content, bool replace)
{
Name = name;
Content = content;
ReplaceExisting = replace;
Properties = new Dictionary<string, object>();
}
}
And this is the class where I use it to upload files (Document) to an existing share point folder:
public class SharePointHandler : IDisposable
{
private static string sharePointSite = "My Site";
private static string documentLibraryName = "Root folder";
public SharePointHandler() { }
public void Upload(List<Document> documents, string company, int year, string quarter)
{
string Year = year.ToString();
try
{
using (ClientContext context = new ClientContext(sharePointSite))
{
var list = context.Web.Lists.GetByTitle(documentLibraryName);
context.Load(list);
var root = list.RootFolder;
context.Load(root);
context.ExecuteQuery();
.
.
.
foreach (var document in documents)
{
var fileCreationInformation = new FileCreationInformation();
fileCreationInformation.Content = document.Content;
fileCreationInformation.Overwrite = true;
fileCreationInformation.Url = list.RootFolder.ServerRelativeUrl + "/" + company + "/" + Year + "/" + quarter + "/" + document.Name;
Microsoft.SharePoint.Client.File uploadFile = quarterFolder.Files.Add(fileCreationInformation);
foreach (KeyValuePair<string, object> property in document.Properties)
uploadFile.ListItemAllFields[property.Key] = property.Value;
try
{
uploadFile.CheckOut();
context.ExecuteQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
uploadFile.ListItemAllFields.Update();
context.ExecuteQuery();
uploadFile.CheckIn("", CheckinType.MajorCheckIn);
context.ExecuteQuery();
}
}
}
catch (Exception ex)
{
EventLog.WriteEntry(ex.Message, EventLogEntryType.Error);
return;
}
}
public void Dispose() { }
}
When I run the code I have one document with:
Content: {byte[11430]}
Folder: null
Name: Testing.docx
Properties: Count = 0
ReplaceExisting: false
Everything works fine and I get the URL needed.
But when I get to these commands:
try
{
uploadFile.CheckOut();
context.ExecuteQuery();
}
The program falls and I get error that says: File not found.
What am I doing wrong?
Thank you for your help!
Here is a working example of an upload to SharePoint via CSOM:
using (ClientContext conext = new ClientContext(site.url))
{
List projectFiles = projects.Web.Lists.GetByTitle("Project Files");
context.Load(projectFiles.RootFolder, w => w.ServerRelativeUrl);
context.ExecuteQuery();
FileStream documentStream = System.IO.File.OpenRead(filePath);
byte[] info = new byte[documentStream.Length];
documentStream.Read(info, 0, (int)documentStream.Length);
string fileURL = projectFiles.RootFolder.ServerRelativeUrl + "/Folder/FileName.ext";
FileCreationInformation fileCreationInformation = new FileCreationInformation();
fileCreationInformation.Overwrite = true;
fileCreationInformation.Content = info;
fileCreationInformation.Url = fileURL;
Microsoft.SharePoint.Client.File uploadFile = projectFiles.RootFolder.Files.Add(fileCreationInformation);
context.Load(uploadFile, w => w.MajorVersion, w => w.MinorVersion);
context.ExecuteQuery();
}
In your case, I would upload the file and ExecuteQuery() and then add your metadata and execute a second query, make sure you add a context.Load after your files.Add(). You are trying to do too many things at once, so just use this code to get the file uploaded and work your way through your other needs after. Also, the file add will not create folders for you so make sure you are specifying a valid path.
Related
I am using Selenium for automation purpose. I have a class for screenshot and Page Object method to call all my element in different class for every page. Now I am calling get screenshot of page in every class. But here is the think how to do I create a folder name get the screenshot in that folder.
Result.cs
class Result
{
static int i = 1;
public static void screenshot()
{
ITakesScreenshot screenshotDriver = myCollection.driver as ITakesScreenshot;
Screenshot screenCapture = screenshotDriver.GetScreenshot();
string path = #"..\..\..\Results\ScreenShots\";
string timestamp = DateTime.Now.ToString("yy-MM-dd hh-mm-ss");
{
screenCapture.SaveAsFile(#path + i + timestamp + ".png", System.Drawing.Imaging.ImageFormat.Png);
i++;
}
}
}
LoginPageObject.cs
[FindsBy(How = How.Name, Using = "txtusername")]
public IWebElement userName { get; set;}
[FindsBy(How = How.Name, Using = "Password")]
public IWebElement pwd { get; set; }
[FindsBy(How = How.ClassName, Using = "login_button")]
public void Login(string uname, string paswd)
{
userName.EnterText(uname);
pwd.EnterText(paswd);
clickLogin.Click();
Result.screenshot();
Thread.Sleep(4000);
}
Same for HomePageObject
main.cs
[Test]
public void Initialize()
{
myCollection.driver = new TWebDriver();
LoginPageObject objLogin = new LoginPageObject();
string pathfile = #"..\..\a.xlsx";
string sheetName = "Common";
var excelFile = new ExcelQueryFactory(pathfile);
var abc = from a in excelFile.Worksheet(sheetName) select a;
foreach (var a in abc)
{
myCollection.driver.Navigate().GoToUrl(a["URL"]);
}
myCollection.driver.Manage().Window.Maximize();
foreach (var a in abc)
{
objLogin.Login(a["uname"], a["paswd"]);
}
HomePagePbject objHome = new HomePageObject();
objHome.HomeFunction();
}
Here my main function is Initialize. So now how would I add all screenshots to that folder. For Now, I am adding it to screenshot folder.
You can write something like it: Create a folter to Logs and after append a screenshot folder inside it. If the folder does not exist, create it.
Using NUnit (but you can do the same with a similar sintax in VisualStudio.TestTools):
public void SaveScreenShot(string screenshotFirstName)
{
var folderLocation = ConfigurationManager.AppSettings["LogPath"] +"\\ScreenShot\\";
if (!Directory.Exists(folderLocation))
Directory.CreateDirectory(folderLocation);
var screenshot = ((ITakesScreenshot) _driver).GetScreenshot();
var image = ScreenshotToImage(screenshot);
var filename = new StringBuilder(folderLocation);
filename.Append(screenshotFirstName);
filename.Append(".png");
image.Save(filename.ToString(), ImageFormat.Png);
}
private static Image ScreenshotToImage(Screenshot screenshot)
{
Image screenshotImage;
using (var memStream = new MemoryStream(screenshot.AsByteArray))
{
screenshotImage = Image.FromStream(memStream);
}
return screenshotImage;
}
[TearDown]
public static void Cleanup()
{
Browser.Dispose();
var dateTimeNow = DateTime.Now;
var data = dateTimeNow.ToString("dd/MM/yyyy HH:mm:ss");
IntegrationTest.WriteInLog("Test ends at: " + data);
IntegrationTest.WriteInLog("Time to execute: " + (dateTimeNow - InicioTeste).TotalSeconds + " seconds");
var takeScreenShoot = false;
if (TestContext.CurrentContext.Result.Outcome.Equals(ResultState.Failure))
{
IntegrationTest.WriteInLog("FAILS");
takeScreenShoot = true;
}
else if(TestContext.CurrentContext.Result.Outcome.Equals(ResultState.Error))
{
IntegrationTest.WriteInLog("ERROR");
takeScreenShoot = true;
}
else if(TestContext.CurrentContext.Result.Outcome.Equals(ResultState.SetUpError))
{
IntegrationTest.WriteInLog("SETUP ERROR");
takeScreenShoot = true;
}
else if(TestContext.CurrentContext.Result.Outcome.Equals(ResultState.SetUpFailure))
{
IntegrationTest.WriteInLog("SETUP FAILURE");
takeScreenShoot = true;
}
else if(TestContext.CurrentContext.Result.Outcome.Equals(ResultState.Inconclusive))
{
IntegrationTest.WriteInLog("INCONCLUSIVE");
}
else if (TestContext.CurrentContext.Result.Outcome.Equals(ResultState.Success))
{
IntegrationTest.WriteInLog("SUCESS");
}
else
{
IntegrationTest.WriteInLog("UNKNOW");
}
if (takeScreenShoot)
{
Browser.SaveScreenShot(TestContext.CurrentContext.Test.Name.ToUpper()));
IntegrationTest.WriteInLog("Screenshot saved as " + TestContext.CurrentContext.Test.Name.ToUpper()));
}
IntegrationTest.WriteInLog("\n");
}
I'm currently working on a .NET 2.0 application and I got stuck while trying to loop through all files in a specific folder and determine its file pairs. (Files with the same name but different extensions)
Like:
MyFile0001.jpg
MyFile0001.mp3
MyFile0001.txt
I'm interested in the filename extension, if they are available or not, that's why I created a class called "FileClass". At the end the file pairs will be added to a list list.AddRange().
Her is my code example:
class FileClass
{
public string FileName { get; set; }
public string filePath { get; set; }
public bool mp3 { get; set; }
public bool txt { get; set; }
public bool jpg { get; set; }
}
static void Main()
{
var list = new List<FileClass>();
var dirConfig = new DirectoryInfo(#"New Folder");
var allFiles = dirConfig.GetFiles("*");
foreach (var fileInfo in allFiles)
{
// Some code for finding file pairs...
// set properties, if filename extension is available
// and add them to a list.
}
}
Any suggestion how to handle this?
if possible without LINQ
I would use a Dictionary<String, List<String>> (for filename -> list of extensions)
The first step could look like this:
Dictionary<String, List<String>> d = new Dictionary<string, List<string>>();
var dirConfig = new DirectoryInfo(#"SomeFolder");
var allFiles = dirConfig.GetFiles("*");
foreach (var fileInfo in allFiles)
{
String coreName = Path.GetFileNameWithoutExtension(fileInfo.Name);
if (!d.ContainsKey(coreName)) d.Add(coreName, new List<String>());
d[coreName].Add(fileInfo.Extension);
}
Something like this should work:
class FileClass
{
public string FileName { get; set; }
public string filePath { get; set; }
public bool mp3 { get; set; }
public bool txt { get; set; }
public bool jpg { get; set; }
}
static void Main()
{
var list = new List<FileClass>();
var dirConfig = new DirectoryInfo(#"New Folder");
var allFiles = dirConfig.GetFiles("*");
foreach (var fileInfo in allFiles)
{
// for purposes of matching files with different extensions,
// the "fileName" variable below is the file name minus the extension
var fileName = fileInfo.Name.Substring(0, fileInfo.Name.Length
- fileInfo.Extension.Length);
var fileClass = list.Where(fc => fc.FileName == fileName).FirstOrDefault();
if (fileClass == null)
{
// this is the first version of this file name,
// so create a new FileClass instance and add it to the list
fileClass = new FileClass({
FileName = fileName,
filePath = Path.Combine(fileInfo.DirectoryName, fileName),
mp3 = (fileInfo.Extension.ToLower() == ".mp3"),
txt = (fileInfo.Extension.ToLower() == ".txt"),
jpg = (fileInfo.Extension.ToLower() == ".jpg")
});
list.Add(fileClass);
}
else
{
// a different version of this file was already found,
// so just set the boolean flag for this extension
switch (fileInfo.Extension.ToLower()) {
case ".mp3": fileClass.mp3 = true; break;
case ".txt": fileClass.txt = true; break;
case ".jpg": fileClass.jpg = true; break;
}
}
}
}
You can do something like this.
string[] arrayOfFiles= Directory.GetFiles(folderPath, "Filename.*");
I have written a piece of code that parses links from the top navigation from a website.
private string url = "http://www.blah.com/";
private HtmlWeb web;
private HtmlDocument doc;
private string topNavName = "";
private string topNavUrl = "";
public void Setup()
{
try
{
web = new HtmlWeb();
doc = web.Load(url);
web.AutoDetectEncoding = true;
TopCats();
}
catch (Exception e)
{
Console.WriteLine("There has been an issue loading url {0}", e);
}
}
private List<Catalogue> TopCats()
{
List<Catalogue> GetTop = new List<Catalogue>();
try
{
HtmlNodeCollection TopNode = doc.DocumentNode.SelectNodes("//*[#id='TopTabs1_tabs']/li/span/a");
if (TopNode != null)
{
foreach (HtmlNode Topitem in TopNode)
{
topNavName = Topitem.InnerText;
topNavUrl = url + Topitem.Attributes["href"].Value;
Catalogue xmltopcat = new Catalogue();
xmltopcat.indentifier = "here";
xmltopcat.name = topNavName;
xmltopcat.url = topNavUrl;
xmltopcat.description = "";
Console.WriteLine("Category >> {0}",topNavName);
}
}
}
catch (Exception e)
{
Console.WriteLine("There has been an issue Top Nav {0}", e);
}
return GetTop;
}
}
The problem that I am having is that I am not sure how to make each parsed data in the for each loop fill the XML elements. For the mapping on the XML I have created a new class:
class Catalogue
{
[XmlElement("Category identifier")]
public string indentifier
{ get; set; }
[XmlElement("name")]
public string name
{ get; set; }
[XmlElement("url")]
public string url
{ get; set; }
[XmlElement("description")]
public string description
{ get; set; }
}
I am really not sure to create a XML document- I have tried a few things, and I am really am not sure what I am doing. I am still learning C# and this is my first time working with XML.
You can use LINQ to XML.First store your all Catalogues into a List.
Catalogue xmltopcat = new Catalogue();
xmltopcat.indentifier = "here";
xmltopcat.name = topNavName;
xmltopcat.url = topNavUrl;
xmltopcat.description = "";
GetTop.Add(xmltopcat); // <-- add current catalogue to the list
Then call TopCats method and get your list and create XML file:
var list = TopCats();
XElement xDoc = new XElement("Catalogues",
list.Select(c => new XElement("Catalogue",
new XElement("indentifier",c.indentifier)
new XElement("name",c.name)
new XElement("url",c.url)
new XElement("description",c.description)));
xDoc.Save("savepath");
Or you can use XmlSerializer
FileStream fs = new FileStream("records.xml",FileMode.OpenOrCreate,FileAccess.Write);
XmlSerializer serializer = new XmlSerializer(typeof(List<Catalogue>),new XmlRootAttribute("Catalogues"));
serializer.Serialize(fs,list);
I stomped on some very weird bug which is very hard to reproduce I literally cant reproduce it. We have a window service installed on around 300+ PCs. From time to time config file(xml) that is used by this service become clear (on some of them). Totally clear no xml tags, nothing, 0kb. I have no clue what can cause such problem. No exception is logged in our logs. Even after this config becoming clear it's still running however it's not communicating with our web service. This is the class that is used for xml serialization and deserialization. I can’t find what can be possibly causing such behavior. Of course problem might not be in this particular class. Any suggestions?? Maybe some hints what can cause a file to become clear. When any operation on this file is by using this class.
Sorry for my bad English.
[XmlRootAttribute("xmlconfig", Namespace = "DSD_Config", IsNullable = false)]
public class xmlconfig
{
[XmlElementAttribute(IsNullable = false)]
public string ProgramApteczny { get; set; }
public string Server { get; set; }
public string Database { get; set; }
public string User { get; set; }
public string Password { get; set; }
public string DSDUser { get; set; }
public string DSDPassword { get; set; }
public string DSDServerAdres { get; set; }
//public static string cofFile = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\DSD_Agent\\config.xml";
public static string cofFile = Application.StartupPath + "\\config.xml";
public xmlconfig()
{
}
public xmlconfig(string sProgramApteczny, string sServer, string sDatabase, string sUser, string sPassword, string sDSDUser, string sDSDPassword, string sDSDServerAdres)
{
ProgramApteczny = sProgramApteczny;
Server = sServer;
Database = sDatabase;
User = sUser;
Password = sPassword;
DSDUser = sDSDUser;
DSDPassword = sDSDPassword;
DSDServerAdres = sDSDServerAdres;
}
public static void readXMLConfig(out xmlconfig configFile)
{
XmlSerializer oSerializer = new XmlSerializer(typeof(xmlconfig));
configFile = new xmlconfig();
try
{
using (FileStream fs = new FileStream(cofFile, FileMode.Open, FileAccess.Read))
{
configFile = (xmlconfig)oSerializer.Deserialize(fs);
try
{
configFile.Password = Encryption.DecryptString(configFile.Password);
}
catch (Exception)
{
configFile.Password = configFile.Password;
}
try
{
configFile.DSDPassword = Encryption.DecryptString(configFile.DSDPassword);
}
catch (Exception)
{
configFile.DSDPassword = configFile.DSDPassword;
}
}
}
catch
{
configFile = null;
}
}
public static void writeXMLConfig(string sProgramApteczny, string sServer, string sDatabase, string sUser, string sPassword, string sDSDUser, string sDSDPassword)
{
xmlconfig oxmlconfig = new xmlconfig();
readXMLConfig(out oxmlconfig);
sPassword = Encryption.EncryptString(sPassword);
sDSDPassword = Encryption.EncryptString(sDSDPassword);
if (oxmlconfig == null)
{
oxmlconfig = new xmlconfig(sProgramApteczny, sServer, sDatabase, sUser, sPassword, sDSDUser, sDSDPassword, "");
}
else
{
oxmlconfig.ProgramApteczny = sProgramApteczny;
oxmlconfig.Server = sServer;
oxmlconfig.Database = sDatabase;
oxmlconfig.User = sUser;
oxmlconfig.Password = sPassword;
oxmlconfig.DSDUser = sDSDUser;
oxmlconfig.DSDPassword = sDSDPassword;
}
XmlSerializer oSerializer = new XmlSerializer(typeof(xmlconfig));
TextWriter oStreamWriter = null;
try
{
oStreamWriter = new StreamWriter(cofFile, false);
oSerializer.Serialize(oStreamWriter, oxmlconfig);
}
catch (Exception oException)
{
WriteToLog(DateTime.Now, "Aplikacja wygenerowała następujący wyjątek: " + oException.Message);
// Console.WriteLine("Aplikacja wygenerowała następujący wyjątek: " + oException.Message);
}
finally
{
if (null != oStreamWriter)
{
oStreamWriter.Close();
}
}
}
public static void writeXMLDSDConfig(string sDSDServerAdres)
{
xmlconfig oxmlconfig = new xmlconfig();
readXMLConfig(out oxmlconfig);
if (oxmlconfig == null)
{
throw new Exception("Aplikacja wygenerowała następujący wyjątek: Musisz zdefiniować wszystkie parametry");
}
else
{
oxmlconfig.DSDPassword = Encryption.EncryptString(oxmlconfig.DSDPassword);
oxmlconfig.Password = Encryption.EncryptString(oxmlconfig.Password);
oxmlconfig.DSDServerAdres = sDSDServerAdres;
}
XmlSerializer oSerializer = new XmlSerializer(typeof(xmlconfig));
TextWriter oStreamWriter = null;
try
{
oStreamWriter = new StreamWriter(cofFile, false);
oSerializer.Serialize(oStreamWriter, oxmlconfig);
}
catch (Exception oException)
{
throw new Exception("Aplikacja wygenerowała następujący wyjątek: " + oException.Message);
}
finally
{
if (null != oStreamWriter)
{
oStreamWriter.Close();
}
}
}
}
What I guess, the xml file is accessed by multiple computers/windows services; if so?
Looks no locking mechanism is being used while reading and writing the file. a possible work around would be using a single instance class that only allows one thread to read/write file at one time.
bool isInProgress=false
Public void Read()
{
if(isInProgress==false)
{
isInProgress=true;
try
{
//Do reading or writing
}
finally
{
isInProgress=false;
}
}
}
I will add a new node to parent node on my xml file. Unit test for this code says "success", it is passing but no added node in xml.
Also, some of tests i'm getting the error;
<< Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) >>
on the line SaveToFileAsync
what is wrong with me? and there is an alternative way to do this?
public string ConnectionPath { get; set; }
protected string XPath { get; set; }
protected string XParentPath { get; set; }
protected XmlDocument Source { get; set; }
protected StorageFolder SFolder { get; set; }
protected StorageFile SFile { get; set; }
public RepositoryBase(string connectionPath)
{
this.ConnectionPath = connectionPath;
}
public async void Insert(T entity)
{
SFolder = Package.Current.InstalledLocation;
SFile = await SFolder.GetFileAsync(this.ConnectionPath);
var content = await FileIO.ReadTextAsync(SFile);
if (!string.IsNullOrEmpty(content))
{
Source = new XmlDocument();
Source.LoadXml(content);
}
var tagName = typeof(T).Name;
if (tagName != null)
{
IXmlNode parentNode = Source.SelectSingleNode(XParentPath);
if (parentNode != null)
{
XmlElement newNode = Source.CreateElement(tagName);
newNode.InnerText = GetContent(entity);
parentNode.AppendChild(newNode);
}
}
await Source.SaveToFileAsync(SFile);
}
* PlaceRepositoryClass ;
public class PlaceRepository : RepositoryBase<Place>
{
public PlaceRepository()
: base("Data\\bla\\bla.xml")
{
XPath = "/Country[Id=1]/Cities/City[Id=1]/Places/Place";
XParentPath = "/Country[Id=1]/Cities/City[Id=1]/Places";
}
}
Unit Test Method ;
[TestMethod]
public void AppendNode()
{
Place place = new Place()
{
Id = 40,
Name = "xxxxx",
SummaryPath = "yyyyy",
Logo = "xy.png",
LogoSmall = "xy_small.png",
Latitude = "32.423",
Longitude = "34.23424",
Content = new PlaceContent() { Items = new List<ContentItem>() { new ContentItem() { TextPath = "aaaa", Header = "bbbbb", AudioFilePath = "x.mp3" } } },
Gallery = new PhotoGallery() { Photos = new List<Photo>() { new Photo() { Path = "ab.png", Text = "abab" } } }
};
PlaceRepository repository = new PlaceRepository();
repository.Insert(place);
}
You are trying to write to a file that's part of the application package, and that's read only. You could copy the file to local storage and make the modifications there perhaps.