我正在构建一个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。那会有意义吗?
答案 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; }
}
非常简单的模型。基本上我们有三个属性。
StepNumber
:确定我们当前的步骤Step1Validation
:我们验证的所有步骤都不为空的简单字符串Step2Validation
:从第2步开始再次使用简单字符串。现在,在此模型中,我们基于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.");
}
}
现在查看方法调用(在构造函数中注释)基本上就是这样读。
所以我们可以阅读。在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>
}
}
现在这又需要另一个库,但根据我的经验,这个库值得参考。