C# 使用ASP.NET MVC3在jquery非侵入式客户端验证失败时强制服务器端验证

C# 使用ASP.NET MVC3在jquery非侵入式客户端验证失败时强制服务器端验证,c#,asp.net-mvc-3,validation,C#,Asp.net Mvc 3,Validation,我将展示一些最低限度的代码,因为我认为我的公司不希望我展示太多,尽管我们目前正在做研究 我们正在实体框架4中使用POCO将数据保存回数据库。我们正在使用数据注释来减少重复验证的数量(这是我们以前的经典ASP解决方案的一个问题,我们在应用程序的三个不同级别上进行了相同的验证) 我们希望在模型中包含业务规则,这包括确保根据其他表验证的字段有效(我们在模型中不使用下拉列表,因此用户可以键入任何内容)。例如,我们正在建筑物中存储房间信息。房间有一个名为“房间类型”的字段。有效的房间类型在不同的表中定义

我将展示一些最低限度的代码,因为我认为我的公司不希望我展示太多,尽管我们目前正在做研究

我们正在实体框架4中使用POCO将数据保存回数据库。我们正在使用数据注释来减少重复验证的数量(这是我们以前的经典ASP解决方案的一个问题,我们在应用程序的三个不同级别上进行了相同的验证)

我们希望在模型中包含业务规则,这包括确保根据其他表验证的字段有效(我们在模型中不使用下拉列表,因此用户可以键入任何内容)。例如,我们正在建筑物中存储房间信息。房间有一个名为“房间类型”的字段。有效的房间类型在不同的表中定义

我们还希望立即进行客户端验证。例如,数字字段必须介于0和32767之间。如果用户输入-1,我们使用客户端验证立即响应用户,让他们知道-1无效。我们通过打开客户端验证和使用数据注释来实现这一点

Web配置:

<appSettings>
    <add key="webpages:Version" value="1.0.0.0" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
视图: (不必费心显示用于创建自动完成的javascript…)

@使用(Html.BeginForm()){
@Html.ValidationSummary(false,“尝试保存此文件室时发生以下错误:”)
房间
@LabelFor(model=>model.Building)
@DisplayFor(model=>model.Building)
@LabelFor(model=>model.RoomID)
@DisplayFor(model=>model.RoomID)
@LabelFor(model=>model.RoomType)
@EditorFor(model=>model.RoomType)
@LabelFor(model=>model.MaxStudents)
@EditorFor(model=>model.MaxStudents)
@Html.ValidationMessageFor(model=>model.MaxStudents)

}
我注意到的是,如果用户在Maximum Seats字段中键入-1,客户端验证将启动,并让用户知道该值必须介于0和32767之间

如果用户单击submit,客户端验证将再次启动,并显示在表单顶部的验证摘要中

如果用户在Maximum Seats中输入有效值,但在Room Type字段中输入了错误值,则客户端验证指示没有错误(我理解,因为客户端没有验证Room Type),如果用户单击Submit,则在调用
TryUpdateModel()
期间调用IValidateObject.Validate函数,返回一个验证错误,然后显示在表单顶部验证摘要的页面上

但是,如果用户键入错误的号码(-1)和无效的文件室类型,并单击“提交”,则客户端验证将启动,但服务器端验证不会启动,因此他们只会看到与客户端相关的错误

JavaScript中是否有一个设置或一些技巧可以用来调用客户端和服务器端验证

如果没有,我认为我唯一的选择是在服务器端执行所有验证,这将在用户从一个字段到另一个字段时提供较少的反馈,或者在客户端执行房间类型验证(通过ajax调用检查房间类型表中的值),这将重复工作


有什么想法吗?

我想这就是你想要的。有了它,您就可以完成您提到的使用ajax进行验证的事情。您在客户机上执行数字验证,在服务器上执行房间验证,并在客户端验证中报告验证结果。

我将对此进行研究。看起来很有希望:)
public class Room : IValidatableObject
{
    // I'm only showing the relevant properties...

    // this is a field that's validated based on another table in the database.
    // (In the model we are using autocomplete instead of a dropdown -- it's a long 
    // story --, so potentially invalid data can be passed through the form...
    [DisplayName("Room Type"), MaxLength(5)]        
    public String RoomType { get; set; }

    // A number field, with a range.
    [Range(0, 32767), DisplayName("Maximum Seats")]
    public Int16? MaxStudents { get; set; }

    // do server side validation for this entity.
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var validateErrors = new List<ValidationResult>();

        // make sure room type is a valid type
        if(!String.IsNullOrEmpty(RoomType)) {
            // hit database, which is a little weird since we need to create a context,
            // and I know that might make some people's brains explode
        }

        // return all of the errors
        return validateErrors;
    }
}
    // I didn't include all the actions, just edit

    public ActionResult Edit(Int32 Building, String RoomID)
    {
        // return a single room and show the detail information in edit mode.
        Room room = findRoom(Building, RoomID);
        return View(room);
    }

    [HttpPost]
    public ActionResult Edit(Int32 Building, String RoomID, FormCollection collection)
    {
        // get the current room from the database.
        Room room = findRoom(Building, RoomID);

        // save the room being edited, but don't touch the key fields.
        if (TryUpdateModel(room, null, null, new string[] {"Building", "RoomID"}))
        {
            // if the entity changed, audit and save
            if (db.Entry(room).State == EntityState.Modified)
            {
                db.setLastUpdate(room); // this is a function in our context for auditing
                db.SaveChanges();
            }                
        }
        return View(room);
    }
@using (Html.BeginForm()) {
    @Html.ValidationSummary(false, "The following errors occured when attempting to save this Room:")
    <fieldset>
        <legend>Room</legend>
        <div class="field-block">
            <div class="editor-label">
                @Html.LabelFor(model => model.Building)
            </div>
            <div class="editor-field">
                @Html.DisplayFor(model => model.Building)
            </div>
        </div>
        <div class="field-block">
            <div class="editor-label">
                @Html.LabelFor(model => model.RoomID)
            </div>
            <div class="editor-field">
                @Html.DisplayFor(model => model.RoomID)
            </div>
        </div>
        <div class="field-block">
            <div class="editor-label">
                @Html.LabelFor(model => model.RoomType)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.RoomType)
            </div>
        </div>

        <div class="field-block">
            <div class="editor-label">
                @Html.LabelFor(model => model.MaxStudents)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.MaxStudents)
                @Html.ValidationMessageFor(model => model.MaxStudents)
            </div>
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}