I'm using ASP.NET MVC with EF code first.
In my model I have a property that can be null:
public byte[] Avatar { get; set; }
However, when I run update-database I get:
Cannot insert the value NULL into column 'Avatar', table 'temp';
column does not allow nulls. UPDATE fails.
I don't have a dataannotation specifying the property to be required, nor is the property a foreign key.
Any ideas?
Further updates:
If I delete my database and force a new one to be created with 'update-database -verbose' then I can see the table being created specifically forces a NOT NULL flag on my field:
CREATE TABLE [dbo].[UserProfile] (
[UserId] [int] NOT NULL IDENTITY,
[UserName] [nvarchar](max),
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[EmailAddress] [nvarchar](50) NOT NULL,
[WorkPhone] [nvarchar](20),
[MobilePhone] [nvarchar](20),
[HireDate] [datetime],
[Avatar] [image] NOT NULL,
[AvatarMimeType] [nvarchar](max),
CONSTRAINT [PK_dbo.UserProfile] PRIMARY KEY ([UserId])
)
My full model:
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
[Required]
[Display(Name = "First name")]
[MaxLength(50, ErrorMessage = "First Name cannot be longer than 50 characters.")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
[MaxLength(50, ErrorMessage = "Last Name cannot be longer than 50 characters.")]
public string LastName { get; set; }
[Display(Name = "Full Name")]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
[Required]
[RegularExpression("^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*#[a-z0-9]+(\\.[a-z0-9]+)*\\.([a-z]{2,4})$", ErrorMessage = "Not a valid email address")]
[Display(Name = "Email Address")]
[MaxLength(50, ErrorMessage = "Email Address cannot be longer than 50 characters.")]
public string EmailAddress { get; set; }
[Display(Name = "Work Phone")]
[MaxLength(20, ErrorMessage = "Work Phone cannot be longer than 20 characters.")]
public string WorkPhone { get; set; }
[Display(Name = "Mobile Phone")]
[MaxLength(20, ErrorMessage = "Mobile Phone cannot be longer than 20 characters.")]
public string MobilePhone { get; set; }
[Display(Name = "Hire Date")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime? HireDate { get; set; }
[ValidateFile(ErrorMessage = "Please select a PNG, JPG or GIF image smaller than 2MB")]
[Column(TypeName = "image")]
public byte[] Avatar { get; set; }
public string AvatarMimeType { get; set; }
[Column(TypeName = "image")]
public byte[] Avatar { get; set; }
I think you need to tell EF that you are using it in this fashion. Try using the image annotation as above.
This will make sure your field is created as the image type; designed for this type of scenario.
EDIT: Please see the comments for the answer that eventually worked.
Change it from byte[] to byte?[]
It isn't maybe direct answer but useful workaround. When you are creating entity,initalize Avatar field:
public void CreateSomething(Something something)
{
something.Avatar= new byte[0],
Db.Somethings.Add(something);
Db.SaveChanges();
}
For EF Avatar now is not null so everything is ok.
Hope,it will help.
Try the solution noted here: What is the data annotation for changing nullable and not null data types?
I.E:
Change it from byte[] to byte?
Cheers
Related
Here's the problem. I have a [Range] attribute above the SalesCenterId property of my ViewModel. On my view side I have dropdown list with a default option "---Select---" and some Sales Centers with different Id-s. For example, if I set the Range between 0 and 1, then when selecting a sales center with Id = 2, my custom error message works. But when i select the default option "---Select---" (id = 0 , range between 1 and 1000) then the default error message is displayed: "The value '---Select---' is not valid for SalesCenterId." Why is this? I've checked through debugging and saw that when choosing "---Select---" Id = 0.
I'm using MVC core 2.2
ViewModel:
public class OrderViewModel
{
[Required(ErrorMessage = "*The Last Name field is required.")]
public string LastName { get; set; }
[Required(ErrorMessage = "*The First Name field is required.")]
public string FirstName { get; set; }
[Required(ErrorMessage = "*The Middle Name field is required.")]
public string MiddleName { get; set; }
[Required(ErrorMessage = "*The Pin field is required.")]
public string Pin { get; set; }
[Required(ErrorMessage = "*The Phone field is required.")]
public string Phone { get; set; }
[Required(ErrorMessage = "*The Email field is required.")]
public string Email { get; set; }
[Required(ErrorMessage = "*The Serial Number field is required.")]
public string SerialNumber { get; set; }
[Range(1, 1000, ErrorMessage="jgsjfdngi")]
public int SalesCenterId { get; set; }
[Range(1, 999, ErrorMessage = "jgsjfdngi")]
public int OrderTimeId { get; set; }
[JsonIgnore]
[IgnoreDataMember]
public SalesCenter SalesCenter { get; set; }
public List<CartItem> Cart { get; set; }
public OrderTime OrderTime { get; set; }
public decimal TotalPrice { get; set; }
}
Validation message span:
<p><span asp-validation-for="SalesCenterId" class="error"></span></p>
Select list:
<td>
<select id="SCID" asp-for="SalesCenterId" asp-items="#ViewBag.SalesCenterId" class="input" style="width:200px; height:30px; padding:1.5%">
<option>---#Localizer["Select"]---</option>
</select><br />
</td>
I expect the output to be "jgsjfdngi", but the actual output is "The value '---Select---' is not valid for SalesCenterId."
Have you used ModelState.IsValid in your controller??
Try this
if (ModelState.IsValid)
{
// your code
return View();
}
return View();
I have define a Entity call Users...that is mapped to Users table with EF.
public partial class Users
{
public long User_id { get; set; }
[Required]
[StringLength(30, ErrorMessage = "LastName cannot be longer than 30 characters.")]
public string LastName { get; set; }
[Required]
[StringLength(30, ErrorMessage = "Name cannot be longer than 30 characters.")]
public string Name { get; set; }
public int Country_id { get; set; }
public Nullable<int> State_id { get; set; }
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string Email { get; set; }
public System.DateTime CreationDate { get; set; }
public Nullable<System.DateTime> UpDateTime { get; set; }
[RegularExpression(#"^.{5,}$", ErrorMessage = "Minimum 3 characters required")]
[Required]
[StringLength(9, MinimumLength = 3, ErrorMessage = "Password cannot be longer than 9 characters.")]
public string Password { get; set; }
public int Rol_id { get; set; }
public byte[] Picture { get; set; }
public string CodArea { get; set; }
public string PhoneNumber { get; set; }
public virtual Ages Ages { get; set; }
public virtual Countries Countries { get; set; }
[NotMapped] // Does not effect with your database
[RegularExpression(#"^.{5,}$", ErrorMessage = "Minimum 3 characters required")]
[StringLength(9, MinimumLength = 3, ErrorMessage = "Confirm Password cannot be longer than 9 characters.")]
[Compare("Password")]
public virtual string ConfirmPassword { get; set; }
}
I use this entity to inherit from my Create View...
When I Update, I do not need a lot of this properties. I defined a a new Entity called UserEditView with this definition. I do not have Password and ConfirmPassword.
public partial class UserEditView
{
public long User_id { get; set; }
[Required]
[StringLength(30, ErrorMessage = "LastName cannot be longer than 30 characters.")]
public string LastName { get; set; }
[Required]
[StringLength(30, ErrorMessage = "Name cannot be longer than 30 characters.")]
public string Name { get; set; }
public int Country_id { get; set; }
public Nullable<int> State_id { get; set; }
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string Email { get; set; }
public System.DateTime CreationDate { get; set; }
public Nullable<System.DateTime> UpDateTime { get; set; }
[RegularExpression(#"^.{5,}$", ErrorMessage = "Minimum 3 characters required")]
[Required]
[StringLength(9, MinimumLength = 3, ErrorMessage = "Password cannot be longer than 9 characters.")]
public byte[] Picture { get; set; }
public string CodArea { get; set; }
public string PhoneNumber { get; set; }
}
I defined a Mapper in my Global asax and Ignore those properties I dot not need.
cfg.CreateMap<Users, UserEditView>();
cfg.CreateMap<UserEditView, Users>()
.ForMember(x => x.CreationDate, opt => opt.Ignore())
.ForMember(x => x.Password, opt => opt.Ignore())
.ForMember(x => x.ConfirmPassword, opt => opt.Ignore())
.ForMember(x => x.Rol_id, opt => opt.Ignore());
}
When I Update, I mapp UserEditView to Users so I can call _db.SaveChanges() like this.
public async Task<ActionResult> Edit(UserEditView model, System.Web.HttpPostedFileBase image = null)
{
try
{
if (!ModelState.IsValid)
{
return View(model);
}
model.user.UpDateTime = DateTime.Now;
model.user.IP = Request.UserHostAddress;
model.user.Url = UserValidation.EncriptacionURL(model.user.Email);
var user = _db.Users.FirstOrDefault(p => p.User_id == model.user.User_id);
if (user == null)
{
return View(model);
}
Mapper.Map<UserEditView, Users>(model.user, user);
_db.Entry(user).State = System.Data.Entity.EntityState.Modified;
_db.SaveChanges();
}
}
in user I have the data I have in Users table. So ConfirmPassword is null because it is set as [NotMapped].
On _db.SaveChanges() I have an error because ConfirmPassword is null, so, when it is compared with Users Entity, it is compared whith Password property and failed.
How can I work when using [NotMapped] properties there is null?
Thanks
The problem I had in a Property ConfirmPassword I have add to my Users Entity with the Notation [NotMapped]. That case me a problem, when I do AutoMapper to Update Modified fields. Entity Validation ocurrs and ConfirmPassowrd is null, so, when validations ocurrs, I had an error on SaveChanges();.
I solved it adding
context.Configuration.ValidateOnSaveEnabled = false;
In the Checkout Controller I have the code
[HttpPost]
public ActionResult AddressAndPayment(FormCollection values)
{
var order = new Order();
TryValidateModel(order);
....
The model looks like this
[Bind(Exclude="OrderId")]
public partial class Order
{
[ScaffoldColumn(false)]
public int OrderId { get; set; }
[ScaffoldColumn(false)]
public string Username { get; set; }
[Required(ErrorMessage= "First Name is required")]
[DisplayName("First Name")]
[StringLength(160)]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required")]
[DisplayName("Last Name")]
[StringLength(160)]
public string LastName { get; set; }
[Required(ErrorMessage="Address is required")]
[StringLength(70)]
public string Address { get; set; }
[Required(ErrorMessage = "City is required")]
[StringLength(40)]
public string City { get; set; }
[Required(ErrorMessage = "State is required")]
[StringLength(40)]
public string State { get; set; }
[Required(ErrorMessage = "Postal Code is required")]
[DisplayName("Postal Code")]
[StringLength(10)]
public string PostalCode { get; set; }
[Required(ErrorMessage="Country is required")]
[StringLength(40)]
public string Country { get; set; }
[Required(ErrorMessage= "Phone is required")]
[StringLength(24)]
public string Phone { get; set; }
[Required(ErrorMessage="Email Address is required")]
[DisplayName("Email Address")]
[RegularExpression(#"[A-za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage="Email is not valid.")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[ScaffoldColumn(false)]
public decimal Total { get; set; }
[ScaffoldColumn(false)]
public DateTime OrderDate { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
}
I can stop right before the TryValidateModel line and look at form values like
? Request.Form["FirstName"]
"Michael"
? values["FirstName"]
"Michael"
So why does TryValidateModel(order); return false and the order object does not get populated?
Update
To clarify my question I know false means it can not bind but I do not know why it can not bind. Or that it should through the TryValidateModel(or even the ValidateModel)
But what is interesting is that if I change my method signature to
public ActionResult AddressAndPayment(Order order)
order gets populated correctly. So if it is able to bind in the Method call why not TryValidateModel(or even the ValidateModel)?
I am using MVC 4
TryValidateModel returns false when validation of the Form Model against your Orders Model Fails, thus Binding fails.
I hate using
TryValidateModel(order);
and prefer
ValidateModel(order);
early on while developing my page, because binding is a delicate process. This way, if the model fails to bind, I get an exception and an indicative error msg.
I am creating a web application that contains a model for the user. After creating the model without errors, I'm trying to update the password for the user (Change password form). Every time I try to update the model, the db.savechanges() throw an exception (Title and the category are required although this user has entries for both fields). When I try to debug this controller method, no exceptions are thrown and The user contains data for both the category and the faculty title!!
here is my user model:
[Key]
public int Id { get; set; }
[Required]
[ScaffoldColumn(false)]
[Display(Name = "Email address")]
public string Email { get; set; }
[ScaffoldColumn(false)]
[Required]
public virtual FacultyTitle Title { get; set; }
[Required]
[StringLength(128, MinimumLength = 2, ErrorMessage = "{0} must be less than {1} characters and more than {2} characters.")]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Position")]
[ScaffoldColumn(false)]
[Required]
public virtual Categories Categorie { get; set; }
And here is the part of the method that I am using to update the user password:
user.Password = Helper.EncryptPassword(newPass);
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
The exception message: The title and the categories field are required
Please any one help me
I have this data model:
public class User
{
public long UserID { get; set; }
[Required(ErrorMessage = "User name is required.")]
[MaxLength(50, ErrorMessage = "User name cannot be longer than 50 characters.")]
public string UserName { get; set; }
[Email]
[Required(ErrorMessage = "Email is required.")]
[MaxLength(100, ErrorMessage = "Email cannot be longer than 100 characters.")]
public string Email { get; set; }
[Required(ErrorMessage = "Password is required.")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }
[MaxLength(150, ErrorMessage = "Full name cannot be longer than 150 characters.")]
public string FullName { get; set; }
public int UserTypeID { get; set; }
public virtual UserType UserType { get; set; }
public virtual ICollection<Page> Pages { get; set; }
}
and I'm using this model to only edit some fields (password shouldn't be editable):
public class EditUserModel
{
public long UserID { get; set; }
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Email]
[Required(ErrorMessage = "Email is required.")]
[MaxLength(100, ErrorMessage = "Email cannot be longer than 100 characters.")]
public string Email { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Full name")]
[MaxLength(150, ErrorMessage = "Full name cannot be longer than 150 characters.")]
public string FullName { get; set; }
public int UserTypeID { get; set; }
public virtual UserType UserType { get; set; }
}
but I'm confused on how to pass the EditUserModel to my data context to update it. Sorry if seems elementary, but I'm really stumped.
This is the auto-generated edit action that I modified:
[IsAdministrator]
[HttpPost]
public ActionResult Edit(EditUserModel user)
{
if (ModelState.IsValid)
{
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.UserTypeID = new SelectList(db.UserTypes, "UserTypeId", "Name", user.UserTypeID);
return View(user);
}
This is the line I'm having trouble with:
db.Entry(user).State = EntityState.Modified;
The reason I created a custom class was to avoid exposing the password from the view.
This can't work because you're trying to save view model.
You could use AutoMapper to rewrite data from view model to your data model. After that you should be able to save changes.
User userModel = Mapper.Map<EditUserModel, User>(user);
userModel = // todo: get password from database
// todo: attach your model to context and save changes
I'm using Entity Framework Code First and that approach works great.