I have created a Model file for my MVC project that contains the following:
Public Class Player
Public Property FirstName As String
Public Property LastName As String
Public Property GoesBy As String
Public Property Birthdate As Date
End Class
I didn't mark the Birthdate field as a Required field, but it won't accept nulls. How can I add a validation or something else to allow for nulls? Or is that not possible and I have to just insert 1900-01-01 or something similar?
Just make your property Public Property Birthdate As Date as nullable like shown below:
Public Property Birthdate As Nullable(Of Date)
and just make your database field which accepts Birthdate as nullable so that it can accept null values also.
Related
I have one ViewModel that has property Id of type long without attribute [required]. This model I use for search.
Problem : Why always when i try to make search request and input for property Id leave empty i get validation error as Id field is required ?
Make your model property nullable.
public long? myprop { get; set; }
I have been working with MVC 4 and Entity Framework to create a web app recently. Things have been going well with my database "ppProject" model, as shown here:
Public Class ppProject
<Key()>
Public Property ProjectID As Integer
Public Property ClientID As Integer
Public Property ProjectTitle As String
Public Overridable Property Client As ppClient
Public Overridable Property Milestones As ICollection(Of ppMilestone)
Public Overridable Property Tasks As ICollection(Of ppTask)
End Class
The problem is that I am adding a new table of employees, "ppEmployees". This way the Project can have a ProjectManager, which is a foreign key into the Employees table. These are the new models where ProjectManagerID (foreign key) is linked to EmployeeID (primary key):
Public Class ppProject
<Key()>
Public Property ProjectID As Integer
Public Property ClientID As Integer
Public Property ProjectTitle As String
Public Property ProjectManagerID As Integer 'NEW'
Public Overridable Property Client As ppClient
Public Overridable Property Milestones As ICollection(Of ppMilestone)
Public Overridable Property Tasks As ICollection(Of ppTask)
Public Overridable Property ProjectManager As ppEmployee 'NEW'
End Class
Public Class ppEmployee
<Key()>
Public Property EmployeeID As Integer
Public Property DepartmentID As Integer
Public Property FirstName As String
Public Property LastName As String
Public Overridable Property ProjectsInManagement As ICollection(Of ppProject)
Public Overridable Property TimeItems As ICollection(Of ppTimeItem)
Public Overridable Property Department As ppDepartment
End Class
When I change my project model and add the employee model, I am getting the error
Invalid column name 'ProjectManager_EmployeeID'
The line of code that is triggering this is when I first access my projects in a view with:
#For Each proj In client.Projects
Any ideas at what is causing this? This must be a naming convention problem or something simple because I haven't had any errors with any of my other table models prior to this.
EDIT - See my answer below. Very confused about what Entity Framework is doing here.
In Entity Framework the name of the field must match the name of the column.
otherwise EF wouldnt know how to map the fields unless you decorate the property with the column attribute like you did in your answer.
Ok I think I've fixed this. I had to make the following changes to the "ppProject" class:
<Column("ProjectManagerID")>
Public Property EmployeeID As Nullable(Of Integer) 'Has to be set, dont know why
If anyone knows why my property has to be named EmployeeID, please let me know. I'm very curious.
I had a similar problem about a month ago. I dropped the table and created a new one and the problem was solved. that is after i have tried other ways that did not work
In our ASP.NET MVC 4 application, one of the models has a field of the DateTime type. When editing such model objects via a form, the value for the DateTime field has to be non-empty and on the format yyyy-MM-dd H:mm:ss (e.g., 2012-10-17 10:49:00). How do I ensure this field is correctly validated in the application? I've tried the following annotations:
[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.DisplayFormat(DataFormatString="yyyy-MM-dd H:mm:ss",
ApplyFormatInEditMode=true)]
However, validation of form data doesn't require all components of the format to be present. For instance, the value '2012-10-17' is accepted (leaving out the 'H:mm:ss' part). It's just verified that the field contains a valid DateTime string.
How should I ensure that this DateTime field is indeed on my specified format (yyyy-MM-dd H:mm:ss)?
Alternative solution - view-only model class
Darin's solution is of course valid, but it's not the only one you can use. And it would require you to write more complex code than with this solution that I'm going to show you here.
So this is an alternative. I'd suggest that instead of creating a custom model binder you rather create a separate view model class that instead of taking DateTime takes a string where you can set as complex validation regular expression as you like. And then have a method on it that would translate it to your application/domain model class instance (and back).
// suppose this app model
public class User
{
[Required]
public string Name { get; set; }
[Required]
public DateTime DateOfBirth { get; set; }
}
public class ViewUser
{
[Required]
public string Name { get; set; }
[Required]
[RegularExpression("\d{4}-\d{2}-\d{2}(?:\s\d{1,2}:\d{2}:\d{2})?")]
public string DateOfBirth { get; set; }
public ViewUser(User user)
{
this.Name = user.Name;
this.DateOfBirth = user.DateOfBirth.ToString("yyyy-MM-dd H:mm:ss");
}
public User ToPoco()
{
return new User {
Name = this.Name,
DateOfBirth = DateTime.Parse(this.DateOfBirth, "yyyy-MM-dd H:mm:ss")
};
}
}
With a bit of tweaking you could inherit ViewUser from User class and use new keyword on DateOfBirth and use base property to store correct typed value. In that case you wouldn't need the ToPoco method.
Note: you will have to use DateTime.TryParseExact method to parse your dates because they may include time or they may not. I didn't include that in my code because it depends on the exact requirements of your date input.
You could write a custom model binder which will use the exact format you have specified in the DisplayFormat attribute. I have shown an example of how this could be achieved in this post.
Also don't be confused into thinking that the DisplayFormat attribute overrides the Required attribute. The DisplayFormat is only used for displaying the field in the input field. It is not a validation attribute. It has strictly nothing to do with validation and when the form is POSTed to the server it is never used.
I've got a number of classes which have a relationship to other classes for properties like Location, Currency etc. Take the following example:
Public Class Transaction
Public Property ID As Integer
Public Property Description As String
Public Property Quantity As Integer
Public Property SaleAmount As Double
Public Overridable Property Currency As Currency
End Class
Public Class Currency
Public Property ID As String
Public Property Description As String
Public Property Symbol As String
Public Property SymbolImage As String
End Class
I add my currencies when I initialise the application for first use. When adding a transaction, I have a drop down box to select the currency.
I have no issues saving the Transaction to the db and the currency ID is saved also.
When I edit the transaction and try to change the currency, I can't get it to save back to the db.
<HttpPost()>
Function Edit(transaction As Transaction) As ActionResult
transaction.Currency = db.Currencies.Find(transaction.Currency.ID)
Debug.Print("Currency: " & transaction.Currency.ID)
If ModelState.IsValid Then
db.Entry(transaction).State = EntityState.Modified
db.SaveChanges()
Return RedirectToAction("Index")
End If
Return View(transaction)
End Function
When I do the debug.print in the post method above, the currency is correctly being reported as the changed currency but the Currency ID on the Transaction record in the DB isn't updated.
I've done some searching and reading and haven't found much/anything.
I did try adding this line to the post method but it still didn't save the changes:
db.Entry(transaction.Currency).State = EntityState.Modified
I'm stumped and would appreciate any help!
So here's the best solution I could find. I'd be interested to hear other ways to achieve the same result. The other methods I've found are much more complicated than this.
Public Class Transaction
Public Property ID As Integer
Public Property Description As String
Public Property Quantity As Integer
Public Property SaleAmount As Double
Public Property Name As String
Public Property CurrencyID() As String
<ForeignKey("CurrencyID")>
Public Overridable Property Currency() As Currency
End Class
I've setup the Edit view with a drop down list containing a list of the currencies and a hidden field to store the CurrencyID. The edit post looks like this:
<HttpPost()>
Function Edit(transaction As Transaction) As ActionResult
If ModelState.IsValid Then
db.Entry(transaction).State = EntityState.Modified
db.SaveChanges()
Return RedirectToAction("Index")
End If
Return View(transaction)
End Function
Validating a form with Data Annotations using MVC.
Are you to define all properties of an input object parameter as string with data annotations so one can check the model state to catch errors, or should I just use the native data types for objects?
I created numerous "control function" models in bound which are identical to the View Models with the exception of Regex validators and "string" for each field.
Doing this seems to be unnecessary complexity. Just want to make sure I am on the right track, or that the double data models is something that MVC normally handles anyway.
For example:
public class Product
{ public int id {get;set;}
public string name {get;set;}
public double? retailPrice {get;set;}
[Required]
public int deptId {get;set;}
[Required]
public bool active {get;set;}
}
public class Product
{ [RegularExpression(#"^\d*$", ErrorMessage = "*")]
public string id {get;set;}
public string name {get;set;}
[RegularExpression(#"^\d*$", ErrorMessage = "*")]
public string retailPrice {get;set;}
[RegularExpression(#"^\d+$", ErrorMessage = "*")]
public string deptId {get;set;}
[RegularExpression(#"(?i)^true$|^false$", ErrorMessage = "*")]
public string active {get;set;}
}
Could just use the first as the inbound object, or use the second and convert to the first upon successful validation.
You should define your view models to have properties (or fields) with the correct data type. There is no requirement for them to be strings. If you have defined a property to be of type int and the model binder binds the request data to it, but cannot coerce the value to an int then the property will not be set and the model state will indicate that there is an error.
Some people have the concern of wanting to rerender the page and still have the user value in the textbox to allow them to correct it. If you use the built in Html helper methods, then this will be done for you as it looks to see if there is a model state error for that field and if there is, it will try and find the value from the request data and use that instead.