MVC3 验证 - 需要组中的一个

2024-02-28

给定以下视图模型:

public class SomeViewModel
{
  public bool IsA { get; set; }
  public bool IsB { get; set; }
  public bool IsC { get; set; } 
  //... other properties
}

我希望创建一个自定义属性来验证至少一个可用属性是否为真。我设想能够将属性附加到属性并分配组名称,如下所示:

public class SomeViewModel
{
  [RequireAtLeastOneOfGroup("Group1")]
  public bool IsA { get; set; }

  [RequireAtLeastOneOfGroup("Group1")]
  public bool IsB { get; set; }

  [RequireAtLeastOneOfGroup("Group1")]
  public bool IsC { get; set; } 

  //... other properties

  [RequireAtLeastOneOfGroup("Group2")]
  public bool IsY { get; set; }

  [RequireAtLeastOneOfGroup("Group2")]
  public bool IsZ { get; set; }
}

我想在表单提交之前在客户端进行验证,因为表单中的值会发生变化,这就是为什么我更愿意尽可能避免使用类级属性。

这将需要服务器端和客户端验证来查找具有作为自定义属性的参数传入的相同组名称值的所有属性。这可能吗?非常感谢任何指导。


这是一种继续进行的方法(还有其他方法,我只是举例说明一种与您的视图模型相匹配的方法):

[AttributeUsage(AttributeTargets.Property)]
public class RequireAtLeastOneOfGroupAttribute: ValidationAttribute, IClientValidatable
{
    public RequireAtLeastOneOfGroupAttribute(string groupName)
    {
        ErrorMessage = string.Format("You must select at least one value from group \"{0}\"", groupName);
        GroupName = groupName;
    }

    public string GroupName { get; private set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        foreach (var property in GetGroupProperties(validationContext.ObjectType))
        {
            var propertyValue = (bool)property.GetValue(validationContext.ObjectInstance, null);
            if (propertyValue)
            {
                // at least one property is true in this group => the model is valid
                return null;
            }
        }
        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
    }

    private IEnumerable<PropertyInfo> GetGroupProperties(Type type)
    {
        return
            from property in type.GetProperties()
            where property.PropertyType == typeof(bool)
            let attributes = property.GetCustomAttributes(typeof(RequireAtLeastOneOfGroupAttribute), false).OfType<RequireAtLeastOneOfGroupAttribute>()
            where attributes.Count() > 0
            from attribute in attributes
            where attribute.GroupName == GroupName
            select property;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var groupProperties = GetGroupProperties(metadata.ContainerType).Select(p => p.Name);
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage
        };
        rule.ValidationType = string.Format("group", GroupName.ToLower());
        rule.ValidationParameters["propertynames"] = string.Join(",", groupProperties);
        yield return rule;
    }
}

现在,让我们定义一个控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new SomeViewModel();
        return View(model);        
    }

    [HttpPost]
    public ActionResult Index(SomeViewModel model)
    {
        return View(model);
    }
}

和一个视图:

@model SomeViewModel

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.IsA)
    @Html.ValidationMessageFor(x => x.IsA)
    <br/>
    @Html.EditorFor(x => x.IsB)<br/>
    @Html.EditorFor(x => x.IsC)<br/>

    @Html.EditorFor(x => x.IsY)
    @Html.ValidationMessageFor(x => x.IsY)
    <br/>
    @Html.EditorFor(x => x.IsZ)<br/>
    <input type="submit" value="OK" />
}

剩下的最后一部分是注册适配器以进行客户端验证:

jQuery.validator.unobtrusive.adapters.add(
    'group', 
    [ 'propertynames' ],
    function (options) {
        options.rules['group'] = options.params;
        options.messages['group'] = options.message;
    }
);

jQuery.validator.addMethod('group', function (value, element, params) {
    var properties = params.propertynames.split(',');
    var isValid = false;
    for (var i = 0; i < properties.length; i++) {
        var property = properties[i];
        if ($('#' + property).is(':checked')) {
            isValid = true;
            break;
        }
    }
    return isValid;
}, '');

根据您的具体要求,代码可能会进行调整。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MVC3 验证 - 需要组中的一个 的相关文章

  • Razor CheckBox用于在视图中有条件地检查和取消检查

    在我看来 我有 Html CheckBoxFor m gt m IsExist new id IsExist In my Model我有来自数据库的 IsExist 值 要么是真的 要么是假的 现在我如何根据 IsExist 中的 true
  • System.Web.Caching.Cache 在模型中抛出 null 异常

    也许这个问题应该很简单 但事实并非如此 我读过了在 ASP NET 中使用 System Web Caching Cache 类时出现问题 https stackoverflow com questions 531014 problem u
  • MVC3 中的“方法‘LabelFor’没有重载需要 2 个参数”

    我正在运行 ASP NET MVC 3 并且正在查看模型的编辑视图 我有一个FullName我想呈现为 全名 的属性 这是有问题的行 div class display label div 现在智能感知shows存在重载 有两个签名 第一个
  • 在 MVC Razor 中的 C# 和 Javascript 之间共享常量

    我想在服务器上的 C 和客户端上的 Javascript 中都使用字符串常量 我将常量封装在 C 类中 namespace MyModel public static class Constants public const string
  • 运行测试项目时自动启动ASP.MVC项目

    我正在尝试为我的 ASP 网站设置一个测试项目 对于某些测试 我想使用 selenium 来执行端到端测试 因此 我的网站必须运行 以便测试可以访问该网站 运行测试时如何启动我的网站项目 请参考以下链接 我相信这是可能的 但会有点棘手 这些
  • MVC3 Controller 文件夹不会出现在 URL 中

    这只是一个例子 我不知道如何让它工作 在我的 MVC3 控制器文件夹中 如果我添加一个名为 Admin 的新文件夹 并添加一个带有操作 Index 的控制器 News 则当您尝试打开该 url 404 时 您会收到服务器错误 http ur
  • 在 MVC 控制器内打开 websocket 通道

    有没有人有在 MVC 控制器内打开 websocket 连接的良好经验 技术栈 ASPNET Core 1 0 RC1 MVC dnx46 System Net WebSockets 为什么使用 MVC 而不是中间件 为了整体一致性 路由
  • 防止更新 ASP.NET MVC 和实体框架中未更改的值

    我正在使用 ASP NET MVC 和实体框架 我有一个 编辑人员 网页 可以在其中编辑人员的字段 然后在回发操作中 我使用以下代码 var person objectCtx Persons Where s gt s Id id First
  • 将 MVC 操作结果发送到打印机

    我有一个带有操作的控制器 SomeController ActionToBePrinted ActionToBePrinted 返回一个 html 视图 当按下按钮时 从普通的 mvc razor 视图调用此操作 当按下按钮时 我将如何将视
  • 如何找出 ModelState 的哪个键有错误

    当 ModelState IsValid 为 false 时 如何确定 ModelState 中的哪些键包含错误 通常我只需将鼠标悬停在 ModelState Values 列表中 逐项检查错误计数 gt 0 但现在我正在处理一个包含一些复
  • 未捕获的类型错误:未定义不是函数

    我收到消息Uncaught TypeError Undefined is not a function当我尝试调用家庭控制器中的方法时 也许关于我为什么收到此消息的建议 findIdpActivities function pernr ca
  • SimpleMemership CreateUserAndAccount 自定义

    我正在尝试添加一个新属性UserProfile我的模型中的类 public class UserProfile Key DatabaseGeneratedAttribute DatabaseGeneratedOption Identity
  • 将跟踪消息获取到来自控制器的失败请求跟踪中

    在 ASP NET MVC Preview 5 上 我们无法从全局或控制器获取任何跟踪消息以显示在页面 视图 或失败请求跟踪 FREB 中 这些调用都不能在控制器操作中工作 HttpContext Trace Write hello Sys
  • IIS Express 捕获所有子域 url

    我正在寻找 IIS Express 中子域包罗万象 url 的解决方案 基本上 我环顾四周并找到了如何在 IIS Express 中创建域 子域 它很容易找到 我所要做的就是在 IIS Express 的 ApplicationHost c
  • 使用 ADAL v3 使用 ClientID 对 Dynamics 365 进行身份验证

    我正在尝试对我们的在线 Dynamics CRM 进行身份验证以使用可用的 API 我能找到的唯一关于执行此操作的官方文档是 https learn microsoft com en us dynamics365 customer enga
  • 混合模型优先和代码优先

    我们使用模型优先方法创建了一个 Web 应用程序 一名新开发人员进入该项目 并使用代码优先方法 使用数据库文件 创建了一个新的自定义模型 这 这是代码第一个数据库上下文 namespace WVITDB DAL public class D
  • 如何对使用 Controller.User 变量的控制器操作进行单元测试?

    我有一个控制器操作 如果用户已经登录 它会自动重定向到新页面 User Identity IsAuthenticated 针对这种情况编写单元测试以确保重定向发生的最佳方法是什么 我一直在使用以下 Mocks 和 Moq 来允许在我的单元测
  • 为什么我应该在 ASP .Net MVC 应用程序中放弃使用 HTTPContext 会话状态的形式?

    我记得读过一些地方 人们不鼓励在 ASP Net Web 应用程序中使用 HTTPContext Current Session 状态 有人可以解释一下最近这一趋势背后的一些原因吗 A这有可靠的技术原因吗 谢谢 约翰 B 首先 MVC 不是
  • 使用多态对象数组进行 JSON 反序列化

    我在涉及多态对象数组的 JSON 反序列化方面遇到问题 我已经尝试过记录的序列化解决方案here https stackoverflow com questions 5186973 json serialization of array w
  • 表单帖子上的 asp.net mvc 编码

    我在我的 asp net mvc 表单 带有文本区域的 nicedit 中使用富文本编辑器 当我在帖子上提交表单时 因为它不是 html 编码的 我收到以下消息 从客户端检测到潜在危险的 Request Form 值 如何对 post 上的

随机推荐