within windows live messenger, it is possible to share the song you are currently listening to. what would i need to do to get this working within c# like libarys etc cannot find the correct documentation on google.
You'll need to use the iTunes SDK to interact with iTunes from .NET. So there's your Google search term. :)
Here's a start:
http://blogs.msdn.com/b/noahc/archive/2006/07/06/automating-itunes-with-c-in-net.aspx
http://blogs.msdn.com/b/dancre/archive/2004/05/08/128645.aspx
Here is a script for LinqPad in C# which does as requested. (see LinqPad.com)
Bonus! Artwork view.
It looks like this:
<Query Kind="Program">
<Namespace>iTunesLib</Namespace>
<Namespace>System.Security.Cryptography</Namespace>
</Query>
void Main()
{
var track = new iTunesApp().CurrentTrack;
if (track == null)
"nothing playing".Dump();
else
new Viewer(track,true).Dump();
}
public class Viewer
{
const string PREFIX = "itlps-";
private IITFileOrCDTrack store;
private bool materialize;
public string album { get { return store.Album; } }
public string band { get { return store.Artist; } }
public string song { get { return store.Name; } }
public string desc { get { return store.Description; } }
public int? artCnt { get {
if (store.Artwork == null) return null;
else return store.Artwork.Count; }
}
public IEnumerable<ImageViewer> art { get {
if (materialize)
{
foreach(var artT in store.Artwork)
{
var art = artT as IITArtwork;
string ext = ".tmp";
switch(art.Format)
{
case ITArtworkFormat.ITArtworkFormatBMP:
ext = ".BMP";
break;
case ITArtworkFormat.ITArtworkFormatJPEG:
ext = ".JPG";
break;
case ITArtworkFormat.ITArtworkFormatPNG:
ext = ".PNG";
break;
}
string path = Path.Combine(Path.GetTempPath(),PREFIX+Path.GetRandomFileName()+ext);
art.SaveArtworkToFile(path);
yield return new ImageViewer(path);
}
}
yield break; }
}
public Viewer(IITFileOrCDTrack t,bool materializeArt = false)
{
store = t;
materialize = materializeArt;
}
public Viewer(IITTrack t,bool materializeArt = false)
{
store = t as IITFileOrCDTrack;
materialize = materializeArt;
}
}
public class ImageViewer
{
public string hash { get { return _hash.Value; } }
static private string _path { get; set; }
public object image { get { return _image.Value; } }
static private SHA1Managed sha = new SHA1Managed();
private Lazy<object> _image = new Lazy<object>(() => {return Util.Image(_path);});
private Lazy<string> _hash = new Lazy<string>(() =>
{
string hash = string.Empty;
using (FileStream stream = File.OpenRead(_path))
{
byte [] checksum = sha.ComputeHash(stream);
hash = BitConverter.ToString(checksum).Replace("-", string.Empty);
}
return hash;
});
public ImageViewer(string path)
{
_path = path;
}
}
last i checked this functionality is included out of the box all you need is to have itunes and windows live messenger installed and activate "what im listening to" and it shows this in your messenger status. if you are looking to create a bot that messages this out to a contact that is a different story tho that you will need to write a script for
Related
I've searched on google on how to dynamically edit the Resources.Values.strings.xml file so I can add my Facebook Access Token so the user won't need to log in again when he reuses the app.
Is it possible to edit it, or do I have to use another method to store the token?
I think the best place would be to save this to the KeyStore. To do this you must use the DependencyService More Info here
The interface and implementation would then be:
PCL interface
public interface IAuth
{
void CreateStore();
IEnumerable<string> FindAccountsForService(string serviceId);
void Save(string pin,string serviceId);
void Delete(string serviceId);
}
Android
public class IAuthImplementation : IAuth
{
Context context;
KeyStore ks;
KeyStore.PasswordProtection prot;
static readonly object fileLock = new object();
const string FileName = "MyProg.Accounts";
static readonly char[] Password = null;
public void CreateStore()
{
this.context = Android.App.Application.Context;
ks = KeyStore.GetInstance(KeyStore.DefaultType);
prot = new KeyStore.PasswordProtection(Password);
try
{
lock (fileLock)
{
using (var s = context.OpenFileInput(FileName))
{
ks.Load(s, Password);
}
}
}
catch (Java.IO.FileNotFoundException)
{
//ks.Load (null, Password);
LoadEmptyKeyStore(Password);
}
}
public IEnumerable<string> FindAccountsForService(string serviceId)
{
var r = new List<string>();
var postfix = "-" + serviceId;
var aliases = ks.Aliases();
while (aliases.HasMoreElements)
{
var alias = aliases.NextElement().ToString();
if (alias.EndsWith(postfix))
{
var e = ks.GetEntry(alias, prot) as KeyStore.SecretKeyEntry;
if (e != null)
{
var bytes = e.SecretKey.GetEncoded();
var password = System.Text.Encoding.UTF8.GetString(bytes);
r.Add(password);
}
}
}
return r;
}
public void Delete(string serviceId)
{
var alias = MakeAlias(serviceId);
ks.DeleteEntry(alias);
Save();
}
public void Save(string pin, string serviceId)
{
var alias = MakeAlias(serviceId);
var secretKey = new SecretAccount(pin);
var entry = new KeyStore.SecretKeyEntry(secretKey);
ks.SetEntry(alias, entry, prot);
Save();
}
void Save()
{
lock (fileLock)
{
using (var s = context.OpenFileOutput(FileName, FileCreationMode.Private))
{
ks.Store(s, Password);
}
}
}
static string MakeAlias(string serviceId)
{
return "-" + serviceId;
}
class SecretAccount : Java.Lang.Object, ISecretKey
{
byte[] bytes;
public SecretAccount(string password)
{
bytes = System.Text.Encoding.UTF8.GetBytes(password);
}
public byte[] GetEncoded()
{
return bytes;
}
public string Algorithm
{
get
{
return "RAW";
}
}
public string Format
{
get
{
return "RAW";
}
}
}
static IntPtr id_load_Ljava_io_InputStream_arrayC;
void LoadEmptyKeyStore(char[] password)
{
if (id_load_Ljava_io_InputStream_arrayC == IntPtr.Zero)
{
id_load_Ljava_io_InputStream_arrayC = JNIEnv.GetMethodID(ks.Class.Handle, "load", "(Ljava/io/InputStream;[C)V");
}
IntPtr intPtr = IntPtr.Zero;
IntPtr intPtr2 = JNIEnv.NewArray(password);
JNIEnv.CallVoidMethod(ks.Handle, id_load_Ljava_io_InputStream_arrayC, new JValue[]
{
new JValue (intPtr),
new JValue (intPtr2)
});
JNIEnv.DeleteLocalRef(intPtr);
if (password != null)
{
JNIEnv.CopyArray(intPtr2, password);
JNIEnv.DeleteLocalRef(intPtr2);
}
}
Call Create Store in the main activity of Android app first. - This could possibly be improved and remove CreateStrore() from the interface by checking if ks == null in Save and Delete and calling the method if true
This would then save the access token to the KeyStore that you can then retrieve later
I have a Xamarin application and have managed to download my data from my server to my device. I have also got it set up so that it can take a SqlCipher Encryption key to encrypt the data.
My question is where is the correct location to store my key that I use to encrypt this data? Is it to you KeyStore / KeyChain? Which mono classes should I be looking to use?
Due to the popularity of this question I am going to post my implementation of this:
PCL interface
public interface IAuth
{
void CreateStore();
IEnumerable<string> FindAccountsForService(string serviceId);
void Save(string pin,string serviceId);
void Delete(string serviceId);
}
Android
public class IAuthImplementation : IAuth
{
Context context;
KeyStore ks;
KeyStore.PasswordProtection prot;
static readonly object fileLock = new object();
const string FileName = "MyProg.Accounts";
static readonly char[] Password = null;
public void CreateStore()
{
this.context = Android.App.Application.Context;
ks = KeyStore.GetInstance(KeyStore.DefaultType);
prot = new KeyStore.PasswordProtection(Password);
try
{
lock (fileLock)
{
using (var s = context.OpenFileInput(FileName))
{
ks.Load(s, Password);
}
}
}
catch (Java.IO.FileNotFoundException)
{
//ks.Load (null, Password);
LoadEmptyKeyStore(Password);
}
}
public IEnumerable<string> FindAccountsForService(string serviceId)
{
var r = new List<string>();
var postfix = "-" + serviceId;
var aliases = ks.Aliases();
while (aliases.HasMoreElements)
{
var alias = aliases.NextElement().ToString();
if (alias.EndsWith(postfix))
{
var e = ks.GetEntry(alias, prot) as KeyStore.SecretKeyEntry;
if (e != null)
{
var bytes = e.SecretKey.GetEncoded();
var password = System.Text.Encoding.UTF8.GetString(bytes);
r.Add(password);
}
}
}
return r;
}
public void Delete(string serviceId)
{
var alias = MakeAlias(serviceId);
ks.DeleteEntry(alias);
Save();
}
public void Save(string pin, string serviceId)
{
var alias = MakeAlias(serviceId);
var secretKey = new SecretAccount(pin);
var entry = new KeyStore.SecretKeyEntry(secretKey);
ks.SetEntry(alias, entry, prot);
Save();
}
void Save()
{
lock (fileLock)
{
using (var s = context.OpenFileOutput(FileName, FileCreationMode.Private))
{
ks.Store(s, Password);
}
}
}
static string MakeAlias(string serviceId)
{
return "-" + serviceId;
}
class SecretAccount : Java.Lang.Object, ISecretKey
{
byte[] bytes;
public SecretAccount(string password)
{
bytes = System.Text.Encoding.UTF8.GetBytes(password);
}
public byte[] GetEncoded()
{
return bytes;
}
public string Algorithm
{
get
{
return "RAW";
}
}
public string Format
{
get
{
return "RAW";
}
}
}
static IntPtr id_load_Ljava_io_InputStream_arrayC;
void LoadEmptyKeyStore(char[] password)
{
if (id_load_Ljava_io_InputStream_arrayC == IntPtr.Zero)
{
id_load_Ljava_io_InputStream_arrayC = JNIEnv.GetMethodID(ks.Class.Handle, "load", "(Ljava/io/InputStream;[C)V");
}
IntPtr intPtr = IntPtr.Zero;
IntPtr intPtr2 = JNIEnv.NewArray(password);
JNIEnv.CallVoidMethod(ks.Handle, id_load_Ljava_io_InputStream_arrayC, new JValue[]
{
new JValue (intPtr),
new JValue (intPtr2)
});
JNIEnv.DeleteLocalRef(intPtr);
if (password != null)
{
JNIEnv.CopyArray(intPtr2, password);
JNIEnv.DeleteLocalRef(intPtr2);
}
}
Call Create Store in the main activity of Android app first. - This could possibly be improved and remove CreateStrore() from the interface by checking if ks == null in Save and Delete and calling the method if true
iOS
public class IAuthImplementation : IAuth
{
public IEnumerable<string> FindAccountsForService(string serviceId)
{
var query = new SecRecord(SecKind.GenericPassword);
query.Service = serviceId;
SecStatusCode result;
var records = SecKeyChain.QueryAsRecord(query, 1000, out result);
return records != null ?
records.Select(GetAccountFromRecord).ToList() :
new List<string>();
}
public void Save(string pin, string serviceId)
{
var statusCode = SecStatusCode.Success;
var serializedAccount = pin;
var data = NSData.FromString(serializedAccount, NSStringEncoding.UTF8);
//
// Remove any existing record
//
var existing = FindAccount(serviceId);
if (existing != null)
{
var query = new SecRecord(SecKind.GenericPassword);
query.Service = serviceId;
statusCode = SecKeyChain.Remove(query);
if (statusCode != SecStatusCode.Success)
{
throw new Exception("Could not save account to KeyChain: " + statusCode);
}
}
//
// Add this record
//
var record = new SecRecord(SecKind.GenericPassword);
record.Service = serviceId;
record.Generic = data;
record.Accessible = SecAccessible.WhenUnlocked;
statusCode = SecKeyChain.Add(record);
if (statusCode != SecStatusCode.Success)
{
throw new Exception("Could not save account to KeyChain: " + statusCode);
}
}
public void Delete(string serviceId)
{
var query = new SecRecord(SecKind.GenericPassword);
query.Service = serviceId;
var statusCode = SecKeyChain.Remove(query);
if (statusCode != SecStatusCode.Success)
{
throw new Exception("Could not delete account from KeyChain: " + statusCode);
}
}
string GetAccountFromRecord(SecRecord r)
{
return NSString.FromData(r.Generic, NSStringEncoding.UTF8);
}
string FindAccount(string serviceId)
{
var query = new SecRecord(SecKind.GenericPassword);
query.Service = serviceId;
SecStatusCode result;
var record = SecKeyChain.QueryAsRecord(query, out result);
return record != null ? GetAccountFromRecord(record) : null;
}
public void CreateStore()
{
throw new NotImplementedException();
}
}
WP
public class IAuthImplementation : IAuth
{
public IEnumerable<string> FindAccountsForService(string serviceId)
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
string[] auths = store.GetFileNames("MyProg");
foreach (string path in auths)
{
using (var stream = new BinaryReader(new IsolatedStorageFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, store)))
{
int length = stream.ReadInt32();
byte[] data = stream.ReadBytes(length);
byte[] unprot = ProtectedData.Unprotect(data, null);
yield return Encoding.UTF8.GetString(unprot, 0, unprot.Length);
}
}
}
}
public void Save(string pin, string serviceId)
{
byte[] data = Encoding.UTF8.GetBytes(pin);
byte[] prot = ProtectedData.Protect(data, null);
var path = GetAccountPath(serviceId);
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = new IsolatedStorageFileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, store))
{
stream.WriteAsync(BitConverter.GetBytes(prot.Length), 0, sizeof(int)).Wait();
stream.WriteAsync(prot, 0, prot.Length).Wait();
}
}
public void Delete(string serviceId)
{
var path = GetAccountPath(serviceId);
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
store.DeleteFile(path);
}
}
private string GetAccountPath(string serviceId)
{
return String.Format("{0}", serviceId);
}
public void CreateStore()
{
throw new NotImplementedException();
}
}
This is an adaptation of the Xamarin.Auth library (Found Here) but removes the dependency from the Xamarin.Auth library to provide cross platform use through the interface in the PCL. For this reason I have simplified it to only save one string. This is probably not the best implementation but it works in my case. Feel free to expand upon this
There is a nuget package called KeyChain.NET that encapsulated this logic for iOs, Android and Windows Phone.
It's open source and you have find sample at its github repository
More info at this blog post
I am using ZKFinger SDK2.3.3.1 version and Device
Communication Protocol SDK(32Bit Ver6.2.4.1 -- DLL Version : zkemkeeper.dll - 6.2.4.1. I have a small USB fingerprint scanner. When I scan the fingerprint,
I get an array of bytes . I saved it to disc in a bitmap file and jpg both and the fingerprint looks quite good scanned. To set the fingerprint template to a user on the device, i decomporessed fingerprint image, and then call SetUserTmp Function of zkemkeeper.dll.
I am getting size error , (-3) in code.
How can i go further? What is my mistake?
Below is my code for transfering finger from USB device to BioMetric device
bool fullImage = false;
zkfpEng.SaveJPG("Myfirstfinger.jpg");
string strtmp, sRegTemplate;
object pTemplate;
sRegTemplate = zkfpEng.GetTemplateAsStringEx("9");
pTemplate = zkfpEng.DecodeTemplate1(sRegTemplate);
// Note: 10.0Template can not be compressed
zkfpEng.SetTemplateLen(ref pTemplate, 602);
zkfpEng.SaveTemplate("Myfirstfingerprint.tpl", pTemplate);
byte[] TmpData = new byte[700];
TmpData =ObjectToByteArray(pTemplate);
if (bIsConnected == false)
{
MessageBox.Show("Please connect the device first!", "Error");
return;
}
int idwFingerIndex = Convert.ToInt32(cbFingerIndex.Text.Trim());
int idwEnrollNumber = Convert.ToInt32(txtUserID.Text.Trim());
int iTmpLength = 0;
string sdwEnrollNumber = txtUserID.Text.Trim();
axCZKEM1.EnableDevice(iMachineNumber, false);
Cursor = Cursors.WaitCursor;
bool IsSetTmp = false;
IsSetTmp = axCZKEM1.SetUserTmp(iMachineNumber, idwEnrollNumber, idwFingerIndex, ref TmpData[0]);
int errCode = 0;
axCZKEM1.GetLastError(ref errCode);
MessageBox.Show(IsSetTmp.ToString() + " " + errCode.ToString());
if (IsSetTmp == true)
{
MessageBox.Show("User template set successfully!", "Success");
}
else
{
MessageBox.Show("User template not set successfully!", "Error");
}
i think you don't have to convert it to image file, just like Remin said.
here some example. i'm using xaf and mysql db
private void DownloadUserInformationAction_Execute(object sender, SimpleActionExecuteEventArgs e)
{
IObjectSpace os = Application.CreateObjectSpace();
Terminal terminal = (Terminal)View.SelectedObjects[0];
//create new czkemclass obj
CZKEMClass myCZKEMClass = new CZKEMClass();
//connecting the device
myCZKEMClass.Connect_Net(terminal.IPAddress, terminal.Port);
//Initialize variable for store temporary user information
int tMachineNo = 0;
string tEnrollNo = "";
string tName = "";
string tPassword = "";
int tPrivilage = 0;
bool tEnabled = false;
int tFingerIndex;
int tFlag = 0;
string tTemplateData = "";
int tTemplateLength = 0;
myCZKEMClass.EnableDevice(terminal.DeviceId, false);
myCZKEMClass.ReadAllUserID(terminal.DeviceId);
myCZKEMClass.ReadAllTemplate(terminal.DeviceId);
while (myCZKEMClass.SSR_GetAllUserInfo(tMachineNo, out tEnrollNo, out tName, out tPassword, out tPrivilage, out tEnabled))
{
for (tFingerIndex = 0; tFingerIndex < 10; tFingerIndex++)
{
if (myCZKEMClass.GetUserTmpExStr(tMachineNo, tEnrollNo, tFingerIndex, out tFlag, out tTemplateData, out tTemplateLength))
{
EmployeeBiometric employeeBiometric = new EmployeeBiometric(terminal.Session);
//employeeBiometric.EnrollNumber = tEnrollNo;
XPCollection<Employee> employees = new XPCollection<Employee>(terminal.Session);
employeeBiometric.Employee = employees.Where(emp => emp.EnrollNo == tEnrollNo).FirstOrDefault();//(emp => emp.Sequence.ToString() == tEnrollNo).FirstOrDefault();
employeeBiometric.UserName = tName;
employeeBiometric.Password = tPassword;
employeeBiometric.Privilege = (Privilege)Enum.ToObject(typeof(Privilege), tPrivilage);
employeeBiometric.Enabled = tEnabled;
employeeBiometric.FingerprintIndex = tFingerIndex;
employeeBiometric.FingerprintTemplate = tTemplateData;
employeeBiometric.TemplateLength = tTemplateLength;
terminal.Session.CommitTransaction();
}
}
}
myCZKEMClass.EnableDevice(terminal.DeviceId, true);
}
that's method for downloading the your fingerprint image from device to your apps.
and here you can upload it back to another device
private void UploadUserInformationAction_Execute(object sender, PopupWindowShowActionExecuteEventArgs e)
{
IObjectSpace os = Application.CreateObjectSpace();
EmployeeBiometric employeeBiometric = (EmployeeBiometric)View.SelectedObjects[0];
EmployeeBiometricParameter param = (EmployeeBiometricParameter)e.PopupWindowViewCurrentObject;
//create new czkemclass obj
CZKEMClass myCZKEMClass = new CZKEMClass();
//connecting the device
myCZKEMClass.Connect_Net(param.Terminal.IPAddress, param.Terminal.Port);
myCZKEMClass.EnableDevice(param.Terminal.DeviceId, false);
int myCount = View.SelectedObjects.Count;
//Set specific user to fingerprint device
for (int i = 1; i <= myCount; i++)
{
int tMachineNo = param.Terminal.DeviceId;
string tEnrollNo = employeeBiometric.Employee.EnrollNo;//Sequence.ToString();
string tName = employeeBiometric.UserName;
string tPassword = employeeBiometric.Password;
int tPrivilege = (int)employeeBiometric.Privilege;
bool tEnabled = employeeBiometric.Enabled;
int tFingerIndex = employeeBiometric.FingerprintIndex;
string tTmpData = employeeBiometric.FingerprintTemplate;
int tFlag = 1;
if (myCZKEMClass.SSR_SetUserInfo(tMachineNo, tEnrollNo, tName, tPassword, tPrivilege, tEnabled))
{
myCZKEMClass.SetUserTmpExStr(tMachineNo, tEnrollNo, tFingerIndex, tFlag, tTmpData);
}
}
myCZKEMClass.RefreshData(param.Terminal.DeviceId);
myCZKEMClass.EnableDevice(param.Terminal.DeviceId, true);
}
and this is my "Terminal" Class
public partial class Terminal : XPCustomObject
{
Guid fOid;
[Key(AutoGenerate = true), Browsable(false)]
public Guid Oid
{
get { return fOid; }
set { SetPropertyValue<Guid>("Oid", ref fOid, value); }
}
private Branch _Branch;
[RuleRequiredField("", DefaultContexts.Save, "Branch required")]
public Branch Branch
{
get
{
return _Branch;
}
set
{
SetPropertyValue("Branch", ref _Branch, value);
}
}
string fDescription;
[RuleUniqueValue("", DefaultContexts.Save, "The value was already registered within the system.", ResultType = ValidationResultType.Warning)]
[RuleRequiredField("", DefaultContexts.Save, "Description required")]
public string Description
{
get { return fDescription; }
set { SetPropertyValue<string>("Description", ref fDescription, value); }
}
string fIPAddress;
[Size(15)]
public string IPAddress
{
get { return fIPAddress; }
set { SetPropertyValue<string>("IPAddress", ref fIPAddress, value); }
}
private int _Port;
public int Port
{
get
{
return _Port;
}
set
{
SetPropertyValue("Port", ref _Port, value);
}
}
string fDeviceDescription;
public string DeviceDescription
{
get { return fDeviceDescription; }
set { SetPropertyValue<string>("DeviceDescription", ref fDeviceDescription, value); }
}
private int _DeviceId;
public int DeviceId
{
get
{
return _DeviceId;
}
set
{
SetPropertyValue("DeviceId", ref _DeviceId, value);
}
}
private bool _Disabled;
public bool Disabled
{
get
{
return _Disabled;
}
set
{
SetPropertyValue("Disabled", ref _Disabled, value);
}
}}
Read the FP as string and push the same string to the Biometric device without any compression or conversion.
I have an object I want to store in the IsolatedStorageSettings, which I wan't to reuse when the application restarts.
My problem lies in that the code I have written for some reason does not remember the object when trying to access the key upon restarting it.
namespace MyNameSpace
{
public class WindowsPhoneSettings
{
private const string SelectedSiteKey = "SelectedSite";
private IsolatedStorageSettings isolatedStore = IsolatedStorageSettings.ApplicationSettings;
private T RetrieveSetting<T>(string settingKey)
{
object settingValue;
if (isolatedStore.TryGetValue(settingKey, out settingValue))
{
return (T)settingValue;
}
return default(T);
}
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;
if (isolatedStore.Contains(Key))
{
if (isolatedStore[Key] != value)
{
isolatedStore[Key] = value;
valueChanged = true;
}
}
else
{
isolatedStore.Add(Key, value);
valueChanged = true;
}
return valueChanged;
}
public MobileSiteDataModel SelectedSite
{
get
{
return RetrieveSetting<MobileSiteDataModel>(SelectedSiteKey);
}
set
{
AddOrUpdateValue(SelectedSiteKey, value);
isolatedStore.Save();
}
}
}
}
I then instantiate WindowsPhoneSettings in App.xaml.cs and make a public getter and setter for it. To be able to access it in the whole application. Debugging this shows that the right object gets stored in the isolated store, but when closing the app and reopening it isolated store seems to be empty. I have tried this on both the emulator and a real device. As you can see I do call the save method when setting the object.
What am I doing wrong here?
I ended up saving the settings to a file in the isolated storage as IsolatedStorageSettings never seemed to work.
So my code ended up like this:
public class PhoneSettings
{
private const string SettingsDir = "settingsDir";
private const string SettingsFile = "settings.xml";
public void SetSettings(Settings settings)
{
SaveSettingToFile<Settings>(SettingsDir, SettingsFile, settings);
}
public Settings GetSettings()
{
return RetrieveSettingFromFile<Settings>(SettingsDir, SettingsFile);
}
private T RetrieveSettingFromFile<T>(string dir, string file) where T : class
{
IsolatedStorageFile isolatedFileStore = IsolatedStorageFile.GetUserStoreForApplication();
if (isolatedFileStore.DirectoryExists(dir))
{
try
{
using (var stream = new IsolatedStorageFileStream(System.IO.Path.Combine(dir, file), FileMode.Open, isolatedFileStore))
{
return (T)SerializationHelper.DeserializeData<T>(stream);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Could not retrieve file " + dir + "\\" + file + ". With Exception: " + ex.Message);
}
}
return null;
}
private void SaveSettingToFile<T>(string dir, string file, T data)
{
IsolatedStorageFile isolatedFileStore = IsolatedStorageFile.GetUserStoreForApplication();
if (!isolatedFileStore.DirectoryExists(dir))
isolatedFileStore.CreateDirectory(dir);
try
{
string fn = System.IO.Path.Combine(dir, file);
if (isolatedFileStore.FileExists(fn)) isolatedFileStore.DeleteFile(fn); //mostly harmless, used because isolatedFileStore is stupid :D
using (var stream = new IsolatedStorageFileStream(fn, FileMode.CreateNew, FileAccess.ReadWrite, isolatedFileStore))
{
SerializationHelper.SerializeData<T>(data, stream);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Could not save file " + dir + "\\" + file + ". With Exception: " + ex.Message);
}
}
}
And a settings class just containing the stuff I want to save. This could be:
class Settings
{
private string name;
private int id;
public string Name
{
get { return name; }
set { name = value; }
}
public int Id
{
get { return id; }
set { id = value; }
}
}
EDIT: Sample of how SerializationHelper could be implemented
public static class SerializationHelper
{
public static void SerializeData<T>(this T obj, Stream streamObject)
{
if (obj == null || streamObject == null)
return;
var ser = new DataContractJsonSerializer(typeof(T));
ser.WriteObject(streamObject, obj);
}
public static T DeserializeData<T>(Stream streamObject)
{
if (streamObject == null)
return default(T);
var ser = new DataContractJsonSerializer(typeof(T));
return (T)ser.ReadObject(streamObject);
}
}
Objects stored in IsolatedStorageSettings are serialised using the DataContractSerializer and so must be serializable. Ensure they can be or serialize (and deserialize) them yourself before adding to (and after removing from) ISS.
If the items aren't there when trying to retrieve then it may be that they couldn't be added in the first place (due to a serialization issue).
Here is the code I use to save an object to isolated storage and to load an object from isolated storage -
private void saveToIsolatedStorage(string keyname, object value)
{
IsolatedStorageSettings isolatedStore = IsolatedStorageSettings.ApplicationSettings;
isolatedStore.Remove(keyname);
isolatedStore.Add(keyname, value);
isolatedStore.Save();
}
private bool loadObject(string keyname, out object result)
{
IsolatedStorageSettings isolatedStore = IsolatedStorageSettings.ApplicationSettings;
result = null;
try
{
result = isolatedStore[keyname];
}
catch
{
return false;
}
return true;
}
Here is code I use to call the above -
private void SaveToIsolatedStorage()
{
saveToIsolatedStorage("GameData", GameData);
}
private void LoadFromIsolatedStorage()
{
Object temp;
if (loadObject("GameData", out temp))
{
GameData = (CGameData)temp;
}
else
{
GameData.Reset();
}
}
Note that the objects I save and restore like this are small and serializable. If my object contains a 2 dimensional array or some other object which is not serializable then I perform my own serialization and deserialization before using iso storage.
What if you changed RetrieveSetting<T> to this:
private T RetrieveSetting<T>(string settingKey)
{
T settingValue;
if(isolatedStore.TryGetValue(settingKey, out settingValue))
{
return (T)settingValue;
}
return default(T);
}
Notice that the object being fetched is being declared as type T instead of object.
would anyone have a working example of an amazon ITEMLOOKUP ?>
i have the following code but it does not seem to work:
string ISBN = "0393326381";
string ASIN = "";
if (!(string.IsNullOrEmpty(ISBN) && string.IsNullOrEmpty(ASIN)))
{
AWSECommerceServicePortTypeChannel service = new AWSECommerceServicePortTypeChannel();
ItemLookup lookup = new ItemLookup();
ItemLookupRequest request = new ItemLookupRequest();
lookup.AssociateTag = secretKey;
lookup.AWSAccessKeyId = accessKeyId;
if (string.IsNullOrEmpty(ASIN))
{
request.IdType = ItemLookupRequestIdType.ISBN;
request.ItemId = new string[] { ISBN.Replace("-", "") };
}
else
{
request.IdType = ItemLookupRequestIdType.ASIN;
request.ItemId = new string[] { ASIN };
}
request.ResponseGroup = new string[] { "OfferSummary" };
lookup.Request = new ItemLookupRequest[] { request };
response = service.ItemLookup(lookup);
if (response.Items.Length > 0 && response.Items[0].Item.Length > 0)
{
Item item = response.Items[0].Item[0];
if (item.MediumImage == null)
{
//bookImageHyperlink.Visible = false;
}
else
{
//bookImageHyperlink.ImageUrl = item.MediumImage.URL;
}
//bookImageHyperlink.NavigateUrl = item.DetailPageURL;
//bookTitleHyperlink.Text = item.ItemAttributes.Title;
//bookTitleHyperlink.NavigateUrl = item.DetailPageURL;
if (item.OfferSummary.LowestNewPrice == null)
{
if (item.OfferSummary.LowestUsedPrice == null)
{
//priceHyperlink.Visible = false;
}
else
{
//priceHyperlink.Text = string.Format("Buy used {0}", item.OfferSummary.LowestUsedPrice.FormattedPrice);
//priceHyperlink.NavigateUrl = item.DetailPageURL;
}
}
else
{
//priceHyperlink.Text = string.Format("Buy new {0}", item.OfferSummary.LowestNewPrice.FormattedPrice);
//priceHyperlink.NavigateUrl = item.DetailPageURL;
}
if (item.ItemAttributes.Author != null)
{
//authorLabel.Text = string.Format("By {0}", string.Join(", ", item.ItemAttributes.Author));
}
else
{
//authorLabel.Text = string.Format("By {0}", string.Join(", ", item.ItemAttributes.Creator.Select(c => c.Value).ToArray()));
}
/*
ItemLink link = item.ItemLinks.Where(i => i.Description.Contains("Wishlist")).FirstOrDefault();
if (link == null)
{
//wishListHyperlink.Visible = false;
}
else
{
//wishListHyperlink.NavigateUrl = link.URL;
}
* */
}
}
}
the problem is with this:
thisshould be defined differently but i do not know how AWSECommerceServicePortTypeChannel service = new AWSECommerceServicePortTypeChannel();
Say, that code looks awful familiar. You're missing the Endpoint signing piece from when they switched over to requiring that you add message signing. You need to add a behavior on your client. Here's the change to your code above:
if (!(string.IsNullOrEmpty(ISBN) && string.IsNullOrEmpty(ASIN)))
{
AWSECommerceServicePortTypeClient client = new AWSECommerceServicePortTypeClient();
client.ChannelFactory.Endpoint.Behaviors.Add(
new Amazon.AmazonSigningEndpointBehavior(
accessKeyId,
secretKey);
ItemLookup lookup = new ItemLookup();
ItemLookupRequest request = new ItemLookupRequest();
lookup.AssociateTag = accessKeyId;
lookup.AWSAccessKeyId = secretKey;
//... etc.
And here's the Endpoint (I can't take credit for this, I wish I could remember who should):
namespace Amazon
{
public class AmazonSigningEndpointBehavior : IEndpointBehavior {
private string accessKeyId = "";
private string secretKey = "";
public AmazonSigningEndpointBehavior(string accessKeyId, string secretKey) {
this.accessKeyId = accessKeyId;
this.secretKey = secretKey;
}
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime) {
clientRuntime.MessageInspectors.Add(new AmazonSigningMessageInspector(accessKeyId, secretKey));
}
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher) { return; }
public void Validate(ServiceEndpoint serviceEndpoint) { return; }
public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters) { return; }
}
}
Oh. And you'll need the MessageInspector for that to work.
namespace Amazon
{
public class AmazonSigningMessageInspector : IClientMessageInspector {
private string accessKeyId = "";
private string secretKey = "";
public AmazonSigningMessageInspector(string accessKeyId, string secretKey) {
this.accessKeyId = accessKeyId;
this.secretKey = secretKey;
}
public object BeforeSendRequest(ref Message request, IClientChannel channel) {
// prepare the data to sign
string operation = Regex.Match(request.Headers.Action, "[^/]+$").ToString();
DateTime now = DateTime.UtcNow;
string timestamp = now.ToString("yyyy-MM-ddTHH:mm:ssZ");
string signMe = operation + timestamp;
byte[] bytesToSign = Encoding.UTF8.GetBytes(signMe);
// sign the data
byte[] secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
HMAC hmacSha256 = new HMACSHA256(secretKeyBytes);
byte[] hashBytes = hmacSha256.ComputeHash(bytesToSign);
string signature = Convert.ToBase64String(hashBytes);
// add the signature information to the request headers
request.Headers.Add(new AmazonHeader("AWSAccessKeyId", accessKeyId));
request.Headers.Add(new AmazonHeader("Timestamp", timestamp));
request.Headers.Add(new AmazonHeader("Signature", signature));
return null;
}
public void AfterReceiveReply(ref Message reply, object correlationState) { }
}
}
And finally, the Header:
namespace Amazon
{
public class AmazonHeader : MessageHeader
{
private string name;
private string value;
public AmazonHeader(string name, string value)
{
this.name = name;
this.value = value;
}
public override string Name { get { return name; } }
public override string Namespace { get { return "http://security.amazonaws.com/doc/2007-01-01/"; } }
protected override void OnWriteHeaderContents(XmlDictionaryWriter xmlDictionaryWriter, MessageVersion messageVersion)
{
xmlDictionaryWriter.WriteString(value);
}
}
}
Yes, they made it complicated when they started requiring message signing...
A simple and easy library is available on nuget.
PM> Install-Package Nager.AmazonProductAdvertising
Example
var authentication = new AmazonAuthentication("accesskey", "secretkey");
var client = new AmazonProductAdvertisingClient(authentication, AmazonEndpoint.US);
var result = await client.GetItemsAsync("B00BYPW00I");
To perform a lookup for anything other then an ASIN, you need to specify the "SearchIndex" property. You can simply set it to "All".
var request = new ItemLookupRequest();
request.ItemId = new[] {upcCode};
request.IdType = ItemLookupRequestIdType.UPC;
request.IdTypeSpecified = true;
request.SearchIndex = "All";
Here is a link to the documentation: http://docs.amazonwebservices.com/AWSECommerceService/2011-08-01/DG/index.html?ItemLookup.html. Note the description of the SearchIndex parameter:
Constraint:If ItemIdis an ASIN, a search index cannot be specified in
the request. Required for non-ASIN ItemIds.
I actually built a little wrapper around it so it hands you back a handy object graph. I have the source up on BitBucket and a little more about it on the C# Amazon ItemLookup page.
C# Amazon ItemLookup
You can make calls like:
var item = client.LookupByAsin("B0037X9N5U");
double? price = item.GetLowestPrice();