Hi, I know this is old, but I thought I would add some additions to Iyendesβs answer to help people who, like me, had the same problem and spent hours watching forums for an answer (there were several, but none of them was any example that you could follow), it is not difficult to understand, but with the example I could solve this in 10 minutes, and not spend several hours.
My problems were that we have custom structs type types in our application, an example I will use is EmailAddress. Unfortunately, in Ravendb we could not run queries against these types without defining a custom serializer.
Our Type value was as follows:
[DataContract(Namespace = DataContractNamespaces.ValueTypes)] public struct EmailAddress : IEquatable<EmailAddress> { private const char At = '@'; public EmailAddress(string value) : this() { if (value == null) { throw new ArgumentNullException("value"); } this.Value = value; } public bool IsWellFormed { get { return Regex.IsMatch(this.Value, @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"); } } public string Domain { get { return this.Value.Split(At)[1]; } } [DataMember(Name = "Value")] private string Value { get; set; } public static bool operator ==(EmailAddress left, EmailAddress right) { return left.Equals(right); } public static bool operator !=(EmailAddress left, EmailAddress right) { return !left.Equals(right); } public override bool Equals(object obj) { if (obj == null) { return false; } return this.Equals(new EmailAddress(obj.ToString())); } public override int GetHashCode() { return this.Value.GetHashCode(); } public override string ToString() { return this.Value; } public bool Equals(EmailAddress other) { return other != null && this.Value.Equals(other.ToString(), StringComparison.OrdinalIgnoreCase); } }
The type of document we wanted to save and the request would look something like this.
public class Customer { public Guid Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public EmailAddress Email { get; set; } }
A custom serializer to store our email as a raw string, and then convert it back to its value type when searching, looks like this:
public class EmailConverterTest : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(EmailAddress); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { EmailAddress actualAddress = new EmailAddress(reader.Value.ToString()); return actualAddress; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { EmailAddress actualAddress = (EmailAddress)value; string stringEmail = actualAddress.ToString(); writer.WriteValue(stringEmail); } }
Finally, I plugged it in and was able to query everything like this:
public static void serializercustom(Newtonsoft.Json.JsonSerializer serialiser) { serialiser.Converters.Add(new EmailConverterTest()); } public static void TestCustomer() { using (var documentStore = new DefaultDocumentStore()) { documentStore.ConnectionStringName = Properties.Settings.Default.SandBoxConnection; documentStore.Initialize(); documentStore.Conventions.CustomizeJsonSerializer = new Action<Newtonsoft.Json.JsonSerializer>(serializercustom); var customer = new Customer { Id = Guid.NewGuid(), FirstName = "TestFirstName", LastName = "TestLastName", Email = new EmailAddress(" testemail@gmail.com ") };