为什么 MVC 在 GET 上使用 Modelstate 而不是提供的模型

2024-01-27

当 MVC 运行时ActionMethod它将填充ModelState字典并使用ModelBinder建立ActionMethod参数(如果有)。它对两者都这样做GET and POST。这是有道理的。

之后ActionMethod已成功运行,视图使用提供的剃刀进行渲染,在我的例子中使用了尽可能多的剃刀HtmlHelper尽可能打电话。到目前为止,您可能会想,“是的,我知道 MVC 是如何工作的”。等一下,我这就到了。

当我们使用例如@Html.TextFor(m => m.Name)MVC使用的代码可以是here https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/Html/InputExtensions.cs来渲染标签。

有趣的部分是在文件的末尾,我们发现:

switch (inputType)
{
    case InputType.CheckBox:
        // ... removed for brevity
    case InputType.Radio:
    // ... removed for brevity
    case InputType.Password:
    // ... removed for brevity
    default:
        string attemptedValue = 
               (string)htmlHelper.GetModelStateValue(fullName, typeof(string));
        tagBuilder.MergeAttribute("value", attemptedValue ?? 
               ((useViewData) 
                  ? htmlHelper.EvalString(fullName, format) 
                  : valueParameter), isExplicitValue);
        break;
} 

这意味着Modelstate用于获取超过所提供的值Model。这对于POST因为当出现验证错误时,您希望 MVC 使用用户已提供的值来渲染视图。文档也说明了这种行为,StackOverflow 上有几篇帖子证实了这一点。但它的规定仅适用于POST,如上所示这个线程 https://stackoverflow.com/a/8191658/3294832例如

然而,当渲染视图时也会使用此代码GET!这对我来说毫无意义。

考虑以下操作方法:

public ActionResult GetCopy(Guid id)
{
    var originalModel = this.repository.GetById(id);
    var copiedModel = new SomeModel
    {
        Id = Guid.NewGuid(),
        Name = originalModel.Name,
    };

    return this.View(copiedModel);
}

使用这个简单的剃​​刀标记:

    @Html.TextBoxFor(m => m.Id)
    @Html.TextBoxFor(m => m.Name)

我希望视图显示新生成的GUID而不是Id原始模型的。然而该视图显示Id传递给action方法GET请求因为ModelState字典包含一个带有名称的键Id.

我的问题不是如何解决这个问题,因为这相当简单:

  • 重命名ActionMethod参数不同
  • 清除ModelState在返回之前ActionResult using Modelstate.Clear()
  • 替换中的值ModelState字典并且不提供Model根本看不到风景。

我的问题是: 为什么这个过程对于两者来说是相同的GET and POST。是否有使用填充的有效用例ModelState超过提供的Model on a GET.


The DefaultModelBinder不区分 GET 和 POST 请求。虽然只有 MVC 团队可以确认他们为什么做出这个决定,但有有效的用例来解释为什么ModelState应该在 GET 中使用(与在 POST 中使用的方式相同),因为您也可以将表单提交到 GET 方法。

以航空公司预订应用程序为例,您有一个模型,其中的属性可以选择出发和到达地点、日期和乘客数量(int属性),加上过滤结果的集合属性。 GET 方法签名可能如下所示

public ActionResult Search(SearchViewModel model)

该视图包含一个返回该方法的 GET 方法,并包含一个用于显示乘客数量的文本框。

禁用了 javascript 的(不太聪明的)用户在文本框中输入“TWO”并提交表单。您的方法返回视图而不填充可用航班的集合,因为ModelState无效(值“TWO”对于int),现在用户看到一条错误消息,指出乘客字段必须是数字.

如果使用模型值而不是ModelState值,然后关联的文本框将显示0代替"Two",使错误消息变得混乱(但是0是一个数字! - 我输入的内容发生了什么?)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 MVC 在 GET 上使用 Modelstate 而不是提供的模型 的相关文章

随机推荐

  • Python - 检查类是否存在

    有没有办法检查类是否已定义 存在 我的菜单上有不同的选项 其中一些需要继承变量 因此如果您在设置变量之前尝试选择该函数 它会崩溃 我的课程名为 Gen0 我通过简单地输入 class Gen0 接下来是设置变量的其余代码 对于上下文 我正在
  • Reset_cooldown Discord.py

    我对discord py 和Python 都很陌生 但我正在努力学习 我不知道如何将 command reset cooldown 添加到我的代码中 正如下面代码中所说 我希望 test 忽略冷却时间 但我希望 test 2 有冷却时间 有
  • Spring Boot 中的 JAX-RS 和 MVC

    我有一个作为 MVC 工作的 Spring Boot 应用程序 我想在我的应用程序中使用 JAX RS 而不使用 Spring 注释 我将在不同的类中同时拥有 JAX RS 带注释的组件和 MVC 组件 当我添加 Jersey 资源配置时
  • Boost Container向量可以通过非原始指针管理内存吗?

    我有一个类似指针的结构来代替指针 与指针的区别在于它具有额外的信息 也是特殊的 分配器可以用来释放内存 这种类似指针的结构适用于所有基本用途 我可以分配和释放内存 解引用 增量 gt etc 现在我想使用这个指针来由类似STL的容器来管理
  • 邮递员到普罗米修斯和马车“\r”?第 1 行中的文本格式解析错误:预期浮点数作为值,得到“1\r”

    只是试图通过邮递员向普罗米修斯添加新的指标 但是得到 第 1 行中的文本格式解析错误 预期浮点数作为值 得到 1 r 度量就像 test metric 1 不带引号 为什么会发生这种情况以及如何将其从邮递员的请求中删除 原因在于之间的差异
  • 这里使用指针向量是不必要的还是更糟,会导致内存泄漏?

    我对 C 编程相对较新 但我是一名有 10 年经验的 C 程序员 因此我对对象的指针比对对象的引用更熟悉 我正在编写一款纸牌游戏 这种设计不安全吗 有没有更好的办法 无论如何 我还有课SolitaireGame class Solitair
  • 如何动态获取程序集名称[重复]

    这个问题在这里已经有答案了 我在图书馆里有一堂课是这样的 namespace Foo public abstract class EventBase public string EventSource gt Assembly GetExec
  • IE9 中的 iframe 中未发送 Cookie

    首先 我在发布这个问题之前做了一些研究 所以我知道P3P政策 https stackoverflow com questions 389456 cookie blocked not saved in iframe in internet e
  • php 多个 if 语句?

    抱歉 这看起来像是一个菜鸟问题 今天早上我的大脑无法运转 我正在尝试执行多个if声明 但他们的行为不正确 在找到它正在寻找的模板后 它似乎总是加载最少的模板 做这样的事情的最好方法是什么 post wp query gt post if i
  • 如何用Python中的其他字符替换字符串中的unicode字符?

    我有一个从阅读带有项目符号的 HTML 网页中获得的字符串 由于项目符号列表 这些项目符号具有类似 的符号 请注意 文本是来自使用 Python 2 7 的网页的 HTML 源代码urllib2 read webaddress 我知道项目符
  • 将物理网卡绑定到docker容器

    我的主机 PC 上安装了 4 个 NIC 我想启动不同的 docker 容器 并将不同的物理网卡绑定到每个容器 我能为docker做些什么 对于 VirtualBox 这可以通过为物理网卡的每个虚拟机创建桥接适配器来完成 当您使用 Dock
  • 版权元标记在 HTML5 中有效吗?

    W3C 验证器输出 第 5 行 第 41 列 元素元上的属性名称版权值错误 未注册关键字版权 我需要设置版权 任何想法 都柏林核心提出rightsHolder https www dublincore org specifications
  • 了解接口内部接口(嵌入式接口)

    我试图用以下代码来理解接口嵌入 我有以下内容 type MyprojectV1alpha1Interface interface RESTClient rest Interface SamplesGetter SamplesGetter h
  • 仅 CSS 3D 旋转文本

    我有一个带有一些文本旋转的 div 如何获得文本深度以提供更好的 3D 效果 为了澄清 在90deg文本变成1px厚 因为我们只能从侧面看到它 我该如何制作它 例如 10px厚的 此外 应显示适当的深度 即在0deg我们看不到深度 在45d
  • 在用户可见活动后执行方法

    我的活动包含太多 UI 控件 我想在使活动可见后执行一个方法 我尝试过的一个例子 public class Main extends Activity Override public void onCreate Bundle savedIn
  • Android 画布保存总是 java.io.IOException: 打开失败: ENOENT (没有这样的文件或目录)

    我有一个画布应用程序 我正在尝试创建一个签名应用程序Canvas onTouchListener 这是我的保存方法 我尝试将签名保存到图像中 private void save hideMenuBar View content this c
  • Travis 尝试将应用提交到 Google Play 商店时出错

    我首先研究了在 Github 上找到的几个要点 https gist github com lpetre 87a5196d14cf4484f1f2 https gist github com lpetre 87a5196d14cf4484f
  • sphinx4 中的语音识别响应很差

    目前我们正在研究使用 sphinx4 进行语音识别 我们正在努力为听写类型应用程序取得良好的响应 输入是一个 wav 文件 我们希望转录它 我研究了 Sphinx4 提供的 LatticeDemo 和 Transscriber 演示 当我使
  • SBT:依赖其他SBT项目而不发布

    我有一组松散相关的组件 其中一些组件依赖于其他组件 为了具体起见 我们假设我们有组件 common a 和 b common 没有任何依赖项 但所有其他项目都使用 common 此外 a 依赖于 b 所有组件都是用 Scala 编写的 我想
  • 为什么 MVC 在 GET 上使用 Modelstate 而不是提供的模型

    当 MVC 运行时ActionMethod它将填充ModelState字典并使用ModelBinder建立ActionMethod参数 如果有 它对两者都这样做GET and POST 这是有道理的 之后ActionMethod已成功运行