Click here to Skip to main content
15,906,626 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I'm using Entity Framework to a SQL database and would like to perform Client Side Server validation, within the Model. So far so good, however when I add my partial class and attempt to validate the controls in the view, I discover that Entity Framework (EF) has already added validation to these controls and receive a compile error. The EF generated the Client Side validation is not as strong as I would like.

From what I have read, although you can, you should not modify what EF generates.

So my question is how do you add additional validation without modifying the EF code? I have not done much work with Partial classes before, but understand the concepts.

Thank you,
Posted

 
Share this answer
 
Personally, I don't pass any of the 'Entity' objects back to the view. I would create a 'View Model', which would contain just the data needed to present my View and annotations that the client side validation understands and creates approriate rules for.

You *can* add Annotations to your POCO objects that EF is using, however - this breaks a few programming rules. Data Annotations in this context are just about the 'View' so shouldn't be on our entity objects (which are generally a representation of data)

A good example of this is in the 'Account' models that are automatically created by Visual Studio when you create an 'Internet' type project, e.g.

C#
public class ChangePasswordModel
{
    [Required]
    [DataType(DataType.Password)]
    [DisplayName("Current password")]
    public string OldPassword { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [DisplayName("New password")]
    [RegularExpression(@"^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,15}$", ErrorMessage = "Password must contain at least one capital letter and one number")]
    public string NewPassword { get; set; }

    [DataType(DataType.Password)]
    [DisplayName("Confirm new password")]
    [Compare("NewPassword", ErrorMessage="Passwords must match")]
    public string ConfirmPassword { get; set; }
}


HTML
@model ChangePasswordModel
@{
    ViewBag.Title = "Change Password";
}

<h2>Change Password</h2>
<p>
    Use the form below to change your password. 
</p>
<p>
    New passwords are required to be a minimum of @Membership.MinRequiredPasswordLength characters in length.
</p>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true, "Password change was unsuccessful. Please correct the errors and try again.")
    <div>
        <fieldset>
            <legend>Account Information</legend>

            <div class="editor-label">
                @Html.LabelFor(m => m.OldPassword)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.OldPassword)
                @Html.ValidationMessageFor(m => m.OldPassword)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.NewPassword)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.NewPassword)
                @Html.ValidationMessageFor(m => m.NewPassword)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.ConfirmPassword)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.ConfirmPassword)
                @Html.ValidationMessageFor(m => m.ConfirmPassword)
            </div>

            <p>
                <input type="submit" value="Change Password" />
            </p>
        </fieldset>
    </div>
}


In this case, our View is bound to our model, which knows nothing about any data or persistence. All the Model knows is what fields it is expecting, data types and validation rules.

The controller method looks something like..

C#
[HttpPost, Authorize]
public ActionResult ChangePassword(ChangePasswordModel model)
{
    if (ModelState.IsValid)
    {
        // ChangePassword will throw an exception rather than return false in certain failure scenarios.
        bool changePasswordSucceeded = this.MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword);

        if (changePasswordSucceeded)
        {
            return RedirectToAction("ChangePasswordSuccess");
        }
        else
        {
            ModelState.AddModelError("", "Some Error Messge to Display.");
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}


The key points are that our view will validate against our simple view model using javascript (if enabled) , the controller will also validate the model and then data collected from the view is passed on to some other Service, in this case the 'MembershipService'

I like this approach, since there is a clear seperation of concerns and every component is doing the job it's supposed to do.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900