So I have a code first EF 6 layer which has a Contact class of:
public class Contact
{
[Key]
public int Id { get; set; }
[MaxLength(50)]
public string Prefix { get; set; }
[MaxLength(50)]
public string Suffix { get; set; }
[MaxLength(50)]
public string FirstName { get; set; }
[MaxLength(50)]
public string MiddleName { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
[NotMapped]
[DisplayName("Full Name")]
public string FullName
{
get
{
string tempName =
(!string.IsNullOrEmpty(Prefix) ? Prefix + " " : "") +
(!string.IsNullOrEmpty(FirstName) ? FirstName + " " : "") +
(!string.IsNullOrEmpty(MiddleName) ? MiddleName + " " : "") +
(!string.IsNullOrEmpty(LastName) ? LastName + " " : "") +
(!string.IsNullOrEmpty(Suffix) ? Suffix + " " : "");
return tempName.Trim();
}
}
[MaxLength(50)]
public string JobTitle { get; set; }
public bool? Primary { get; set; }
public bool? Inactive { get; set; }
public int? Customer_Id { get; set; }
[ForeignKey("Customer_Id")]
public virtual Customer Customer { get; set; }
public virtual ICollection<Email> Emails { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
I have an ASP.NET Web API 2 service running that offers up a list of contacts, but when I perform an OData query of $filter=contains(tolower(FullName), tolower('smith')) I get a BadRequest response. I verified in the WebAPI get method that it is successfully getting results from the database, but it sends back a BadRequest error.
It definitely has something to do with the FullName field either being a calculated field or because it has the NotMapped attribute. When I change the OData query to $filter=contains(tolower(LastName), tolower('smith')) it works fine. I also tried using the display name of "Full Name" in the query instead of "FullName" and that too did not work.
Is there something I need to do to make OData play nice with a calculated or notmapped field?
Implement an OData function on your ContactsController that takes a string for comparison and returns the filtered set of Contacts. Something like:
[HttpGet]
[ODataRoute("Contacts/Default.FullNameContains(value={value})")]
public IHttpActionResult FullNameContains(string value)
{
value = value.ToLower();
return Ok(db.Contacts.ToList().Where(c => c.FullName.Contains(value)));
}
Because FullName
is computed, the function must perform the filtering in memory.