【问题标题】:Why does an ASP.NET MVC 4 Custom validator cause a routing error?为什么 ASP.NET MVC 4 自定义验证器会导致路由错误?
【发布时间】:2014-01-02 20:45:34
【问题描述】:

我有一个似乎可以正常工作的 ASP.NET MVC 4 应用程序。我编写了一个自定义 ValidatorAttribute 以确保一个属性的值不小于另一个。由于涉及到两个属性,我重写了 IsValid(object, context)。

我使用 Validator.TryValidateObject 和属性的 Validate(object, context) 成员编写单元测试,它们按预期通过。我包括对有效值和无效值的预期用途的测试。我包括将属性应用于正确类型的属性并获得预期行为的测试(如果任一属性类型错误,我的设计选择是通过。)

我将属性添加到我的模型中,并将其连接到应用程序中。比如:

public abstract class DataElement
{
    ...

    [Required]
    public string Version { get; set; }

    [StringLength(8, ErrorMessage = "8 characters or less")]
    [Required(ErrorMessage = "Required")]
    [DisplayName("ID")]
    public string DataElementNumber { get; set; }
    ...
}

public abstract class SimpleElement : DataElement
{
    [Required]
    [DisplayName("Minimum")]
    public int MinimumLength { get; set; }

    [Required]
    [DisplayName("Maximum")]
    [NotSmallerThan("MinimumLength")]
    public int MaximumLength { get; set; }
}

public class CodeList: SimpleElement
{
    public Collection<CodeValue> Values { get; set; }
}

我有一个类似的控制器

    [HttpGet]
    public ActionResult Edit(string elementId, string version)
    {
        CodeList model = Store.GetCodeList(elementId, version);
        return View(model);
    }

    [HttpPost]
    public ActionResult Edit(CodeList model)
    {
        ActionResult result;
        if (ModelState.IsValid)
        {
            Store.Upsert(model);
            result = RedirectToAction("Index", "SomeOtherController");
        }
        else
        {
            result = View(model.DataElementNumber, model.Version);
        }

        return result;
    }

我觉得很简单。如果模型有效,则提交到数据存储。如果它无效,请重新显示表单,并带有验证消息。在我在表单中输入有效值的情况下,验证器会按预期运行,即应用程序将值提交到数据存储并继续前进。

在我输入的最小值小于最大值的情况下,我要防范这种情况,而不是看到我的视图,我再次看到一个错误屏幕,类似于 DataElementNumber=" 的情况XML-25" 和 Version="201301"

未找到视图“XML-25”或其主视图,或者没有视图引擎支持搜索到的位置。搜索了以下位置:

~/Views/CodeListBuilder/XML-25.aspx

~/Views/CodeListBuilder/XML-25.ascx

~/Views/Shared/XML-25.aspx

~/Views/Shared/XML-25.ascx

~/Views/CodeListBuilder/201301.master

~/Views/Shared/201301.master

~/Views/CodeListBuilder/XML-25.cshtml

~/Views/CodeListBuilder/XML-25.vbhtml

~/Views/Shared/XML-25.cshtml

~/Views/Shared/XML-25.vbhtml

~/Views/CodeListBuilder/201301.cshtml

~/Views/CodeListBuilder/201301.vbhtml

~/Views/Shared/201301.cshtml

~/Views/Shared/201301.vbhtml

说明:在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详情:System.InvalidOperationException:...

我可以注释掉自定义的 NotSmallerThanAttribute 并且系统会按照我的预期运行,除了表单能够输入小于最小值的最大值。我不确定如何诊断。验证器中的哪些行为会混淆路由引擎?我如何找到它? TIA

【问题讨论】:

  • 您的问题与您的自定义验证器无关,而是与View(model.Id) 语句有关...Id 的类型是什么?价值是什么?在搜索到的位置中是否有名为 Edit.csthml 的视图?
  • 如果将result = View(model.Id); 更改为result = View("MyEditView", model);(同时删除.Id)会怎样?
  • 为什么会有一个名为 Bob 的视图,如果这不是具体的错误信息,请附上抛出的具体错误信息,而不是示例。
  • @Erick,我不想将这个问题与许多我必须解释的内部问题混淆。报告视图的实际值是“XML-25”,这不是视图的名称,它是视图 ID 的一部分。我的“Id”实际上是一个复合的。我有调用视图的 [HttpGet]Edit(string elementId, string version){..},我对视图的实际调用是 result=View(model.DataElementNumber, model.Version)。错误开始 未找到视图“XML-25”或其主视图,或者没有视图引擎支持搜索到的位置。搜索了以下位置:~/V...
  • @nenesv,我的视图中有 Edit.cshtml。它与处理 POST 并调用验证器时收集值的位置相同。

标签: c# asp.net-mvc validation asp.net-mvc-4


【解决方案1】:

您的问题与您的验证器无关。

使用result = View(model.DataElementNumber, model.Version);,您正在使用View method: 的以下重载

protected internal ViewResult View(
    string viewName,
    string masterName
)

所以框架认为你的 model.DataElementNumber 是你的 viewName 而你的 model.Version 你的 masterName 这就是为什么你会得到这个奇怪的 view missing 异常。

要解决此问题,您只需使用 correct overload 并传入您的 model

result = View(model);

MVC 将负责重新显示您之前发布的 DataElementNumber 和 Version 值。

【讨论】:

  • 我会买那个。为什么我在删除验证器时看不到相同的行为?我没有更改控制器,但它找到了正确的视图。
  • 是的,因为如果没有验证器,您的模型是有效的并且您的代码运行或者是不同的路径,或者因为您的 model.DataElementNumbermodel.Version 是空的,所以 MVC 回退到其默认行为并寻找正确的看法。
  • :-o 这一切我都知道!感谢您的评论!
猜你喜欢
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多