This references my last question which appears to have been abandoned. I am experiencing an odd "bug" if you will with C# and MS VS 2015. To reproduce the error, follow the steps:
Open console app project and copy paste code below.
Set a break point here:
First run code past break point, it works! :D
Then run code again but this time STOP at the break point and DRAG the executing statement cursor INTO the if statement from here:
to here:
Hit Continue and an NRE exception is thrown. Why does this happen? Is it just me? What is the technical explination for this?
CODE:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace testapp
{
class Program
{
static void Main(string[] args)
{
FILECollection randomCollection = new FILECollection();
// Fill with junk test data:
for(int i = 0; i<10; i++)
{
FILE junkfile = new FILE() { fileName = i.ToString(), folderName = i.ToString(), fileHashDigest = new byte[1] };
randomCollection.Add(junkfile);
}
if (true)
{
Console.WriteLine("testing this weird exception issue...");
FILE test;
test = new FILE();
test.fileName = "3";
test.folderName = "3";
test.fileHashDigest = new byte[1];
FILE exists = randomCollection.Where(f => f.fileName == test.fileName &&
f.fileHashDigest.SequenceEqual(test.fileHashDigest)).First();
}
}
}
public class FILE
{
public FILE() { _fileName = "";}
private string _fileName;
public string fileName
{
get
{
if (false)
return this._fileName.ToUpper();
else
return this._fileName;
}
set
{
if (false)
this._fileName = value.ToUpper();
else
this._fileName = value;
}
}
public string folderName { get; set; }
public byte[] fileHashDigest { get; set; }
}
public class FILECollection : IEnumerable<FILE>, ICollection<FILE>
{
private HashSet<FILE> svgHash;
private static List<FILE> PreallocationList;
public string FileName = "N/A";
/// <summary>
/// Default Constructor, will not
/// preallocate memory.
/// </summary>
/// <param name="PreallocationSize"></param>
public FILECollection()
{
this.svgHash = new HashSet<FILE>();
this.svgHash.Clear();
}
/// <summary>
/// Overload Constructor Preallocates
/// memory to be used for the new
/// FILE Collection.
/// </summary>
public FILECollection(int PreallocationSize, string fileName = "N/A", int fileHashDigestSize = 32)
{
FileName = fileName;
PreallocationList = new List<FILE>(PreallocationSize);
for (int i = 0; i <= PreallocationSize; i++)
{
byte[] buffer = new byte[fileHashDigestSize];
FILE preallocationSVG = new FILE()
{
fileName = "",
folderName = "",
fileHashDigest = buffer
};
PreallocationList.Add(preallocationSVG);
}
this.svgHash = new HashSet<FILE>(PreallocationList);
this.svgHash.Clear(); // Capacity remains unchanged until a call to TrimExcess is made.
}
/// <summary>
/// Add an FILE file to
/// the FILE Collection.
/// </summary>
/// <param name="svg"></param>
public void Add(FILE svg)
{
this.svgHash.Add(svg);
}
/// <summary>
/// Removes all elements
/// from the FILE Collection
/// </summary>
public void Clear()
{
svgHash.Clear();
}
/// <summary>
/// Determine if the FILE collection
/// contains the EXACT FILE file, folder,
/// and byte[] sequence. This guarantees
/// that the collection contains the EXACT
/// file you are looking for.
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool Contains(FILE item)
{
return svgHash.Any(f => f.fileHashDigest.SequenceEqual(item.fileHashDigest) &&
f.fileName == item.fileName &&
f.folderName == item.folderName);
}
/// <summary>
/// Determine if the FILE collection
/// contains the same file and folder name,
/// byte[] sequence is not compared. The file and folder
/// name may be the same but this does not guarantee the
/// file contents are exactly the same. Use Contains() instead.
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool ContainsPartially(FILE item)
{
return svgHash.Any(f => f.fileName == item.fileName &&
f.folderName == item.folderName);
}
/// <summary>
/// Returns the total number
/// of FILE files in the Collection.
/// </summary>
public int Count
{ get { return svgHash.Count(); } }
public bool IsReadOnly
{ get { return true; } }
public void CopyTo(FILE[] array, int arrayIndex)
{
svgHash.CopyTo(array, arrayIndex);
}
public bool Remove(FILE item)
{
return svgHash.Remove(item);
}
public IEnumerator<FILE> GetEnumerator()
{
return svgHash.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return svgHash.GetEnumerator();
}
}
}
I think either I am debugging in a terribly wrong way, or Microsoft should take a look at this. It's like future code is breaking current code...which is impossible!
OK here's my best guess..
First, as I mentioned in the comments, the exception doesn't occur if you comment out the line FILE exists = randomCollection.Where(f => f.fileName == test.fileName && f.fileHashDigest.SequenceEqual(test.fileHashDigest)).First();
Second, I noticed the same behavior can be reproduced with the following code:
if (true)
{
object o;
o = new object();
Func<bool> m = () => o == null;
}
i.e. the cause seems to be related to the variable being used in a lambda expression. So, looking at the same code snippet above in ILSpy I get the following:
Program.<>c__DisplayClass0_0 <>c__DisplayClass0_ = new Program.<>c__DisplayClass0_0();
<>c__DisplayClass0_.o = new object();
Func<bool> func = new Func<bool>(<>c__DisplayClass0_.<Main>b__0);
so my best guess is that the NullReferenceException refers to <>c__DisplayClass0_ intance being null - and I'm therefore inclined to believe that the stepping through the if(true) actually skipped the first line where <>c__DisplayClass0_ is instantiated
Related
I am trying to make a winform application. The app has 2 textboxes (firstName, lastName), a numericUpDown, and a checkbox. The app is able to read from a text file, with comma separated rows (Daniel,Brown,26,true). The app put this info in a listbox. Then you can add a new user. When you are finished adding users you press save and the new info from lisbox will be saved in that text file. I've created the read file script and add user succesfully. However I can't create the save user button so that it'll save: Daniel,Brown,26,true. I was able to save as: Daniel,Brown,26,happy.
Here is the Person Class:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Age { get; set; }
public bool IsHappy { get; set; }
public override string ToString()
{
var statusText = IsHappy ? "happy" : "not happy";
return $"{FirstName} {LastName} is {Age} and is {statusText}";
}
}
Here is the form.cs with it's script:
public partial class ChallengeForm : Form
{
private BindingList<Person> _persons = new BindingList<Person>();
private PersonsService _personsService;
public ChallengeForm()
{
_personsService = new PersonsService();
InitializeComponent();
WireUpDropDown();
}
private void WireUpDropDown()
{
_persons = new BindingList<Person>(_personsService.GetPersons(#"C:\Users\user\Desktop\Document.TXT"));
usersListBox.DataSource = _persons;
}
private void addUserButton_Click(object sender, EventArgs e)
{
var person = new Person { FirstName = firstNameText.Text, LastName = lastNameText.Text, Age = agePicker.Text, IsHappy = isHappyCheckbox.Checked };
_persons.Add(person);
}
private void saveListButton_Click(object sender, EventArgs e)
{
}
}
My question is how can I convert the status back to bool. And write the listbox to the text file as csv. I would be very thankfull if you could use SoC.
Here is what I've tried:
const string sPath = (#"C:\Users\user\Desktop\Document.TXT");
System.IO.StreamWriter SaveFile = new System.IO.StreamWriter(sPath);
SaveFile.Write(myperson);
foreach (var item in usersListBox.Items)
{
List<string> unwantedWords = new List<string> { "is", "and" };
var linesSplitted = item.ToString().Split(' ').ToList();
var wordsWithoutUnwantedWords = linesSplitted.Where(i => !unwantedWords.Contains(i)).ToList();
for (int i = 0; i<wordsWithoutUnwantedWords.Count; i++)
{
var isLastWord = i == wordsWithoutUnwantedWords.Count - 1;
SaveFile.Write(wordsWithoutUnwantedWords[i]);
if (!isLastWord)
{
SaveFile.Write(",");
}
Look into XML Serialization. You can just pass in your filepath and the object and the rest will be done for you by the Serialisation classes. Code below:
This is taken from DeadlyDog's awesome answer: https://stackoverflow.com/a/22417240/1623971
/// <summary>
/// Writes the given object instance to an XML file.
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
TextWriter writer = null;
try
{
var serializer = new XmlSerializer(typeof(T));
writer = new StreamWriter(filePath, append);
serializer.Serialize(writer, objectToWrite);
}
finally
{
if (writer != null)
writer.Close();
}
}
/// <summary>
/// Reads an object instance from an XML file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the XML file.</returns>
public static T ReadFromXmlFile<T>(string filePath) where T : new()
{
TextReader reader = null;
try
{
var serializer = new XmlSerializer(typeof(T));
reader = new StreamReader(filePath);
return (T)serializer.Deserialize(reader);
}
finally
{
if (reader != null)
reader.Close();
}
}
Sample use case:
WriteToXmlFile<Person>("C:\someClass.txt", objectToSerialize);
// Read the file contents back into a variable.
Person deserializedObject = ReadFromXmlFile<Person>("C:\someClass.txt");
So I am completely stumped on this one. I am getting an error Object reference not set to an instance of an object. and I am not sure why.
I have a class FILE
public class FILE
{
private string _fileName;
public string fileName
{
get
{
if (!Settings.Values.CaseSensitive)
return this._fileName.ToUpper();
else
return this._fileName;
}
set
{
if (!Settings.Values.CaseSensitive)
this._fileName = value.ToUpper();
else
this._fileName = value;
}
}
public string folderName { get; set; }
public byte[] fileHashDigest { get; set; }
}
I am creating an instance like:
FILE test1233;
test1233 = new FILE(); // <---- Ex thrown here!? Why???
test1233.fileName = "";
folderName = "";
fileHashDigest = new byte[1];
As soon as the variable is placed on the stack, it throws an exception. BUT... if I remove all refrences to this variable on code further down (WHICH HAS NOT YET BEEN EXECUTED IN DEBUGMODE!!!) then no exception gets thrown. What on earth is going on here?
For refrence, here is the method in it's entirety:
private bool IsFolderOverride(FileCollection zipFILEList, DataTable exceptionTableFileList, DataRow currentRow, ref DataTable detectedFolderRenames)
{
bool foundInExceptionTable = false;
foreach (DataRow exRow in exceptionTableFileList.Rows)
{
if (exRow["FILE_NAME"].ToString().ToUpper() == currentRow["FILE_NAME"].ToString().ToUpper() &&
(decimal)exRow["WINDOW_GROUP_ID"] == (decimal)currentRow["WINDOW_GROUP_ID"])
{
string name = exRow["FILE_NAME"].ToString().ToUpper();
string folder = exRow["FOLDER_NAME"].ToString().ToUpper();
byte[] digest = (byte[])exRow["FILE_HASH_DIGEST"];
CopyCat exCopyCat = new CopyCat();
exCopyCat.fileName = name;
exCopyCat.folderName = folder;
exCopyCat.fileHashDigest = digest;
//HAS AN EXCEPTION!
FILE test1233 = new FILE();
test1233.fileName = "";
test1233.folderName = "";
test1233.fileHashDigest = new byte[1];
//NO EXCEPTION THROWN
FILE test = new FILE();
bool test9 = zipFileList.Contains(test1233);
test.fileName = name;
test.folderName = folder;
test.fileHashDigest = digest;
FILE test123 = new FILE();
if (zipFileList.Contains(test1233)) // Exact match found in zip in old folder from exception table.
{
FILE exists = zipFileList.Where(f => f.fileName == test1233.fileName &&
f.fileHashDigest.SequenceEqual(test1233.fileHashDigest)).First();
object[] items = exRow.ItemArray;
Array.Resize(ref items, items.Length + 4);
items[items.Length - 1] = "Y";
items[items.Length - 2] = exists.folderName;
items[items.Length - 3] = test1233.folderName;
items[items.Length - 4] = "Folder Override";
if (detectedFolderRenames.Rows.Count == 0 || !detectedFolderRenames.Rows.Contains(items[0]))
detectedFolderRenames.Rows.Add(items);
foundInExceptionTable = true;
break;
}
else if (zipFileList.ContainsPartially(test1233)) // Match in zip with Different Hash found from ex table.
{
FILE exists = zipFileList.Where(f => f.fileName == test1233.fileName).First();
object[] items = exRow.ItemArray;
Array.Resize(ref items, items.Length + 4);
items[items.Length - 1] = "N";
items[items.Length - 2] = exists.folderName;
items[items.Length - 3] = test1233.folderName;
items[items.Length - 4] = "Folder Override";
if (detectedFolderRenames.Rows.Count == 0 || !detectedFolderRenames.Rows.Contains(items[0]))
detectedFolderRenames.Rows.Add(items);
foundInExceptionTable = true;
break;
}
}
else
continue;
}
return foundInExceptionTable;
}
UPDATE: I am still working on an example for you, but in the mean time here is potentially helpful information:
test1233' threw an exception of type 'System.NullReferenceException'
Data: {System.Collections.ListDictionaryInternal}
HResult: -2147467261
HelpLink: null
InnerException: null
Message: "Object reference not set to an instance of an object."
Source: null
StackTrace: null
TargetSite: null
The Data: {System.Collections.ListDictionaryInternal} part is a little interesting to me, my class does not use any dictionary lists.
UPDATE #2: Ok, I have produced a reproducible sequence of steps for others to try. On your machines, it may be just fine, like Jon Skeet said, it might be my debug environment settings but please try and let me know. Here are the steps to reproduce.
Open console app project and copy paste code below.
Set a break point here:
First run code past break point, it works! :D
Then run code again but this time STOP at the break point and DRAG the executing statement cursor INTO the if statement from here:
to here:
There it is! So the error was caused from my method of testing, but does this make any sense or is this just me on my machine?
CODE:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace testapp
{
class Program
{
static void Main(string[] args)
{
FILECollection randomCollection = new FILECollection();
// Fill with junk test data:
for(int i = 0; i<10; i++)
{
FILE junkfile = new FILE() { fileName = i.ToString(), folderName = i.ToString(), fileHashDigest = new byte[1] };
randomCollection.Add(junkfile);
}
if (true)
{
Console.WriteLine("testing this weird exception issue...");
FILE test;
test = new FILE();
test.fileName = "3";
test.folderName = "3";
test.fileHashDigest = new byte[1];
FILE exists = randomCollection.Where(f => f.fileName == test.fileName &&
f.fileHashDigest.SequenceEqual(test.fileHashDigest)).First();
}
}
}
public class FILE
{
public FILE() { _fileName = "";}
private string _fileName;
public string fileName
{
get
{
if (false)
return this._fileName.ToUpper();
else
return this._fileName;
}
set
{
if (false)
this._fileName = value.ToUpper();
else
this._fileName = value;
}
}
public string folderName { get; set; }
public byte[] fileHashDigest { get; set; }
}
public class FILECollection : IEnumerable<FILE>, ICollection<FILE>
{
private HashSet<FILE> svgHash;
private static List<FILE> PreallocationList;
public string FileName = "N/A";
/// <summary>
/// Default Constructor, will not
/// preallocate memory.
/// </summary>
/// <param name="PreallocationSize"></param>
public FILECollection()
{
this.svgHash = new HashSet<FILE>();
this.svgHash.Clear();
}
/// <summary>
/// Overload Constructor Preallocates
/// memory to be used for the new
/// FILE Collection.
/// </summary>
public FILECollection(int PreallocationSize, string fileName = "N/A", int fileHashDigestSize = 32)
{
FileName = fileName;
PreallocationList = new List<FILE>(PreallocationSize);
for (int i = 0; i <= PreallocationSize; i++)
{
byte[] buffer = new byte[fileHashDigestSize];
FILE preallocationSVG = new FILE()
{
fileName = "",
folderName = "",
fileHashDigest = buffer
};
PreallocationList.Add(preallocationSVG);
}
this.svgHash = new HashSet<FILE>(PreallocationList);
this.svgHash.Clear(); // Capacity remains unchanged until a call to TrimExcess is made.
}
/// <summary>
/// Add an FILE file to
/// the FILE Collection.
/// </summary>
/// <param name="svg"></param>
public void Add(FILE svg)
{
this.svgHash.Add(svg);
}
/// <summary>
/// Removes all elements
/// from the FILE Collection
/// </summary>
public void Clear()
{
svgHash.Clear();
}
/// <summary>
/// Determine if the FILE collection
/// contains the EXACT FILE file, folder,
/// and byte[] sequence. This guarantees
/// that the collection contains the EXACT
/// file you are looking for.
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool Contains(FILE item)
{
return svgHash.Any(f => f.fileHashDigest.SequenceEqual(item.fileHashDigest) &&
f.fileName == item.fileName &&
f.folderName == item.folderName);
}
/// <summary>
/// Determine if the FILE collection
/// contains the same file and folder name,
/// byte[] sequence is not compared. The file and folder
/// name may be the same but this does not guarantee the
/// file contents are exactly the same. Use Contains() instead.
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool ContainsPartially(FILE item)
{
return svgHash.Any(f => f.fileName == item.fileName &&
f.folderName == item.folderName);
}
/// <summary>
/// Returns the total number
/// of FILE files in the Collection.
/// </summary>
public int Count
{ get { return svgHash.Count(); } }
public bool IsReadOnly
{ get { return true; } }
public void CopyTo(FILE[] array, int arrayIndex)
{
svgHash.CopyTo(array, arrayIndex);
}
public bool Remove(FILE item)
{
return svgHash.Remove(item);
}
public IEnumerator<FILE> GetEnumerator()
{
return svgHash.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return svgHash.GetEnumerator();
}
}
}
I think either I am debugging in a terribly wrong way, or Microsoft should take a look at this. It's like future code is breaking current code...which is impossible!
I tried to execute the code in a console app and is working, can you give more details? Answers about the Settings initialization doesn't make sense here at this point because you should be able to create the instance of FILE. Once you try to assign(set) or request(get) then you are dealing with fileName property. I am not seeing why you get the exception when you create the instance.
static void Main(string[] args)
{
FILE test1233;
test1233 = new FILE(); // <---- Ex is not thrown here!? test1233.fileName = "";
test1233.folderName = "";
test1233.fileHashDigest = new byte[1];
}
public class FILE
{
private string _fileName;
public string fileName
{
get
{
if (YOUR SETTING CONDITION HERE)
return this._fileName.ToUpper();
else
return this._fileName;
}
set
{
if (YOUR SETTING CONDITION HERE)
this._fileName = value.ToUpper();
else
this._fileName = value;
}
}
public string folderName { get; set; }
public byte[] fileHashDigest { get; set; }
}
see the cursor on the print screen
Here is my debug configuration
I followed this article and I created my CustomSettingsProvider in order to get rid of the "_url_somehash" part of the path where the user.config file is stored. Now my settings are stored in <LocalApplicationData>\CompanyName\ProductName\Version\user.config as I wanted.
My user.config file (written by my application before creating my CustomSettingsProvider) contains one Int32[] property that was stored and loaded correctly by the default SettingsProvider. When I use my CustomSettingsProvider I get the following exception:
Exception InvalidCastException
Source = mscorlib
Message = Invalid cast from 'System.String' to 'System.Int32[]'.
TargetSite = System.Object DefaultToType(System.IConvertible, System.Type, System.IFormatProvider)
Stack =
System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
System.Convert.ChangeType(Object value, Type conversionType)
MyApp.Interface.CustomSettingsProvider.GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection) in d:\Users\angelo\Documents\Visual Studio 2013\Projects\MyApp\MyApp\Interface\CustomSettingsProvider.cs:line 112
System.Configuration.SettingsBase.GetPropertiesFromProvider(SettingsProvider provider)
System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
System.Configuration.SettingsBase.get_Item(String propertyName)
System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
MyApp.Properties.Settings.get_UpgradeRequired() in d:\Users\angelo\Documents\Visual Studio 2013\Projects\MyApp\MyApp\Properties\Settings.Designer.cs:line 31
MyApp.Interface.Program.Run() in d:\Users\angelo\Documents\Visual Studio 2013\Projects\MyApp\MyApp\Interface\Program.cs:line 51
MyApp.Interface.Program.Main() in d:\Users\angelo\Documents\Visual Studio 2013\Projects\MyApp\MyApp\Interface\Program.cs:line 34
How can I fix this problem? In a more general way, how can I store collections and classes in the same way I can do it with the default SettingsProvider?
This is the full code of my CustomSettingsProvider class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Reflection;
using System.Xml.Linq;
using System.IO;
// ==>>>> https://stackoverflow.com/questions/2265271/custom-path-of-the-user-config
// https://stackoverflow.com/questions/1947185/c-sharp-get-special-folder
namespace MyApp.Interface
{
class CustomSettingsProvider : SettingsProvider
{
#region Helper struct
/// <summary>
/// Helper struct.
/// </summary>
internal struct SettingStruct
{
internal string name;
internal string serializeAs;
internal string value;
}
#endregion
#region Constants
const string NAME = "name";
const string SERIALIZE_AS = "serializeAs";
const string CONFIG = "configuration";
const string USER_SETTINGS = "userSettings";
const string SETTING = "setting";
#endregion
#region Fields
bool _loaded;
#endregion
#region Properties
/// <summary>
/// Override.
/// </summary>
public override string ApplicationName { get { return System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name; } set { /*do nothing*/ } }
/// <summary>
/// The setting key this is returning must set before the settings are used.
/// e.g. <c>Properties.Settings.Default.SettingsKey = #"C:\temp\user.config";</c>
/// </summary>
private string UserConfigPath
{
get
{
System.Diagnostics.FileVersionInfo versionInfo;
string strUserConfigPath, strUserConfigFolder;
strUserConfigPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.Create);
versionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location);
strUserConfigPath = Path.Combine(strUserConfigPath, versionInfo.CompanyName, versionInfo.ProductName, versionInfo.ProductVersion, "user.config");
strUserConfigFolder = Path.GetDirectoryName(strUserConfigPath);
if(!Directory.Exists(strUserConfigFolder))
Directory.CreateDirectory(strUserConfigFolder);
return strUserConfigPath;
}
}
/// <summary>
/// In memory storage of the settings values
/// </summary>
private Dictionary<string, SettingStruct> SettingsDictionary { get; set; }
#endregion
#region Constructor
/// <summary>
/// Loads the file into memory.
/// </summary>
public CustomSettingsProvider()
{
SettingsDictionary = new Dictionary<string, SettingStruct>();
}
/// <summary>
/// Override.
/// </summary>
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
base.Initialize(ApplicationName, config);
}
#endregion
/// <summary>
/// Must override this, this is the bit that matches up the designer properties to the dictionary values
/// </summary>
/// <param name="context"></param>
/// <param name="collection"></param>
/// <returns></returns>
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
{
//load the file
if(!_loaded)
{
_loaded = true;
LoadValuesFromFile();
}
//collection that will be returned.
SettingsPropertyValueCollection values = new SettingsPropertyValueCollection();
//iterate thought the properties we get from the designer, checking to see if the setting is in the dictionary
foreach(SettingsProperty setting in collection)
{
SettingsPropertyValue value = new SettingsPropertyValue(setting);
value.IsDirty = false;
//need the type of the value for the strong typing
var t = Type.GetType(setting.PropertyType.FullName);
if(SettingsDictionary.ContainsKey(setting.Name))
{
value.SerializedValue = SettingsDictionary[setting.Name].value;
value.PropertyValue = Convert.ChangeType(SettingsDictionary[setting.Name].value, t);
}
else //use defaults in the case where there are no settings yet
{
value.SerializedValue = setting.DefaultValue;
value.PropertyValue = Convert.ChangeType(setting.DefaultValue, t);
}
values.Add(value);
}
return values;
}
/// <summary>
/// Must override this, this is the bit that does the saving to file. Called when Settings.Save() is called
/// </summary>
/// <param name="context"></param>
/// <param name="collection"></param>
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
{
//grab the values from the collection parameter and update the values in our dictionary.
foreach(SettingsPropertyValue value in collection)
{
var setting = new SettingStruct()
{
value = (value.PropertyValue == null ? String.Empty : value.PropertyValue.ToString()),
name = value.Name,
serializeAs = value.Property.SerializeAs.ToString()
};
if(!SettingsDictionary.ContainsKey(value.Name))
SettingsDictionary.Add(value.Name, setting);
else
SettingsDictionary[value.Name] = setting;
}
//now that our local dictionary is up-to-date, save it to disk.
SaveValuesToFile();
}
/// <summary>
/// Loads the values of the file into memory.
/// </summary>
private void LoadValuesFromFile()
{
string strUserConfigPath;
strUserConfigPath = UserConfigPath;
//if the config file is not where it's supposed to be create a new one.
if(!File.Exists(strUserConfigPath))
CreateEmptyConfig(strUserConfigPath);
//System.Security.Policy.StrongName strongName = new System.Security.Policy.StrongName(
//ClickOnce
//load the xml
var configXml = XDocument.Load(UserConfigPath);
//get all of the <setting name="..." serializeAs="..."> elements.
var settingElements = configXml.Element(CONFIG).Element(USER_SETTINGS).Element(typeof(Properties.Settings).FullName).Elements(SETTING);
//iterate through, adding them to the dictionary, (checking for nulls, xml no likey nulls)
//using "String" as default serializeAs...just in case, no real good reason.
foreach(var element in settingElements)
{
var newSetting = new SettingStruct()
{
name = element.Attribute(NAME) == null ? String.Empty : element.Attribute(NAME).Value,
serializeAs = element.Attribute(SERIALIZE_AS) == null ? "String" : element.Attribute(SERIALIZE_AS).Value,
value = element.Value ?? String.Empty
};
SettingsDictionary.Add(element.Attribute(NAME).Value, newSetting);
}
}
/// <summary>
/// Creates an empty user.config file...looks like the one MS creates.
/// This could be overkill a simple key/value pairing would probably do.
/// </summary>
private void CreateEmptyConfig(string strUserConfigPath)
{
Configuration config1;
config1 = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
if(File.Exists(config1.FilePath))
{
File.Copy(config1.FilePath, strUserConfigPath);
}
else
{
string s = Properties.Settings.Default.LastLoadedImage;
var doc = new XDocument();
var declaration = new XDeclaration("1.0", "utf-8", "true");
var config = new XElement(CONFIG);
var userSettings = new XElement(USER_SETTINGS);
var group = new XElement(typeof(Properties.Settings).FullName);
userSettings.Add(group);
config.Add(userSettings);
doc.Add(config);
doc.Declaration = declaration;
doc.Save(strUserConfigPath);
}
}
/// <summary>
/// Saves the in memory dictionary to the user config file
/// </summary>
private void SaveValuesToFile()
{
//load the current xml from the file.
var import = XDocument.Load(UserConfigPath);
//get the settings group (e.g. <Company.Project.Desktop.Settings>)
var settingsSection = import.Element(CONFIG).Element(USER_SETTINGS).Element(typeof(Properties.Settings).FullName);
//iterate though the dictionary, either updating the value or adding the new setting.
foreach(var entry in SettingsDictionary)
{
var setting = settingsSection.Elements().FirstOrDefault(e => e.Attribute(NAME).Value == entry.Key);
if(setting == null) //this can happen if a new setting is added via the .settings designer.
{
var newSetting = new XElement(SETTING);
newSetting.Add(new XAttribute(NAME, entry.Value.name));
newSetting.Add(new XAttribute(SERIALIZE_AS, entry.Value.serializeAs));
newSetting.Value = (entry.Value.value ?? String.Empty);
settingsSection.Add(newSetting);
}
else //update the value if it exists.
{
setting.Value = (entry.Value.value ?? String.Empty);
}
}
import.Save(UserConfigPath);
}
#region Angelo
private object GetDefaultValue(SettingsProperty setting)
{
if (setting.PropertyType.IsEnum)
return Enum.Parse(setting.PropertyType, setting.DefaultValue.ToString());
// Return the default value if it is set
// Return the default value if it is set
if (setting.DefaultValue != null)
{
System.ComponentModel.TypeConverter tc = System.ComponentModel.TypeDescriptor.GetConverter(setting.PropertyType);
return tc.ConvertFromString(setting.DefaultValue.ToString());
}
else // If there is no default value return the default object
{
return Activator.CreateInstance(setting.PropertyType);
}
}
#endregion
}
}
To read properties that are serialized as XML, you first need to deserialize them.
Probably the easiest way is to add a new method called something like getPropertyValue, which determines whether it should return the string value directly or deserialize it first. Then, in your code shown below, you can just call this method instead of using Convert.ChangeType to set property values:
var t = Type.GetType(setting.PropertyType.FullName);
if (SettingsDictionary.ContainsKey(setting.Name))
{
value.SerializedValue = SettingsDictionary[setting.Name].value;
// value.PropertyValue = Convert.ChangeType(SettingsDictionary[setting.Name].value, t);
value.PropertyValue = getPropertyValue(SettingsDictionary[setting.Name].value, t, setting.SerializeAs);
}
else //use defaults in the case where there are no settings yet
{
value.SerializedValue = setting.DefaultValue;
// value.PropertyValue = Convert.ChangeType(setting.DefaultValue, t);
value.PropertyValue = getPropertyValue((string)setting.DefaultValue, t, setting.SerializeAs);
}
An example of how your new method getPropertyValue might work:
private object getPropertyValue(string settingValue, Type settingType, SettingsSerializeAs serializeAs)
{
switch (serializeAs)
{
case SettingsSerializeAs.String:
return settingValue;
case SettingsSerializeAs.Xml:
//for demo purposes, assumes this is your int array--otherwise do further checking to get the correct type
XmlSerializer serializer = new XmlSerializer(typeof(int[]));
return serializer.Deserialize(new StringReader(settingValue));
//implement further types as required
default:
throw new NotImplementedException(string.Format("Settings deserialization as {0} is not implemented", serializeAs));
}
}
This will resolve the invalid cast error and load your array of integers into the setting.
You'll need to apply the corresponding treatment when you save the settings. If you hit complications with that, I suggest you post a new question as the issues are somewhat different.
I am using VS 2010 C#. My code is as follows:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using MarketplaceWebServiceOrders;
using MarketplaceWebServiceOrders.Model;
namespace FetchNewOrdersJob
{
public class MarketplaceWebServiceOrders
{
private volatile bool isRunning;
private OrderFetcher orderFetcher;
private TimeSpan _checkOrdersInterval = TimeSpan.FromMinutes(15.0);
/// <summary>
/// Gets or sets the order check interval. Defaults to 15 minutes.
/// </summary>
public TimeSpan CheckOrdersInterval
{
get { return _checkOrdersInterval; }
set { _checkOrdersInterval = value; }
}
/// <summary>
/// Internal method to handle an order.
/// </summary>
protected virtual void HandleOrder(Order order)
{
Console.WriteLine("Processing Order:");
Console.WriteLine("---------------------------------------------------");
Console.WriteLine(order.ToString());
// Fetch the order items in each order
orderFetcher.FetchOrderItems(order.AmazonOrderId, delegate(OrderItem item)
{
Console.WriteLine("\tProcessing Order Item");
Console.WriteLine("\t---------------------------------------------------"); // Process order item here.
Console.WriteLine("\t" + item.ToString().Replace("\n", "\n\t"));
});
Console.WriteLine("=================================================");
Console.WriteLine();
}
/// <summary>
/// Method to continuously check orders over an interval, and list OrderItems for those Orders.
/// </summary>
private void OrdersJobThread(object obj)
{
orderFetcher.ProcessOrder += HandleOrder;
if (this.CheckOrdersInterval == TimeSpan.MinValue)
{
throw new ArgumentException("The CheckOrdersInterval TimeSpan cannot be zero.", "CheckOrdersInterval");
}
DateTime startCheckInterval = DateTime.Now.Subtract(CheckOrdersInterval);
// Continue forever until the isRunning flag is cleared.
while (isRunning)
{
try
{
// Check the orders for this interval.
DateTime checkInterval = startCheckInterval;
startCheckInterval = DateTime.Now.Subtract(TimeSpan.FromMinutes(3.0));
Console.WriteLine("Fetching orders from " + checkInterval.ToString() + " to " + startCheckInterval.ToString());
orderFetcher.FetchOrders(checkInterval, startCheckInterval);
// Wait for the next interval.
Console.WriteLine("Fetch complete. Sleeping until next interval.");
while (isRunning && DateTime.Now.Subtract(startCheckInterval) < CheckOrdersInterval)
{
Thread.Sleep(1000);
}
}
catch(Exception err)
{
Console.WriteLine("Error: " + err.Message + ". Orders job thread is exiting.");
isRunning = false;
}
}
}
/// <summary>
/// Sample code to invoke the OrderFetcher.
/// </summary>
/// <param name="service">MarketplaceWebServiceOrders object.</param>
/// <param name="sellerId">The seller Id.</param>
/// <param name="marketplaceIdList">List of marketplaces passed in to the GetOrders call.</param>
public static void InvokeOrderFetcherSample(
MarketplaceWebServiceOrders service,
string sellerId,
string [] marketplaceIdList
)
{
// Create a FetchOrderUpdates job with the default time span.
MarketplaceWebServiceOrders job = new MarketplaceWebServiceOrders();
job.isRunning = true;
job.orderFetcher = new OrderFetcher(service, sellerId, marketplaceIdList);
Thread jobThread = new Thread(job.OrdersJobThread);
jobThread.IsBackground = true;
jobThread.Start();
// Pause on the main thread for one hour or until the thread exits, then end the job.
jobThread.Join(1000 * 60 * 60);
job.isRunning = false;
// Block until the thread terminates to prevent any requests in progress from being aborted.
while (jobThread.IsAlive)
{
Thread.Sleep(1000);
}
}
}
}
I get two errors and can't seem to figure this out
Argument 1: cannot convert from 'FetchNewOrdersJob.MarketplaceWebServiceOrders' to 'MarketplaceWebServiceOrders.MarketplaceWebServiceOrders'
The best overloaded method match for 'MarketplaceWebServiceOrders.OrderFetcher.OrderFetcher(MarketplaceWebServiceOrders.MarketplaceWebServiceOrders, string, string[])' has some invalid arguments
The Line number of the error is 112: job.orderFetcher = new OrderFetcher(service, sellerId, marketplaceIdList);
OrderFetcher.cs
using System;
using System.Collections.Generic;
using System.Text;
using MarketplaceWebServiceOrders.Model;
namespace MarketplaceWebServiceOrders
{
/// <summary>
/// Sample helper class to Fetch Orders and OrderItems using the Amazon MWS Orders API.
/// </summary>
public class OrderFetcher
{
public delegate void RetriableMethodCall();
public delegate void ProcessOrderHandler(Order order);
public delegate void ProcessOrderItemHandler(OrderItem orderItem);
/// <summary>
/// Default amount of time, in milliseconds, to sleep if a request is throttled; default to 1 per 10 minutes.
/// </summary>
public const int DEFAULT_THROTTLED_WAIT_TIMEOUT = 10 * 60 * 1000;
/// <summary>
/// Default throttling limit for ListOrders calls; default to 1 per 12 seconds.
/// </summary>
private const int LIST_ORDERS_DEFAULT_THROTTLE_LIMIT = 12 * 1000;
/// <summary>
/// Default throttling limit for ListOrderItems calls; default to 1 per 100 minutes.
/// </summary>
private const int LIST_ORDER_ITEMS_DEFAULT_THROTTLE_LIMIT = 10 * 60 * 1000;
private MarketplaceWebServiceOrders mwsService;
private string mwsSellerId;
private string[] mwsMarketplaceIdList;
private DateTime lastServiceCall = DateTime.MinValue;
private ProcessOrderHandler _processOrder;
/// <summary>
/// Event called when an order is received for processing.
/// </summary>
public event ProcessOrderHandler ProcessOrder
{
add { _processOrder += value; }
remove { _processOrder -= value; }
}
/// <summary>
/// Creates a new instance of the OrderFetcherSample class.
/// </summary>
/// <param name="service"></param>
public OrderFetcher(MarketplaceWebServiceOrders service, string sellerId, string[] marketplaceIdList)
{
mwsService = service;
mwsSellerId = sellerId;
mwsMarketplaceIdList = marketplaceIdList;
}
/// <summary>
/// Fetches all orders created between the starting time and the server's
/// local system time minus two minutes.
/// <param name="startTime">The starting time period of orders to fetch.</param>
public void FetchOrders(DateTime startTime)
{
FetchOrders(startTime, DateTime.MinValue);
}
/// <summary>
/// Fetches all orders created in the given time period and processes them locally.
/// <param name="startTime">The starting time period of orders to fetch.</param>
/// <param name="endTime">The ending time period of orders to fetch.</param>
public void FetchOrders(DateTime startTime, DateTime endTime)
{
ListOrdersRequest request = new ListOrdersRequest();
request.CreatedAfter = startTime;
if (endTime != DateTime.MinValue)
{
request.CreatedBefore = endTime;
}
request.SellerId = mwsSellerId;
request.MarketplaceId = new MarketplaceIdList();
request.MarketplaceId.Id = new List<string>();
foreach (string marketplaceId in mwsMarketplaceIdList)
{
request.MarketplaceId.Id.Add(marketplaceId);
}
List<Order> orderList = new List<Order>();
ListOrdersResponse response = null;
OrderFetcher.InvokeRetriable(LIST_ORDERS_DEFAULT_THROTTLE_LIMIT, delegate()
{
response = mwsService.ListOrders(request);
ProcessOrders(response.ListOrdersResult.Orders.Order);
});
String nextTokenString = response.ListOrdersResult.NextToken;
while (!string.IsNullOrEmpty(nextTokenString))
{
// If NextToken is set, continue looping through the orders.
ListOrdersByNextTokenRequest nextRequest = new ListOrdersByNextTokenRequest();
nextRequest.NextToken = nextTokenString;
nextRequest.SellerId = mwsSellerId;
ListOrdersByNextTokenResponse nextResponse = null;
OrderFetcher.InvokeRetriable(LIST_ORDERS_DEFAULT_THROTTLE_LIMIT, delegate()
{
nextResponse = mwsService.ListOrdersByNextToken(nextRequest);
ProcessOrders(nextResponse.ListOrdersByNextTokenResult.Orders.Order);
});
nextTokenString = nextResponse.ListOrdersByNextTokenResult.NextToken;
}
}
/// <summary>
/// Method called by the FetchOrders method to process the orders.
/// </summary>
/// <param name="orders">List of orders returned by FetchOrders</param>
protected virtual void ProcessOrders(List<Order> orders)
{
foreach (Order order in orders)
{
if (_processOrder != null)
{
_processOrder(order);
}
}
}
/// <summary>
/// Fetches the OrderItems for the specified orderId.
/// </summary>
public void FetchOrderItems(string orderId, ProcessOrderItemHandler handler)
{
if (handler == null) throw new ArgumentNullException("handler");
ListOrderItemsRequest request = new ListOrderItemsRequest();
request.SellerId = mwsSellerId;
request.AmazonOrderId = orderId;
ListOrderItemsResponse response = null;
OrderFetcher.InvokeRetriable(LIST_ORDER_ITEMS_DEFAULT_THROTTLE_LIMIT, delegate()
{
response = mwsService.ListOrderItems(request);
foreach (OrderItem orderItem in response.ListOrderItemsResult.OrderItems.OrderItem)
{
handler(orderItem);
}
});
String nextTokenString = response.ListOrderItemsResult.NextToken;
while (!string.IsNullOrEmpty(nextTokenString))
{
// If NextToken is set, continue looping through the orders.
ListOrderItemsByNextTokenRequest nextRequest = new ListOrderItemsByNextTokenRequest();
nextRequest.NextToken = nextTokenString;
nextRequest.SellerId = mwsSellerId;
ListOrderItemsByNextTokenResponse nextResponse = null;
OrderFetcher.InvokeRetriable(LIST_ORDER_ITEMS_DEFAULT_THROTTLE_LIMIT, delegate()
{
nextResponse = mwsService.ListOrderItemsByNextToken(nextRequest);
foreach (OrderItem orderItem in nextResponse.ListOrderItemsByNextTokenResult.OrderItems.OrderItem)
{
handler(orderItem);
}
});
nextTokenString = nextResponse.ListOrderItemsByNextTokenResult.NextToken;
}
}
/// <summary>
/// Invokes a method in a retriable fashion.
/// </summary>
/// <param name="throttledWaitTime">The amount of time to wait if the request is throttled.</param>
/// <param name="method">The method to invoke.</param>
public static void InvokeRetriable(RetriableMethodCall method)
{
InvokeRetriable(DEFAULT_THROTTLED_WAIT_TIMEOUT, method);
}
/// <summary>
/// Invokes a method in a retriable fashion.
/// </summary>
/// <param name="throttledWaitTime">The amount of time to wait if the request is throttled.</param>
/// <param name="method">The method to invoke.</param>
public static void InvokeRetriable(int throttledWaitTime, RetriableMethodCall method)
{
bool retryRequest = false;
do
{
retryRequest = false;
try
{
// Perform some action
method.Invoke();
}
catch (MarketplaceWebServiceOrdersException ordersErr)
{
// If the request is throttled, wait and try again.
if (ordersErr.ErrorCode == "RequestThrottled")
{
Console.WriteLine("Request is throttled; waiting...");
retryRequest = true;
System.Threading.Thread.Sleep(throttledWaitTime);
}
else
{
// On any other error, re-throw the exception to be handled by the caller
throw;
}
}
} while (retryRequest);
}
}
}
I think this may have to do with the way in which you imported (I assume) your web service objects. If it's a WCF service, make sure your "Model" is referenced along the different projects, and when adding the service reference, make sure to check the option "Reuse existing Types".
You have classes MarketplaceWebServiceOrders both in current FetchNewOrdersJob and in MarketplaceWebServiceOrders namespaces (also last namespace have same name as your class). Looks like your OrderFetcher class is declared in MarketplaceWebServiceOrders namespace. And it expects as argument MarketplaceWebServiceOrders which is also declared in that namespace. But you are trying to pass MarketplaceWebServiceOrders class, which is declared in current FetchNewOrdersJob namespace.
Rename your FetchNewOrdersJob.MarketplaceWebServiceOrders class to avoid these conflicts.
For one of my projects we utilize a Content Delivery Network (EdgeCast) and I was wondering if anyone knew of an existing (open source) library for C# that we could leverage? In a nutshell, I am investigating the ability to create directories, upload files, and allow some general maintenance (rename files, delete files) via our admin panel. Any insight would be appreciated.
NOTE: My code to do this. I don't know if they have an updated API at this point so please check. This code is circa 2009 (as-is, no warranties, use at your own risk, etc).
EdgeCast.cs
using System;
using edgeCastWS = [DOMAIN].com.edgecast.api.EdgeCastWebServices;
namespace [DOMAIN].IO.ContentDeliveryNetwork
{
/// <summary>
/// <b>Authentication</b>
/// <para>Each web service call will include a string parameter called strCredential which will ensure that customers may only access data related to their own accounts. This credential is a string made up of a few separate pieces of information.</para>
/// <para>A typical credential a customer would use may look like: “c:bas:user#email.com:password”</para>
/// <para> * The field format of this string is delimited with a colon “:” character.</para>
/// <para> * The first field is the type of client which is calling the web service. “c” represents an individual customer.</para>
/// <para> * The second field is the security type. “bas” represents Basic Authentication.</para>
/// <para> * With basic authentication the third field is the username which is usually in email address notation.</para>
/// <para> * With basic authentication the fourth field is the password associated with the user.</para>
/// <para>If the username and password are not valid, then the credential will prevent the specified function from proceeding. A SOAP exception will be generated and sent back to the client that called the function. The message contained in the exception will contain the string “Access Denied.”</para>
/// </summary>
public class EdgeCast : IDisposable
{
#region Declarations
[ThreadStatic]
private static EdgeCast _current;
private static EdgeCastCredential _credential = null;
private static string _customerID = string.Empty;
private static edgeCastWS _edgeCastWS = null;
#endregion
#region Constructor
public EdgeCast()
{
if (_current != null)
{
throw new InvalidOperationException("Only one ContentDeliveryNetwork may be created on a given thread.");
}
_current = this;
_edgeCastWS = new edgeCastWS();
ConstructCredentials();
_customerID = AppSettings.EdgeCast_CustomerID;
}
#endregion
#region API Methods
/// <summary>
/// Purges a file from all of the EdgeCast caching servers. This process may take a few minutes to fully complete.
/// </summary>
/// <param name="Path">This is path of the file or folder to purge, in URL format. To specify a folder, please put a trailing slash at the end of the URL. All files under that folder will be purged</param>
/// <param name="MediaType">HTTP Large Object = 3, HTTP Small Object = 8, Flash = 2, Windows = 1</param>
/// <returns>An integer that indicates whether or not the transaction was successful. 0 represents yes, -1 represents no</returns>
internal static short PurgeFileFromEdge(string Path, int MediaType)
{
return _edgeCastWS.PurgeFileFromEdge(_credential.Credential, _customerID, Path, MediaType);
}
/// <summary>
/// Loads a file to disk on all of the EdgeCast caching servers. This process may take a few minutes to fully complete.
/// </summary>
/// <param name="Path">This is path of the file to load, in URL format. Folders may not be loaded and will be ignored</param>
/// <param name="MediaType">HTTP Large Object = 3, HTTP Small Object = 8</param>
/// <returns>An integer that indicates whether or not the transaction was successful. 0 represents yes, -1 represents no</returns>
internal static short LoadFileToEdge(string Path, int MediaType)
{
return _edgeCastWS.LoadFileToEdge(_credential.Credential, _customerID, Path, MediaType);
}
/// <summary>
/// This method call is used to add a token authentication directory. All additions and changes should be processed every 30 minutes
/// </summary>
/// <param name="Dir">Directory Path should be starting from the root. Example: /directory1/directory2</param>
/// <param name="MediaType">Use 1 for Windows, 2 for Flash, 3 for HTTP Caching / Progressive download.</param>
/// <returns></returns>
internal static short TokenDirAdd(string Dir, int MediaType)
{
return _edgeCastWS.TokenDirAdd(_credential.Credential, _customerID, Dir, MediaType);
}
internal static string TokenEncrypt(string Key, string Args)
{
return _edgeCastWS.TokenEncrypt(_credential.Credential, Key, Args);
}
internal static short TokenKeyUpdate(string Key, int MediaType)
{
return _edgeCastWS.TokenKeyUpdate(_credential.Credential, _customerID, Key, MediaType);
}
#endregion
#region FTP Methods
/// <summary>
/// Does a FTP Upload of a file on the local system
/// </summary>
/// <param name="targetPath">The full path to save to on the FTP server (.\Campaigns\Prod\[Company GUID])</param>
/// <param name="sourceFileName">The full path and filename of the file to be uploaded (C:\[DOMAIN]\files\[filename])</param>
internal static void FTP_UploadFile(string targetPath, string sourceFileName)
{
string[] dirs = targetPath.Split(new char[] { '\\', '/' });
using (FTPFactory myFTP = new FTPFactory())
{
myFTP.login();
myFTP.setBinaryMode(true);
// Make sure the directories are there and change down to the bottom most directory...
foreach (string dirName in dirs)
{
bool dirExists = true;
try { myFTP.chdir(dirName); }
catch { dirExists = false; }
if (!dirExists)
{
myFTP.mkdir(dirName);
myFTP.chdir(dirName);
}
}
// upload the file now...
myFTP.upload(sourceFileName);
}
}
/// <summary>
/// Returns a string array of files in the target directory
/// </summary>
/// <param name="targetPath">The target directory</param>
/// <returns>string array or null if no files found</returns>
internal static string[] FTP_GetFileList(string targetPath)
{
string[] dirs = targetPath.Split(new char[] { '\\', '/' });
string[] files = null;
using (FTPFactory myFTP = new FTPFactory())
{
myFTP.login();
myFTP.setBinaryMode(true);
// Make sure the directories are there and change down to the bottom most directory...
foreach (string dirName in dirs)
{
bool dirExists = true;
try { myFTP.chdir(dirName); }
catch { dirExists = false; }
if (!dirExists)
{
myFTP.mkdir(dirName);
myFTP.chdir(dirName);
}
}
// get the list of files now...
files = myFTP.getFileList("*.*");
}
return files;
}
/// <summary>
/// Checks to see if a file exists
/// </summary>
/// <param name="targetPath">The CDN directory path to look in</param>
/// <param name="targetFile">The file to look for</param>
/// <returns>true = found, false = not found</returns>
internal static bool FTP_DoesFileExist(string targetPath, string targetFile)
{
bool retFlag = true;
string[] dirs = targetPath.Split(new char[] { '\\', '/' });
using (FTPFactory myFTP = new FTPFactory())
{
myFTP.login();
myFTP.setBinaryMode(true);
// change to the target directory - if it does not exists, neither does the file! simple...
foreach (string dirName in dirs)
{
try { myFTP.chdir(dirName); }
catch { retFlag = false; }
}
if (retFlag)
{
try { retFlag = myFTP.getFileSize(targetFile) > 0; }
catch { retFlag = false; }
}
}
return retFlag;
}
internal static bool FTP_DoesFileExist(string targetFile)
{
string targetPath = targetFile.Replace(#"http://", "");
targetPath = targetPath.Replace(#"https://", "");
targetPath = targetPath.Replace(#"cdn1.[DOMAIN].com/", "");
targetPath = targetPath.Replace(#"/", #"\");
targetPath = targetPath.Substring(0, targetPath.LastIndexOf(#"\"));
targetFile = targetFile.Substring(targetFile.LastIndexOf(#"/") + 1);
return FTP_DoesFileExist(targetPath, targetFile);
}
#endregion
#region Helper Methods
static private string ConstructCredentials()
{
_credential = new EdgeCastCredential();
return _credential.Credential;
}
static private string ConstructCredentials(string credentials)
{
_credential = new EdgeCastCredential(credentials);
return _credential.Credential;
}
static private string ConstructCredentials(string typeOfClient, string securityType, string userName, string password)
{
_credential = new EdgeCastCredential(typeOfClient, securityType, userName, password);
return _credential.Credential;
}
#endregion
#region IDisposable Members
public void Dispose()
{
_current = null;
}
#endregion
}
}
EdgeCastCredential.cs
using System;
using rivSecurity = [DOMAIN].Security.Cryptography.Internal;
namespace [DOMAIN].IO.ContentDeliveryNetwork
{
internal class EdgeCastCredential
{
#region Properties
public string TypeOfClient;
public string SecurityType;
public string UserName;
public string Password;
public string Credential { get { return String.Format("{0}:{1}:{2}:{3}", TypeOfClient, SecurityType, UserName, Password); } }
#endregion
#region Constructor
public EdgeCastCredential()
{
TypeOfClient = AppSettings.EdgeCast_TypeOfClient;
SecurityType = AppSettings.EdgeCast_SecurityType;
UserName = rivSecurity.Decrypt(AppSettings.EdgeCast_UserName);
Password = rivSecurity.Decrypt(AppSettings.EdgeCast_Password);
}
public EdgeCastCredential(string credentials)
{
string[] parts = credentials.Split(new char[] { ':' });
}
public EdgeCastCredential(string typeOfClient, string securityType, string userName, string password)
{
TypeOfClient = typeOfClient;
SecurityType = securityType;
UserName = userName;
Password = password;
}
#endregion
}
}
Never mind. I created a FTP library and used what little they had for an API. I can not now read/upload/delete files and purge the CDN.