Question

Is there a way to validate a property that should be unique on a model? For example, a user can create and edit a "Product", but they shouldn't be able to create a Product with an existing ProductCode, nor should they be able to edit a Product and change the ProductCode to a code that already exists.

I have tried using a custom attribute.

public class Unique : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        var products = Repository.Store.Products.Where(x => x.ProductCode == value);
        return (products.Count() == 0);
    }
}

All that I can cover with this solution is not allowing the user to insert/update a Product when the code already exists in the DB. This does not allow the user to edit an existing product because when they submit, it will see that the code already exists(it will be the code for the product they are trying to edit.) and returns false.

Is there no way of dealing with a unique index in MVC 2, I have searched for hours, even found other topics on stackoverflow, but nothing with a solid solution.

Was it helpful?

Solution

Just let the insert or update fail and then return an appropriate error message to the user. Checking up front is problematic anyway since there's always a chance that another user will modify the database immediately after your check.

Here's an example of how you can insert an object and determine whether or not it failed due to a unique constraint:

INSERT INTO MyTable (column1, column2, column3) 
    SELECT @param1, @param2, @param3
    WHERE NOT EXISTS (SELECT * FROM table WHERE id = @param4)

If the object already exists, this will modify 0 rows. If it does not, then it will modify 1 row. If anything else goes wrong, you'll get an exception. This is also quite efficient (at least in SQL server). It results in an index seek followed by an index update, just as you would hope.

OTHER TIPS

I struggled with MVC a little in a related area.

Part of the answer gleaned to my question was that you should "probably" have a seperate model for Insert and Update of an object.

That way you could have your custom attribute just on the insert model.

Otherwise, just take care of this as a normal code check in your insert method, not in a custom attribute.

Ok I see....

Can you do a "does not equal" check on the exists for some unique ID on the object - that way you check for the existence of the product code BUT not on the current product.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top