| | 1 | == The C# API's for Shared Records == |
| | 2 | |
| | 3 | The C# library is a port of some of the basic shared records functionality for .NET developers. Provides API's for creating encrypted and unencrypted records, and handling metadata. |
| | 4 | |
| | 5 | === Low Level API === |
| | 6 | !SharedRecords.Storage.IDataStore: this interface represents the lowest level API for dealing with records. IDataStore defines methods for creating records, retrieving records, checking for the existence of records, and adding and retrieving meta data to or from a record. IDataStore is implemented by two classes, !SharedRecords.Storage.!RemoteDataStore and !SharedRecords.Storage.!LocalDataStore. !LocalDataStore maintains a datastore on the local hard drive of the machine running the API. Records and metadata are saved and retrieved from a directory tree rooted at a directory provided by the user of the API. !RemoteDataStore uses the HTTP REST protocol described elsewhere on this wiki to save records to, and retrieve records from a datastore running on a remote server. |
| | 7 | |
| | 8 | === Main Application API === |
| | 9 | |
| | 10 | !SharedRecords.Storage.IStorageProvider is an interface which exposes almost identical functionality as IDataStore, however it adds the ability to manage multiple !DataStores. The interface provides methods to create and retrieve records, to add !MetaData to and receive !MetaData from records, and to check for the existence of records. It also contains methods to add a !DataStore to those managed by the !StorageProvider, to remove a !DataStore from the !StorageProvider, and to get a list of the currently registered !DataStores. An implementation of IStorageProvider, !MultipleStorageProvider, exists in the !SharedRecords.Storage namespace which implements these functions. |
| | 11 | |
| | 12 | The IStorageProvider object also provides an [wiki:StorageProviderEvents Event Framework] for handling asynchronous uploads of records. |
| | 13 | |
| | 14 | There is also a factory class, !SharedRecords.Storage.!DataStoreFactory, which contains methods to create and initialize local or remote !DataStores. The correct !DataStore type will be created and returned, based on whether the argument passed to the factory method is an URL or a C# !DirectoryInfo object. These will create !LocalDataStores and !RemoteDataStores, respectively. |
| | 15 | |
| | 16 | == Reference == |
| | 17 | |
| | 18 | * [/api/CSharp CSharp Class Documentation] |
| | 19 | |
| | 20 | |
| | 21 | == Reference == |
| | 22 | |
| | 23 | * [/downloads/client/SharedRecords.dll CSharp Shared Records dll] |
| | 24 | |
| | 25 | == Code Snippets == |
| | 26 | |
| | 27 | The following code snippet shows how to create and save a local file |
| | 28 | |
| | 29 | {{{ |
| | 30 | /// <summary> |
| | 31 | /// Reads a file "test.doc" encrypts and saves to the configured data stores. Reads it |
| | 32 | /// back and saves as "test-back.doc". Assumes "test.doc" exists in the C: drive |
| | 33 | /// </summary> |
| | 34 | public void TestStandalone() { |
| | 35 | IStorageProvider sp = StorageProviderFactory.CreateFromConfig(); |
| | 36 | |
| | 37 | string readFile = @"C:\test.doc"; |
| | 38 | string writeFile = @"C:\test-back.doc"; |
| | 39 | FileStream myFile = new FileStream(readFile, FileMode.Open, FileAccess.Read); |
| | 40 | // true means encrypt it |
| | 41 | Record r = sp.CreateRecord(myFile, true); |
| | 42 | Console.WriteLine("Created record: " + r); |
| | 43 | FileStream myNewFile = new FileStream(writeFile, FileMode.Create, FileAccess.Write); |
| | 44 | sp.GetRecord(r, myNewFile, null); |
| | 45 | FileInfo sent = new FileInfo(readFile); |
| | 46 | FileInfo received = new FileInfo(writeFile); |
| | 47 | // do a basic sanity check - can open the file for better results |
| | 48 | if (sent.Length != received.Length) { |
| | 49 | throw new Exception("something went wrong."); |
| | 50 | } |
| | 51 | } |
| | 52 | }}} |
| | 53 | |
| | 54 | The following shows the same example, but manually specifying an encryption key. |
| | 55 | |
| | 56 | {{{ |
| | 57 | /// <summary> |
| | 58 | /// The same test as above but specifying an encryption key |
| | 59 | /// </summary> |
| | 60 | public void TestStandaloneWithKey() |
| | 61 | { |
| | 62 | IStorageProvider sp = StorageProviderFactory.CreateFromConfig(); |
| | 63 | |
| | 64 | string readFile = @"C:\test.doc"; |
| | 65 | string writeFile = @"C:\test-back.doc"; |
| | 66 | FileStream myFile = new FileStream(readFile, FileMode.Open, FileAccess.Read); |
| | 67 | |
| | 68 | // the default shared records encryption scheme |
| | 69 | SymmetricAlgorithm alg = EncryptionUtils.Default; |
| | 70 | |
| | 71 | // set the encryption key to use |
| | 72 | alg.Key = StringUtils.ByteArrayFromHexString("13199834a85e3b22"); |
| | 73 | |
| | 74 | Record r = sp.CreateRecord(myFile, true, alg, null, null); |
| | 75 | Console.WriteLine("Created record: " + r); |
| | 76 | |
| | 77 | // make sure the key is the same |
| | 78 | if (!"13199834a85e3b22".Equals(r.Key)) |
| | 79 | { |
| | 80 | throw new Exception("something went wrong - wrong key returned."); |
| | 81 | } |
| | 82 | |
| | 83 | FileStream myNewFile = new FileStream(writeFile, FileMode.Create, FileAccess.Write); |
| | 84 | |
| | 85 | // manually create a new record for retreival with the same key |
| | 86 | Record rBack = new Record(); |
| | 87 | rBack.Id = r.Id; |
| | 88 | rBack.Key = "13199834a85e3b22"; |
| | 89 | |
| | 90 | sp.GetRecord(rBack, myNewFile, null); |
| | 91 | FileInfo sent = new FileInfo(readFile); |
| | 92 | FileInfo received = new FileInfo(writeFile); |
| | 93 | // do a basic sanity check - can open the file for better results |
| | 94 | if (sent.Length != received.Length) |
| | 95 | { |
| | 96 | throw new Exception("something went wrong - bad file size"); |
| | 97 | } |
| | 98 | } |
| | 99 | }}} |
| | 100 | |
| | 101 | |
| | 102 | |
| | 103 | |
| | 104 | |
| | 105 | This snippet shows how to add !MetaData to a Record, andretrieve the !MetaData associated with an Record. |
| | 106 | |
| | 107 | {{{ |
| | 108 | /// <summary> |
| | 109 | /// This test creates a new record in each IDataStore. The test then |
| | 110 | /// creates a new MetaDataEntry associated with that record, and adds |
| | 111 | /// the MetaDataEntry to the IDataStore. The test then reads back the |
| | 112 | /// MetaDataEntries held in the IDataStore. |
| | 113 | /// |
| | 114 | /// This test also shows how the MetaDataEntry.ToXmlText() method |
| | 115 | /// produces well-formed Xml for any MetaDataEntry. |
| | 116 | /// </summary> |
| | 117 | public void GetAndAddMetaDataEntryTest() |
| | 118 | { |
| | 119 | // Create a new Record |
| | 120 | Record record = CreateRecord(dataStore); |
| | 121 | |
| | 122 | // Create a new MetaDataEntry |
| | 123 | MetaDataEntry mde = new MetaDataEntry(); |
| | 124 | mde.RecordUID = record.Id; |
| | 125 | mde.UserID = "User1"; |
| | 126 | mde.ContentType = "text/plain"; |
| | 127 | mde.Title = "Test Metadata"; |
| | 128 | mde.AddTag("Test1"); |
| | 129 | mde.AddTag("Test2"); |
| | 130 | mde.AddTag("Test3"); |
| | 131 | mde.UserTimeStamp = DateTime.Now; |
| | 132 | MemoryStream dataStream = new MemoryStream(17); |
| | 133 | StreamWriter writer = new StreamWriter(dataStream); |
| | 134 | writer.Write("This is the data."); |
| | 135 | writer.Flush(); |
| | 136 | writer.Close(); |
| | 137 | mde.Data = dataStream.GetBuffer(); |
| | 138 | |
| | 139 | // Add the MetaDataEntry |
| | 140 | dataStore.AddMetaDataEntry(record, mde); |
| | 141 | mdeList = dataStore.GetMetaData(record); |
| | 142 | |
| | 143 | Console.WriteLine("Metadata read back from datastore {0} after add:", dataStore.ToString()); |
| | 144 | foreach (MetaDataEntry entry in mdeListAfter) |
| | 145 | System.Console.WriteLine(entry.ToXmlText()); |
| | 146 | } |
| | 147 | } |
| | 148 | }}} |
| | 149 | |
| | 150 | Alternatively, a !MetaDataEntry can be added to the Record directly, without using |
| | 151 | the IDataStore: |
| | 152 | |
| | 153 | {{{ |
| | 154 | /// <summary> |
| | 155 | /// This test creates a new record in each IDataStore. The test then |
| | 156 | /// creates a new MetaDataEntry associated with that record, and adds |
| | 157 | /// the MetaDataEntry to the IDataStore. |
| | 158 | /// </summary> |
| | 159 | public void RecordAddMetaDataEntryTest() |
| | 160 | { |
| | 161 | // Create a new Record |
| | 162 | Record record = CreateRecord(dataStore); |
| | 163 | |
| | 164 | // Create a new MetaDataEntry |
| | 165 | MetaDataEntry mde = new MetaDataEntry(); |
| | 166 | mde.RecordUID = record.Id; |
| | 167 | mde.UserID = "User1"; |
| | 168 | mde.ContentType = "text/plain"; |
| | 169 | mde.Title = "Test Metadata"; |
| | 170 | mde.AddTag("Test1"); |
| | 171 | mde.AddTag("Test2"); |
| | 172 | mde.AddTag("Test3"); |
| | 173 | mde.UserTimeStamp = DateTime.Now; |
| | 174 | MemoryStream dataStream = new MemoryStream(17); |
| | 175 | StreamWriter writer = new StreamWriter(dataStream); |
| | 176 | writer.Write("This is the data."); |
| | 177 | writer.Flush(); |
| | 178 | writer.Close(); |
| | 179 | mde.Data = dataStream.GetBuffer(); |
| | 180 | |
| | 181 | // Add MetaDataEntry to Record |
| | 182 | record.AddMetaDataEntry(mde); |
| | 183 | |
| | 184 | List<MetaDataEntry> mdeList = record.GetMetaData(); |
| | 185 | Console.WriteLine("Metadata read back from datastore {0} after add:", dataStore.ToString()); |
| | 186 | foreach (MetaDataEntry entry in mdeListAfter) |
| | 187 | System.Console.WriteLine(entry.ToXmlText()); |
| | 188 | } |
| | 189 | |
| | 190 | }}} |