ViewModel中基于表单步骤的必填字段

时间:2015-08-11 11:41:29

标签: c# asp.net-mvc

我正在构建一个MVC应用程序并遇到一个问题,我似乎也无法得到一个真正的好答案。将使用此应用程序的用户将通过填写表单的一系列步骤。第一步是基本的简单形式,只能在类别和名称之间进行选择。下一步将是更多信息。为了使这个工作,我有一个我在步骤1和2中使用的ViewModel。问题在于ViewModel我想使用注释来获取必需的字段和其他验证。步骤2中有一些字段,我想在步骤1中进行必要但不可见。最佳方法是什么?我应该制作2个单独的ViewModel。有没有办法指定何时需要该字段?

UPDATE1: 所以我找到了这篇文章:multi-step registration process issues in asp.net mvc (splitted viewmodels, single model),这看起来非常符合我的要求。我在这里看到的唯一问题是基于用户输入我呈现不同的ViewModel。例如,如果用户选择了一个类别Airplanes,我想使用不同的ViewModel,那么当用户选择Cars时。这将意味着每个类别得到3个ViewModels。那会有意义吗?

1 个答案:

答案 0 :(得分:0)

很有可能做到这一点,但我实际上是要插入一个库。由于我选择的验证框架,我已完全转移到FluentValidation。主要是因为它适合我们现在习惯的大多数其他库。

这个框架基本上取代了你通常在模型类中使用的属性。

您需要两个nuget包:

第一个包是显而易见的,它是FluentValidation的核心库,第二个是MVC5包(还有其他可用的框架),可以插入MVC验证pipline并处理模型验证。我真正喜欢这个框架的是它支持构造函数注入(和属性注入,只用AutoFac测试)。

仅供参考:您需要在Application_Start或OWIN启动课程中使用global.asax方法完成register the validator into the MVC pipeline

简单如下: FluentValidationModelValidatorProvider.Configure();

好的..足够的插头让我们看一下基本型号。

public class SampleModel
{
    public int StepNumber { get; set; }

    public string Step1Validation { get; set; }

    public string Step2Validation { get; set; }
}

非常简单的模型。基本上我们有三个属性。

  1. StepNumber:确定我们当前的步骤
  2. Step1Validation:我们验证的所有步骤都不为空的简单字符串
  3. Step2Validation:从第2步开始再次使用简单字符串。
  4. 现在,在此模型中,我们基于StepNumber属性维护步骤。这必须存在于所有请求中。接下来,我们将两个字符串属性Step1Validation作为输入作为第一步,并在所有步骤上进行验证。 Step2Validation仅在第二步上输入,仅在步骤2或更高版本上验证。

    现在是验证器..这是一些copy \ paste代码,但很简单。基本上我们有一个继承自AbstractValidator<T>的类,其中T是要验证的ViewModel类。接下来我们编写一些流畅的验证方法。

    public class SampleModelValidator : AbstractValidator<SampleModel>
    {
        public SampleModelValidator()
        {
            this.RuleFor(x => x.Step1Validation)
                .NotEmpty()
                .When(x => x.StepNumber >= 1)
                .WithMessage("Step1 Validation Required");
    
            this.RuleFor(x => x.Step2Validation)
                .NotEmpty()
                .When(x => x.StepNumber >= 2)
                .WithMessage("Step2 Validation Required.");
        }
    }
    

    现在查看方法调用(在构造函数中注释)基本上就是这样读。

    1. 为表达式属性(Linq Expression)创建规则
    2. As As Empty(几乎是必填字段)
    3. 当LinqExpression匹配时(请注意,这是可选的,不运行所有规则)
    4. 所以我们可以阅读。在Step1Validation时将NotEmpty验证为StepNumber is greater or equal to 1

      现在要将验证器插入到类中,您必须使用ValidatorAttribute(Type type)属性装饰该类。

      [Validator(typeof(SampleModelValidator))]
      public class SampleModel
      {
          //omiteed
      }
      

      最后我们的控制器和视图(注意这些非常基本)。 控制器:

      [HttpGet]
      public ActionResult Index()
      {
          var model = new SampleModel();
          model.StepNumber = 1;
          return View(model);
      }
      
      [HttpPost]
      public ActionResult Index(SampleModel model)
      {
          if (model == null)
          {
              model = new SampleModel();
              return View(model);
          }
          if (!ModelState.IsValid)
              return View(model);
      
          model.StepNumber++;
          return View(model);
      }
      

      查看:

          @using (Html.BeginForm())
          {
              @Html.HiddenFor(x => x.StepNumber)
              if (Model.StepNumber == 1)
              {
                  <div class="row">
                      <div class="col-md-4">
                          @Html.LabelFor(x => x.Step1Validation)
                      </div>
                      <div class="col-md-8">
                          @Html.EditorFor(x => x.Step1Validation)
                          @Html.ValidationMessageFor(x => x.Step1Validation)
                      </div>
                  </div>
                  <div class="row">
                      <button type="submit" class="btn btn-primary">Next</button>
                  </div>
              }
              else if (Model.StepNumber == 2)
              {
                  @Html.HiddenFor(x => x.Step1Validation)
                  <div class="row">
                      <div class="col-md-4">
                          @Html.LabelFor(x => x.Step2Validation)
                      </div>
                      <div class="col-md-8">
                          @Html.EditorFor(x => x.Step2Validation)
                          @Html.ValidationMessageFor(x => x.Step2Validation)
                      </div>
                  </div>
                  <div class="row">
                      <button type="submit" class="btn btn-primary">Next</button>
                  </div>
              }
              else
              {
                  <h4>All Done</h4>
              }
          }
      

      现在这又需要另一个库,但根据我的经验,这个库值得参考。