Asp.net mvc 4 .NET MVC4 ActionNameSelectorAttribute视图中的多个按钮不工作

Asp.net mvc 4 .NET MVC4 ActionNameSelectorAttribute视图中的多个按钮不工作,asp.net-mvc-4,button,razor,view,controller,Asp.net Mvc 4,Button,Razor,View,Controller,我读过很多关于允许不同视图按钮的不同控制器操作的帖子。然而,我无法让它工作 我使用从中获得的这个代码片段 当我逐步浏览这段代码时,我看到了actionName与methodInfo.Name的比较。当整个目的是命名不同于控制器操作的方法时,这些方法怎么可能相等呢 对于行为/功能而言,true或false的返回值实际上意味着什么 我是否应该用“操作”覆盖“fciContactUs”操作 控制器=“HomeController” 视图(视图名称为“fciContactUs”)表单开始: @using

我读过很多关于允许不同视图按钮的不同控制器操作的帖子。然而,我无法让它工作

我使用从中获得的这个代码片段

当我逐步浏览这段代码时,我看到了
actionName
methodInfo.Name
的比较。当整个目的是命名不同于控制器操作的方法时,这些方法怎么可能相等呢

对于行为/功能而言,true或false的返回值实际上意味着什么

我是否应该用“操作”覆盖“fciContactUs”操作

控制器=“HomeController”

视图(视图名称为“fciContactUs”)表单开始:

@using (Html.BeginForm("Action", "Home"))  {
查看按钮:

<input type="submit" name="TrySubmit" value="Submit" />
<input type="submit" name="DoClearForm" value="Clear Form" />

此外,这个
IsValidName
方法总是返回false,并且这些方法永远不会执行

我担心操作名称、视图名称、控制器名称、按钮名称和
ActionNameSelectorAttribute
类重写中存在不一致

我是新加入MVC的,这整件事让我很纠结


任何意见或帮助都将不胜感激。

让我们从
HttpParamActionAttribute
开始。这继承自
ActionNameSelectorAttribute
,其中:

表示影响操作方法选择的属性

因此,当应用于一个操作,并且有一个请求(get或post)传入时,将调用此属性以查看该操作是否确实是正确的操作

它通过调用IsValidName(稍微令人困惑的方法,最好是“IsMatchingAction”或类似方法)来确定这一点。IsvalidName:

确定操作名称在指定的控制器上下文中是否有效

带参数:

控制器上下文:控制器上下文
actionName:操作的名称
methodInfo:有关操作方法的信息

摘自博客文章,您可以通过
controllerContext
获取请求和该请求上的所有值

如果匹配,则返回
true
;如果不是我们要查找的操作,则返回
false

当它被击中时:

  • actionName=来自
    BeginForm
    的操作名称,硬编码为“操作”
  • methodInfo=应用属性的控制器操作(方法),例如
    TrySubmit
因此,第一个检查:

if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
    return true;
如果您在
BeginForm
中指定了除操作之外的其他内容,那么它将转到请求的操作(即不是“操作”),那么它只是一个总括

第二项检查检查您是否在
BeginForm

现在是“聪明”部分:

这将检查所有
请求
参数,以查看是否有与控制器操作(方法)匹配的参数

单击
提交
按钮时,该提交按钮的
名称
将在请求参数中传递

因此,如果你有:

<input type="submit" name="TrySubmit" value="Submit" />
<input type="submit" name="DoClearForm" value="Clear Form" />
如果你点击“清除表单”,那么

实际值(“Submit”/“Clear Form”)是不需要的,只是它不为空

那么代码呢

request[methodInfo.Name] 
检查请求参数是否存在与当前控制器操作(方法)名称匹配的项,例如:

[HttpParamAction]
public ActionResult DoClearForm() 
{

要回答您的第一个问题:

我看到actionName与methodInfo.Name的比较。当整个目的是命名不同于控制器操作的方法时,这些方法怎么可能相等呢

第一个比较是当
BeginForm
未指定操作且
BeginForm
的操作与控制操作(方法)名称匹配时的覆盖

因此,在您的场景中,不,它们不相等,也不应该相等-这是最后一次相关检查


现在的问题是:

为什么这不适合你

问题是您的操作名称与预期的操作名称不匹配,因为您有以下情况:

[ActionName("Action")]
因此,
HttpParamAction
属性找到您的控制器操作(方法)并说“使用这个”,但MVC说,但我在寻找“操作”,而不是“操作”,所以我会给您“找不到资源”。我不是100%的原因,但如果使用MVC5
Route(“Action”)
,它无法找到已经使用属性匹配的操作

如果删除
[ActionName(“Action”)]
,则一切都应该正常


备选方案:如果删除前两个检查(如果表单操作=控制器操作,如果表单操作!=“操作”),并且只将属性应用于所需的方法(为什么要在其他地方应用它?),那么它似乎可以正常工作

现在,我正在使用
[Route(“”)]
并更改了:

将表格发送至:

using (Html.BeginForm("", "", FormMethod.Post, ...
控制员应:

[HttpParamAction]
[HttpPost]
[Route("")]
public ActionResult DoClearForm() 
{
(初始的
[HttpGet]
还有
[Route(“”)

属性为:

public class HttpParamActionAttribute : ActionNameSelectorAttribute 
{
    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) 
    {
        var request = controllerContext.RequestContext.HttpContext.Request;
        return request[methodInfo.Name] != null;
    }
}

另一种选择是,您的“ClearForm”按钮看起来只是重定向到页面。您可以通过一个简单的
@Html.ActionLink(“Clear Form”,“fciContractUS”)
和一点css使其看起来像一个按钮,更容易做到这一点

如果您有任何客户端验证(如必填字段),您也会遇到问题,因为在表单有值之前,您将无法“提交”以清除表单

[HttpParamAction]
public ActionResult DoClearForm() 
{
[ActionName("Action")]
using (Html.BeginForm("", "", FormMethod.Post, ...
[HttpParamAction]
[HttpPost]
[Route("")]
public ActionResult DoClearForm() 
{
public class HttpParamActionAttribute : ActionNameSelectorAttribute 
{
    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) 
    {
        var request = controllerContext.RequestContext.HttpContext.Request;
        return request[methodInfo.Name] != null;
    }
}