I user ServiceStack autoquery to load information. I have a class like this one:
public class QueryItem: QueryDb<Item>
{
public string Name { get; set; }
public DateTime? BirthdayNotEqualTo { get; set; }
}
As written in the documentation, I should be able to receive all items that are not null in the Birthday column like this:
QueryResponse<Item> item = jsonServiceClient.Get(new QueryItem {
BirthdayNotEqualTo = null
});
However, I receive all items, regardless of the null-filter above. How can I change that? The values in the database are correctly set to null.
It's not possible to send a null value using the ServiceClient. A null value, like default(DateTime?) means no value, so there's no "null filter" sent and your query is the same and indistinguishable from sending an Empty QueryItem DTO.
You'd need to use a Custom AutoQuery Implementation or a Customizable Query like:
[QueryDbField(Template = "{Field} IS NOT NULL", Field = "Birthday")]
public bool? BirthdayIsNotNull { get; set; }
Related
I have a model -
public class EmployeeModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Designation { get; set; }
public double? Salary { get; set; }
}
and a LINQ method syntax like -
public List<EmployeeModel> GetEmployees()
{
using (var DbCon = new OfficeEntities())
{
var result = DbCon.Employee.Select(x => new EmployeeModel()
{
Id = x.Id,
Name = x.Name
//Salary = x.Salary,
//Designation = x.Designation
})
.ToList();
return result;
}
}
I have commented out salary and designation but even though it prints with
key : salary and for value i:null="true" why
result comes like this
<EmployeeModel>
<Designation i:nil="true"/>
<Id>1</Id>
<Name>Sulochana </Name>
<Salary i:nil="true"/>
</EmployeeModel>
Even though commented/removed the parameters in the query, why it is appearing in the result. Kindly help
Because you didn't include those properties in the projection.
This has a special meaning for the client to interpret, it's not that these fields have a null value, these fields we're not included in the projection, so their values are indeterminate.
If the client has requesting a projection with $select=Id,Name then these fields would not have been included at all, but because the client is expecting all the fields this is how the API expresses to the client that the fields we're deliberately omitted, but to satisfy the return contract the fields must be provided in some form.
This answer is assuming OP is writing an OData service, but the same concept applies with Linq to Entities in general. If the Linq expression is projecting into a model type, but not including certain fields, then those fields will have an uninitialized value on the model instances that are projected out.
You are creating an EmployeeModel object in the Select projection. Hence, Salary and Designation are being initialized with their default values, even though you didn't set values for them. Then after serializing all properties are present in the result.
If you are expecting only Id and Name in the output/result, then define a type in that shape -
public class EmployeeInfo
{
public int Id { get; set; }
public string Name { get; set; }
}
and create an object of that type in the projection -
var result = DbCon.Employee.Select(x => new EmployeeInfo()
{
Id = x.Id,
Name = x.Name
})
.ToList();
Imagine having an entity like this example:
public class Thing
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
How can I add a contraint-ish so that only ONE of all the Things with a certain name can have true for IsActive?
In other words, we can have multiple Things with the same name, but at any given time only one can have an IsActive which is true - the others need to have false for IsActive. So if we want to add or update one, it needs to check if the new value is true for IsActive that it won't make a "conflict".
Is this somehow possible?
One option would be to adopt actions for changing entity state rather than public setters. For instance, in most cases my entities reside in a Domain assembly along with the DbContext and things like Repository classes. "Things" would reside under a container entity to be uniquely associated.
public class Thing
{
public int Id { get; internal set;}
public string Name { get; internal set; }
public bool IsActive { get; internal set; }
}
public class Container
{
public int Id { get; internal set; }
public virtual ICollection<Thing> Things { get; internal set; } = new List<Thing>();
public void AddThing(string name, bool isActive = true)
{
var existingActiveThing = Things.SingleOrDefault(x => x.Name == name && x.IsActive);
if(isActive && existingActiveThing != null)
existingActiveThing.IsActive = false;
var newThing = new Thing { Name = name, IsActive = isActive };
Things.Add(newThing);
}
public void ActivateThing(int thingId)
{
var thing = Things.Single(x => x.Id == thingId);
if(thing.IsActive)
return; // Nothing to do.
var existingActiveThing = Things.SingleOrDefault(x => x.Name == thing.Name && x.IsAcitve);
if (existingActiveThing != null)
existingActiveThing.IsActive = false;
thing.IsActive = true;
}
// And so forth for instance Renaming a Thing or other allowed actions.
}
Container could be a containing entity, or these actions could be encapsulated in a domain level service class initialized with the collection of Things or access to the DbContext if Things are a top-level entity. The setters are marked as Internal to require the use of a domain level method to mutate state rather than arbitrary updates via the setters. This technique can be useful where you want to enforce validation across multiple entities or multiple fields to ensure the entity state at every point in time is valid. (I.e. updating address fields as a set of values to be validated rather than 1 field at a time, where you can change Country or such leaving the entity in an invalid combination of values that cannot pass validation)
I admit I found many similar question but not exactly this :)
I have entities with data annotation attributes:
public class BaseEntity
{
[Required, DataType(DataType.DateTime)]
public DateTime CreatedAt { get; set; }
public string CreatedBy { get; set; }
}
public class ExchangeRights : BaseEntity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required, DataType(DataType.EmailAddress)]
public string Email { get; set; }
}
And I try to validate an empty object:
ExchangeRights r = new ExchangeRights();
ValidationContext vCtx = new ValidationContext(r);
List<ValidationResult> res = new List<ValidationResult>();
Validator.TryValidateObject(r, vCtx, res, true);
It's only result one Error. That the Email field is required. But not indicate that there is not email format and not indicate that the CreatedAt field is not set (ok maybe it's because non nullable value type)
But here is the twist.
First I really want that every error should be indicated it's empty, it's not email format.
But the bigger problem is that if I set the Email to "asd" the method return no error.
However it's wierd if I use this Entity with strongly typed view (using MVC4 with Razor) on a create page all works fine.
The form indicate that the Email is requires or if I set than it says not valid email address format.
Also indicates that the CreatedAt field is required (with or without the Required attribute!!) and if I set it it says not valid datetime format.
Any help/idea/hunch would be appreciated.
Thanks,
Péter
for the validation of the email you should use the EmailAddress validation attribute. [EmailAddress].
For the CreatedAt, as DateTime is a non nullable type, when you create a ExchangeRights instance, the property CreatedAt is populated with DateTime.MinValue. So the property has a value. If you want a differente behavior, use DateTime? instead of DateTime.
Hope this helps.
You can use the DataTypeAttribute attribute for the following reasons: to provide additional type information for a data field, to associate a custom field template with a data field. DataTypeAttribute doesn't used for validation it's can be used for provide some additional metadata information. To validate email you can use DataAnnotations Extensions EmailAttribute or write you own validation attribute.
You can find more information in
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.datatypeattribute.aspx
In my registration page I have land line phone number and mobile number fields.
I need to ensure that the user needs to add at least one phone number either the land line or mobile.
How do I do this?
Thanks
Arnab
You could write a custom validation attribute and decorate your model with it:
[AttributeUsage(AttributeTargets.Class)]
public class AtLeastOnePhoneAttribute: ValidationAttribute
{
public override bool IsValid(object value)
{
var model = value as SomeViewModel;
if (model != null)
{
return !string.IsNullOrEmpty(model.Phone1) ||
!string.IsNullOrEmpty(model.Phone2);
}
return false;
}
}
and then:
[AtLeastOnePhone(ErrorMessage = "Please enter at least one of the two phones")]
public class SomeViewModel
{
public string Phone1 { get; set; }
public string Phone2 { get; set; }
}
For more advanced validation scenarios you may take a look at FluentValidation.NET or Foolproof.
Adding a solution that can be applied to individual properties, rather than overriding the validation method at the class level...
Create the following custom attribute. Note the "otherPropertyName" parameter in the constructor. This will allow you to pass in the other property to use in validation.
public class OneOrOtherRequiredAttribute: ValidationAttribute
{
public string OtherPropertyName { get; set; }
public OneOrOtherRequiredAttribute(string otherPropertyName)
{
OtherPropertyName = otherPropertyName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var otherPropertyInfo = validationContext.ObjectType.GetProperty(OtherPropertyName);
var otherValue = (string)otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
if (string.IsNullOrEmpty(otherValue) && string.IsNullOrEmpty((string)value))
{
return new ValidationResult(this.ErrorMessage); //The error message passed into the Attribute's constructor
}
return null;
}
}
You can then decorate your properties like so: (be sure to pass in the name of the other property to compare with)
[OneOrOtherRequired("GroupNumber", ErrorMessage = "Either Group Number or Customer Number is required")]
public string CustomerNumber { get; set; }
[OneOrOtherRequired("CustomerNumber", ErrorMessage="Either Group Number or Customer Number is required")]
public string GroupNumber { get; set; }
I'm using an Entity Framework data model to drive a Dynamic Data website for use by users to update data.
One of the entities contains a non-nullable string property (Description). In the database, one of the rows has an empty Description (not null but an empty string). When I try to update the Description I get the following validation error: "This property cannot be set to a null value".
If I manually update the Description in the database and then edit the property, it works as expected. But as soon as I change the Description in the database back to an empty string, the validation error occurs. The error happens on Description's setter.
So I've tried adding an additional string property called CustomDescription which basically wraps Description, made Description a ScaffoldColumn(false) in the entity's metadata and added the new property to the entity's metadata.
[ScaffoldColumn(true)]
public string CustomDescription
{
get { return this.Description; }
set {
if (value == null)
{
value = string.Empty;
}
this.Description = value;
}
}
However what do I need to add to this property in order to get it to display on the dynamic data site?
Problem is that old value was empty string in Non-Nullable field.
By default framework is converting it to null.
To fix the error just add the following attribute to your field:
[DisplayFormat(ConvertEmptyStringToNull = false)]
public object Description { get; set; }
In the corresponding Metadata class, just refernce it as you would an actual field:
[MetadataType(typeof(MyClassMetadata))]
public partial class MyClass
{
[ScaffoldColumn(true)]
public string CustomString
{
return "foo";
}
}
public class MyClassMetadata
{
[Display(Name = "Custom")]
public object CustomString { get; set; }
}