使用流畅验证验证视图模型时出现问题

发布于 2024-10-08 05:43:55 字数 5666 浏览 0 评论 0原文

我正在尝试使用流畅的验证来验证视图模型。当我发布 viewmodel 对象时,modelstate.isvalid 始终返回 false。当我检查已发布对象上的值时,用于获取要在下拉列表中显示的数据的属性也正在验证。怎么解决这个问题。我这样做是否错误,请帮助。 我是 ASP.net MVC 的新手,只是尝试在这个项目中使用流畅的验证和流畅的 NHibernate 映射。

更多详细信息如下:

我有一个域模型对象如下:

[Validator(typeof(TestRequirementValidator))]
public class TestRequirement
{
  public virtual int Id { get; private set; } 
  public virtual int SampleId { get; set; }
  public virtual int TestId { get; set; }
  public virtual int StandardId { get; set; }    
  public virtual string Description { get; set; }
  public virtual Sample Sample { get; set; }
  public virtual Test Test { get; set; }
  public virtual Standard Standard { get; set; }
}

我创建了一个视图模型如下:

[Validator(typeof(TestRequirementViewModelValidator))]
public class TestRequirementViewModel
{
  public TestRequirement TestRequirement; 
  public SelectList Samples;
  public SelectList Tests;
  public SelectList Standards;

  public TestRequirementViewModel()
  {
    ISession _session = FNHsessionFactory.GetSessionFactory();
    this.TestRequirement = new TestRequirement();
    this.Samples = new SelectList(from S in _session.Linq<Sample>() select S, "Id", "Name");
    this.Tests = new SelectList(from T in _session.Linq<Test>() select T, "Id", "Name");
    this.Standards = new SelectList(from St in _session.Linq<Standard>() select St, "Id", "Name");
  }
}

模型验证器如下:

public class TestRequirementValidator : AbstractValidator<TestRequirement>
{
  public TestRequirementValidator()
  {    
    RuleFor(x => x.SampleId)
     .NotEmpty()
     .WithMessage("This field is required")
     .DisplayName("Sample Name");

    RuleFor(x => x.TestId)
      .DisplayName("Test Name"); 

    RuleFor(x => x.StandardId)
      .NotEmpty()
      .WithMessage("This field is required")
      .DisplayName("Standard Name");

    RuleFor(x => x.Description)
      .NotEmpty()
      .WithMessage("This field is required")                
      .Length(0, 10)
      .WithMessage("Length of this field cannot be more than 10 characters");
  }
}

视图模型验证器如下:

public class TestRequirementViewModelValidator:AbstractValidator-TestRequirementViewModel-
{
  public TestRequirementViewModelValidator()
  {            
    RuleFor(x => x.TestRequirement)
      .SetValidator(new TestRequirementValidator());   
  }
}

视图如下:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<foo.Models.ViewModels.TestRequirementViewModel>" MasterPageFile="~/Views/shared/site.master" %>
<asp:Content ContentPlaceHolderID="MainContent" ID="MainContentContent" runat="server">
  <h3><%= Html.Encode(ViewData["Message"]) %></h3>

  <% using (Html.BeginForm()) {%>
    <%= Html.ValidationSummary(true) %>
    <fieldset>
      <legend>Create Test Requirement</legend>  

      <div class="editor-label">
        <%= Html.LabelFor(model => model.TestRequirement.SampleId) %>
      </div>

      <div class="editor-field">
        <%= Html.DropDownListFor(model => model.TestRequirement.SampleId, new SelectList(Model.Samples.Items, Model.Samples.DataValueField, Model.Samples.DataTextField), "Select Sample") %>
        <%= Html.ValidationMessageFor(model => model.TestRequirement.SampleId) %>
      </div>

      <div class="editor-label">
        <%= Html.LabelFor(model => model.TestRequirement.TestId) %>
      </div>

      <div class="editor-field">
        <%= Html.DropDownListFor(model => model.TestRequirement.TestId, new SelectList(Model.Tests.Items, Model.Tests.DataValueField, Model.Tests.DataTextField), "Select Test") %>
        <%= Html.ValidationMessageFor(model => model.TestRequirement.TestId) %>
      </div>

      <div class="editor-label">
        <%= Html.LabelFor(model => model.TestRequirement.StandardId) %>
      </div>

      <div class="editor-field">
        <%= Html.DropDownListFor(model => model.TestRequirement.StandardId, new SelectList(Model.Standards.Items, Model.Standards.DataValueField, Model.Standards.DataTextField), "Select Standard") %>
        <%= Html.ValidationMessageFor(model => model.TestRequirement.StandardId) %>
      </div>

      <div class="editor-label">
        <%= Html.LabelFor(model => model.TestRequirement.Description) %>
      </div>

      <div class="editor-field">
        <%= Html.TextBoxFor(model => model.TestRequirement.Description) %>
        <%= Html.ValidationMessageFor(model => model.TestRequirement.Description) %>
      </div>

      <p>
        <input type="submit" value="Create" />
      </p>
    </fieldset>  
  <% } %>

  <%= Html.ClientSideValidation<TestRequirement>("TestRequirement") %>
</asp:Content>

控制器如下:

public ActionResult TestRequirement()
{   
  TestRequirementViewModel NewTestRequirement = new TestRequirementViewModel();
  return View(NewTestRequirement);
} 

[HttpPost]
public ActionResult TestRequirement(TestRequirementViewModel NewTestRequirement)
{
  if(ModelState.IsValid)
  {
    ISession _session = FNHsessionFactory.GetSessionFactory();    
    _session.SaveOrUpdate(NewTestRequirement.TestRequirement);    

    ViewData["Message"] = "New Test Requirement has been created successfully";

    return View();
  }

  return View(NewTestRequirement);
}

I am trying to validate a viewmodel using fluent validation. When i post the viewmodel object, the modelstate.isvalid always returns false. When i have checked the values on the posted object, the properties which were used to get the data to be shown in dropdowns are also being validated. How to resolve this. Am i doing it in a wrong way, pls help.
I'm new to ASP.net MVC and just trying out using fluent validation and fluent NHibernate mappings in this project.

More details as follows:

I have a domain model object as below:

[Validator(typeof(TestRequirementValidator))]
public class TestRequirement
{
  public virtual int Id { get; private set; } 
  public virtual int SampleId { get; set; }
  public virtual int TestId { get; set; }
  public virtual int StandardId { get; set; }    
  public virtual string Description { get; set; }
  public virtual Sample Sample { get; set; }
  public virtual Test Test { get; set; }
  public virtual Standard Standard { get; set; }
}

I have created a view model as below:

[Validator(typeof(TestRequirementViewModelValidator))]
public class TestRequirementViewModel
{
  public TestRequirement TestRequirement; 
  public SelectList Samples;
  public SelectList Tests;
  public SelectList Standards;

  public TestRequirementViewModel()
  {
    ISession _session = FNHsessionFactory.GetSessionFactory();
    this.TestRequirement = new TestRequirement();
    this.Samples = new SelectList(from S in _session.Linq<Sample>() select S, "Id", "Name");
    this.Tests = new SelectList(from T in _session.Linq<Test>() select T, "Id", "Name");
    this.Standards = new SelectList(from St in _session.Linq<Standard>() select St, "Id", "Name");
  }
}

Model Validator is as below:

public class TestRequirementValidator : AbstractValidator<TestRequirement>
{
  public TestRequirementValidator()
  {    
    RuleFor(x => x.SampleId)
     .NotEmpty()
     .WithMessage("This field is required")
     .DisplayName("Sample Name");

    RuleFor(x => x.TestId)
      .DisplayName("Test Name"); 

    RuleFor(x => x.StandardId)
      .NotEmpty()
      .WithMessage("This field is required")
      .DisplayName("Standard Name");

    RuleFor(x => x.Description)
      .NotEmpty()
      .WithMessage("This field is required")                
      .Length(0, 10)
      .WithMessage("Length of this field cannot be more than 10 characters");
  }
}

View model validator is as below:

public class TestRequirementViewModelValidator:AbstractValidator-TestRequirementViewModel-
{
  public TestRequirementViewModelValidator()
  {            
    RuleFor(x => x.TestRequirement)
      .SetValidator(new TestRequirementValidator());   
  }
}

View is as below:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<foo.Models.ViewModels.TestRequirementViewModel>" MasterPageFile="~/Views/shared/site.master" %>
<asp:Content ContentPlaceHolderID="MainContent" ID="MainContentContent" runat="server">
  <h3><%= Html.Encode(ViewData["Message"]) %></h3>

  <% using (Html.BeginForm()) {%>
    <%= Html.ValidationSummary(true) %>
    <fieldset>
      <legend>Create Test Requirement</legend>  

      <div class="editor-label">
        <%= Html.LabelFor(model => model.TestRequirement.SampleId) %>
      </div>

      <div class="editor-field">
        <%= Html.DropDownListFor(model => model.TestRequirement.SampleId, new SelectList(Model.Samples.Items, Model.Samples.DataValueField, Model.Samples.DataTextField), "Select Sample") %>
        <%= Html.ValidationMessageFor(model => model.TestRequirement.SampleId) %>
      </div>

      <div class="editor-label">
        <%= Html.LabelFor(model => model.TestRequirement.TestId) %>
      </div>

      <div class="editor-field">
        <%= Html.DropDownListFor(model => model.TestRequirement.TestId, new SelectList(Model.Tests.Items, Model.Tests.DataValueField, Model.Tests.DataTextField), "Select Test") %>
        <%= Html.ValidationMessageFor(model => model.TestRequirement.TestId) %>
      </div>

      <div class="editor-label">
        <%= Html.LabelFor(model => model.TestRequirement.StandardId) %>
      </div>

      <div class="editor-field">
        <%= Html.DropDownListFor(model => model.TestRequirement.StandardId, new SelectList(Model.Standards.Items, Model.Standards.DataValueField, Model.Standards.DataTextField), "Select Standard") %>
        <%= Html.ValidationMessageFor(model => model.TestRequirement.StandardId) %>
      </div>

      <div class="editor-label">
        <%= Html.LabelFor(model => model.TestRequirement.Description) %>
      </div>

      <div class="editor-field">
        <%= Html.TextBoxFor(model => model.TestRequirement.Description) %>
        <%= Html.ValidationMessageFor(model => model.TestRequirement.Description) %>
      </div>

      <p>
        <input type="submit" value="Create" />
      </p>
    </fieldset>  
  <% } %>

  <%= Html.ClientSideValidation<TestRequirement>("TestRequirement") %>
</asp:Content>

Controller is as below:

public ActionResult TestRequirement()
{   
  TestRequirementViewModel NewTestRequirement = new TestRequirementViewModel();
  return View(NewTestRequirement);
} 

[HttpPost]
public ActionResult TestRequirement(TestRequirementViewModel NewTestRequirement)
{
  if(ModelState.IsValid)
  {
    ISession _session = FNHsessionFactory.GetSessionFactory();    
    _session.SaveOrUpdate(NewTestRequirement.TestRequirement);    

    ViewData["Message"] = "New Test Requirement has been created successfully";

    return View();
  }

  return View(NewTestRequirement);
}

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

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

发布评论

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

评论(1

丢了幸福的猪 2024-10-15 05:43:55

我无法帮助 Fluent Validation,但由于您已将其标记为 Fluent-nhibernate,所以我想我应该对您的 NHibernate 使用情况发表评论。

您的视图模型不应在其构造函数中使用 NHibernate;事实上,您的视图模型应该只是一个由外部服务填充的数据结构。同样,您可能想对控制器执行相同的操作;人们通常会将数据访问提取到 存储库 中以隔离他们的控制器(并使测试更容易,你正在测试不是吗?)。

如果您使用存储库,则可以从实体投影视图模型;您可以使用 NHibernate 投影和转换器 或通过使用诸如 AutoMapper 之类的工具。

I can't help with Fluent Validation, but as you've tagged this as fluent-nhibernate I thought I should comment on your NHibernate usage.

Your view model should not be using NHibernate in its constructor; in fact, your view model should just be a data structure that gets populated by an external service. Similarly, you might want to do the same with your controller; it's common for people to extract data access into a repository to isolate their controllers (and make testing easier, you are testing aren't you?).

If you're using a repository, you can then project your view model from your entity; you can do that either by using NHibernate projections and transformers or by using a tool like AutoMapper.

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