如何支持模型属性的条件验证

发布于 2024-08-27 18:21:21 字数 465 浏览 9 评论 0原文

我目前正在构建一个需要支持两个不同版本的表单。每个版本可能使用不同的表单字段子集。我必须这样做才能支持两个不同的客户端,但我不想为两个客户端提供完全不同的控制器操作。

因此,我试图想出一种方法来使用具有验证属性的强类型模型,但其中一些属性是有条件的。

我能想到的一些方法类似于 steve sanderson 的

我将根据活跃的表单版本清除过滤器 OnActionExecuting 中的模型错误。

我想到的另一种方法是使用类似的方法将模型分解成多个部分

class FormModel
{

public Form1 Form1Model {get; set;}
public Form2 FormModel {get; set;}
}

,然后找到某种方法来根据版本验证适当的属性。模型上也会有适用于两者的共同属性,这些属性将始终得到验证。

有人对此有好的建议吗?

I currently have a form that I am building that needs to support two different versions. Each version might use a different subset of form fields. I have to do this to support two different clients, but I don't want to have entirely different controller actions for both.

So, I am trying to come up with a way to use a strongly typed model with validation attributes but have some of these attributes be conditional.

Some approaches I can think of is similar to steve sanderson's partial validation approach.

Where I would clear the model errors in a filter OnActionExecuting based on which version of the form was active.

The other approach I was thinking of would to break the model up into pieces using something like

class FormModel
{

public Form1 Form1Model {get; set;}
public Form2 FormModel {get; set;}
}

and then find some way to just validate the appropriate property depending on the version. There would also be common properties on the model that apply to both which would be always validated.

Does anyone have a good suggestion on this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

唱一曲作罢 2024-09-03 18:21:21

我在使用 ModelBinders 从 ModelState 中删除不需要的错误方面取得了一定的成功。

以下是 Address 模型绑定程序的示例。在用户界面中,我有一个针对美国各州的 > 文本框。

模型绑定器会查看国家/地区并删除不需要的值。

至于使用验证属性来做到这一点 - 我认为除非您有非常简单的规则,否则您很快就会陷入困境。

提示:您可以拥有任意数量的模型绑定器,以分割整个模型。例如 - 我的模型中有 2 个 Address 对象,它们每个都会自动应用此行为。

注册:

ModelBinders.Binders[typeof(UI.Address)] = new AddressModelBinder();

ModelBinder:

public class AddressModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

        // get the address to validate
        var address = (Address)bindingContext.Model;

        // remove statecd for non-us
        if (address.IsUSA)
        {
            address.StateOrProvince = string.IsNullOrEmpty(address.StateCd) ? null : CountryCache.GetStateName(address.StateCd);
            bindingContext.ModelState.Remove(bindingContext.ModelName + ".StateOrProvince");
        }
        else
        {
            address.StateCd = null;
            bindingContext.ModelState.Remove(bindingContext.ModelName + ".StateCd");
        }


        // validate US zipcode
        if (address.CountryCode == "US")
        {
            if (new Regex(@"^\d{5}([\-]\d{4})?$", RegexOptions.Compiled).Match(address.ZipOrPostal ?? "").Success == false)
            {
                bindingContext.ModelState.AddModelError(bindingContext.ModelName + ".ZipOrPostal", "The value " + address.ZipOrPostal + " is not a valid zipcode");
            }
        }

        // all other modelbinding attributes such as [Required] will be processed as normal
    }
}

I've had reasonable success with using ModelBinders to remove errors I don't need from the ModelState.

Here's an example for an Address model binder. In the UI I have a <SELECT> for US States, but this is hidden when the country is not 'US' in favor of a <INPUT ID=StateOrProvince> textbox.

The modelbinder looks at the country and removes the unneeded values.

As far as doing this with validation attributes - I'd think you'd quickly get yourself in a big mess unless you have very simple rules.

Tip: You can have as many modelbinders as you want to discreet pieces of your overall model. For instance - I have 2 Address objects in my model and they each automatically get this behavior applied.

Register:

ModelBinders.Binders[typeof(UI.Address)] = new AddressModelBinder();

ModelBinder:

public class AddressModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

        // get the address to validate
        var address = (Address)bindingContext.Model;

        // remove statecd for non-us
        if (address.IsUSA)
        {
            address.StateOrProvince = string.IsNullOrEmpty(address.StateCd) ? null : CountryCache.GetStateName(address.StateCd);
            bindingContext.ModelState.Remove(bindingContext.ModelName + ".StateOrProvince");
        }
        else
        {
            address.StateCd = null;
            bindingContext.ModelState.Remove(bindingContext.ModelName + ".StateCd");
        }


        // validate US zipcode
        if (address.CountryCode == "US")
        {
            if (new Regex(@"^\d{5}([\-]\d{4})?$", RegexOptions.Compiled).Match(address.ZipOrPostal ?? "").Success == false)
            {
                bindingContext.ModelState.AddModelError(bindingContext.ModelName + ".ZipOrPostal", "The value " + address.ZipOrPostal + " is not a valid zipcode");
            }
        }

        // all other modelbinding attributes such as [Required] will be processed as normal
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文