I've read that you can use:
[Bind(Exclude="id")]
to stop an ID field from invalidating a ModelState when creating a record from a 'Create' action.
With DNX Core 5 System.Web is no longer available. Is there an equivalent way to ignore an auto-generated ID or am I in the same boat as this answer:
https://stackoverflow.com/a/34847744/2591770
UPDATE
It seems as though items can be removed from the ModelState directly as described here:
https://stackoverflow.com/a/13169910/2591770
I'm still interested in any other alternatives.
Use a view model and then map the posted values to an instance of your entity. That way, only the properties you place on the view model may be modified. Bind is an anti-pattern anyways.
Related
Background
With ef core code first approach, validation is robust and simple: https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/validation
With the database first approach, it seems like any validation is happening behind the scenes by the database when dbcontext.SaveChanges(); is called. What's worse, these exceptions are nebulous and entirely unhelpful, for example, SqlException: String or binary data would be truncated can be thrown if any of the string properties of any of the entities have too many chars (ours is a legacy app riddled with char(10) and such), or even if a key that is a string is left null.
Question
I want to know if there is any reasonable or accepted way of enforcing the validation. I've found this question which might help debugging, but I would like to enforce the constraints in code
Is there any better method than changing every auto property to one that throws if it's constraints aren't met?
EntityFramework Core does not enforce any validation at all. The validation rules you see in the example are enforced by MVC and not EF. One of the main reason for EF Core to remove validation check was that only. Validation are run in UI and then in EF and then again in database which is just redundant. Hence client side validation is left to the front-end (MVC in this case) and server side is done by database engine.
When you use database first approach, EF core does not generate any annotation for validation because it does not reason about them anyway. That means you would get only server side validation which means error during SaveChanges.
The only way to enforce constraint in the code (client side) is to write those annotations so that MVC can enforce them or write custom code to deal with it. The whole validation mechanism is transparent to EF.
I ended up going with a psuedo extension to the generator tooling. Since the DBContext is a partial class, I made a new class that has a main
public partial class DBContext{
public static void Main(string[]args){
DBContext context = new DBContext();
var modelbuilder = new Microsoft.EntityFrameworkCore.ModelBuilder(new Microsoft.EntityFrameworkCore.Metadata.Conventions.ConventionSet());
context.OnModelCreating(modelbuilder);
IMutableModel model=modelbuilder.Model;
from there I used Linq to transform the various info about each entity's properties and the annotations on them into List<KeyValuePair<string,List<KeyValuePair<Regex,string>>>> where the first pair's key is the entity name, and the value is a list of find and replace pairs to edit the code that had already been generated with the corresponding validation, one per property. Then all I had to do was abuse the fact that the tooling generates the classes in <className>.cs files, and iterate over my list, executing the replacements for each entity source code file.
I'd have preferred doing something a little less hacky, because I'm relying on format that the ef tooling outputs, but it works
I searched on many site about savechanges but i dont get any proper
answer can any one tell me about
db.SaveChanges()
ModelState
db.SaveChanges() is not part of ASP.NET MVC - it's part of Entity Framework which is a set of Object-Relational-Mapping (ORM) tools for the .NET Framework. All this method does is persist (save) data in some of your classes (entities) into a database.
Useful links:
Scott Gu - Code-First Development with Entity Framework 4
MSDN - Entity Framework
ModelState is a part of MVC and allows extra binding metadata to be passed from the Controller to the View, which is typically largely about validation.
Useful links:
MSDN - Model State Class
MSDN - Performing Simple Validation
msdn says : It persists all updates to the data source and resets change tracking in the object context.
Example
To save the changes made to the entities to a database, we need to call the ObjectContext class SaveChanges method. In the example given below, the query retrieves the first customer from the entityset -Customer.
var customer = context.Customer.First();
The context.Customer returns the Objectset of Customer types and the LINQ extension method First() returns only the first customer.
customer.FirstName = "Yasser";
customer.LastName = "Shaikh";
context.SaveChanges();
We can edit the first customer details like name and address by assigning new values to the properties and call the SaveChanges() method to save the changes back to the database.
During SaveChanges, the ObjectContext determines which fields were changed. In this example, only FirstName and LastName are changed. So, only those two values are sent into the command. To identify the row to be updated in the database, the ObjectContext uses the value of the EntityKey property.
Please read:
http://msdn.microsoft.com/en-us/library/bb336792(v=vs.110).aspx
http://www.asp.net/mvc/tutorials/older-versions/models-(data)/performing-simple-validation-cs
This should help you a little. Basically the db.SaveChanges() method is used by Entity Framework to save current changes to the database and ModelState represents validation errors when e.g. the model is not valid.
I'm developing my first Spring 3 webapp. In Spring 2, we used to have formBackingObject load data from the database, then let Spring binding update some of the fields, and then onSubmit would persist those changes.
In Spring 3 it seems I have two options:
Let the user edit 100% of the persistent object. This would mean that the object's ID would need to be a hidden field
Create a form object which holds the editable data, and then map that onto the persistent object on submit
The first option is not truly an option, we cannot let the user edit all fields, and we'd rather not present data in hidden fields where anyone capable of pressing F12 can alter the values.
The second option seems like a decent design approach. However, it appears that it requires to essentially clone every editable, persistent class.
#Entity
public class Company {
private String uuid; // not editable!
.. 30 other properties, 2 are not editable
}
public class CompanyForm {
.. 28 of above properties
}
and then some mapping mechanism with lots of
public void map(CompanyForm cf, Company c) {
cf.setName(c.getName());
.. 27 other set(get())
}
I'm praying this is not the "as designed" approach of Spring's MVC binding. However, all tutorial I've found so far are terribly trivial and implement option 1 from above. Does anyone have some suggestions for implementing option 2?
Thanks, Simon
DataBinder API
Note that there are potential security implications in failing to set an array of allowed fields. In the case of HTTP form POST data for example, malicious clients can attempt to subvert an application by supplying values for fields or properties that do not exist on the form. In some cases this could lead to illegal data being set on command objects or their nested objects. For this reason, it is highly recommended to specify the allowedFields property on the DataBinder.
You can use it together with option 1
A pragmatic way would be to just ignore the non editable fields on the update statement.
I have actually circumvented this in the past by using a #ModelAttribute annotation and detecting the PK on the request, if you do it this way Spring will use the object that is returned from #ModelAttribute and automatically copy the submitted object to it.
It's kind of a hack and not obvious to someone who comes in to maintain the code though.
Say I have a form that has fields to gather data about future conferences (not the real domain but will suffice for the purposes of this question). Part of the validation is that a new event can only happen once in that year so for instance if you have a "stackoverflow getmessyandrunk conference" that happens in 2012 - the user shouldn't be allowed to enter a new event with the same name and year...
Now - what I have tried so far is to add a remote validator to each of the fields:
one for the event name field that uses the AdditionalFields property to include the year field and one for the year field which uses the AdditionalFields to include the event name field.
it doesn't work - if I try to add an event with the same name and year it adds an error to just the year field, correcting it fixes it, then trying again it adds an error to the name field and year field, correcting the name field to make the combination unique only removes the error from the name field - it goes on like this...
How are others doing this?
If you prefer using data annotations for validation, I would recommend that you just use the Foolproof validation library that is available on Codeplex: https://foolproof.codeplex.com/
It supports, amongst others, the following "requiredif" validation attributes / decorations:
[RequiredIf]
[RequiredIfNot]
[RequiredIfTrue]
[RequiredIfFalse]
[RequiredIfEmpty]
[RequiredIfNotEmpty]
[RequiredIfRegExMatch]
[RequiredIfNotRegExMatch]
To get started is easy:
Download the package from the provided link
Add a reference to the included .dll file
Import the included javascript files
Ensure that your views references the included javascript files from within its HTML for unobtrusive javascript and jquery validation.
If you don't like mixing your domain and and validation logic by decorating your domain classes with validation attributes, you can always opt for the powerful fluent validation. You can find the library for it here:
https://fluentvalidation.codeplex.com/
It is unfortunately server-side only, but a suitable option if seperation of concerns is of importance to you... and context is not lost due to the validation being tied to a specific field. (See here: http://www.codeproject.com/Articles/326647/FluentValidation-and-Unity)
I have a requirement to keep a history of values of some fields in an EF4 ASP.NET MVC3 application. This just needs to be a log file of sorts, log the user, datetime, tablename, fieldname, oldvalue, newvalue.
Although it would be pretty easy to code this in various save routines, I'm wondering if I can get global coverage by wiring it into some sort of dataannotation, so that I can perhaps declare
[KeepHistory()]
public string Surname { get; set; }
in my partial class (I'm using POCO but generated from a T4 template).
So Questions
1) Is this a bad idea ? I'm basically proposing to side-effect changes to an entity, not directly referenced by the code, as a result of an annotation.
2) Can it be done ? Will I have access to the right context to tie up with my unit of work so that changes get saved or dropped with the context save?
3) Is there a better way?
4) If you suggest I do this, any pointers would be appreciated - everything I've read is for validation, which may not be the best starting point.
Actually, validation might be a good starting point. Since an attribute does not know about which property or class it was assigned to, but a validation-attribute gets called by the validation framework with all the necessary informátion. If you implement the System.ComponentModel.DataAnnotations.ValidationAttribute class you can override the IsValid(object, ValidationContext) method, which gives you the actual value of the property, the name of the property and the container.
This might take a lot of work, since you need to get to the currently logged-in user etc. I'm guessing that the .NET implementation provides some sort of caching for the specific attributes on an entity type, which would be a pain to implement by yourself.
Another way, would be to use the ObjectStateManager exposed by your EF ObjectContext, which can provide you with the ObjectStateEntry-objects for all entities of a given state. See the
ObjectStateManager.GetObjectStateEntries(EntityState) method, for more information about how to call it (and when). The ObjectStateEntry actually contains a record of the original and current-values, which can be compared to find any changes made within the lifetime of the current ObjectContext.
You might consider using the ObjectStateManager to inject your custom logging behavior, while this behavior decides based on property-attributes which change should be logged.