.NET MVC4 ActionNameSelectorAttribute 视图中的多个按钮不起作用 [英] .NET MVC4 ActionNameSelectorAttribute multiple buttons within View is not working

查看:36
本文介绍了.NET MVC4 ActionNameSelectorAttribute 视图中的多个按钮不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了很多关于允许不同视图按钮的不同控制器操作的帖子.但是,我无法让它发挥作用.

I have read many posts about allowing different controller actions for different view-buttons. However, I cannot get this to work.

我使用从 http://blog.ashmind.com/2010/03/15/multiple-submit-buttons-with-asp-net-mvc-final-solution/.

public class HttpParamActionAttribute : ActionNameSelectorAttribute 
{
    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) 
    {
        if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
            return true;

        if (!actionName.Equals("Action", StringComparison.InvariantCultureIgnoreCase))
            return false;

        var request = controllerContext.RequestContext.HttpContext.Request;
        return request[methodInfo.Name] != null;
    }
}

当我逐步执行此代码时,我看到 actionNamemethodInfo.Name 的比较.当整个目的是命名与控制器操作不同的方法时,这些怎么可能相等.

When I step through this code, I see a compare of actionName with methodInfo.Name. How can these EVER be equal when the whole purpose is to name the method different from the controller's action.

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

What is the return value of true or false actually mean as to the behavior/functionality?

我应该用Action"覆盖fciContactUs"操作吗?

Should I be overriding the 'fciContactUs' action with 'Action'?

控制器 = "HomeController"

The Controller = "HomeController"

  [HttpParamAction]
  [ActionName("Action")]
  [AcceptVerbs(HttpVerbs.Post)]
  [ValidateInput(false)]
  public ActionResult DoClearForm(fciContactUs p_oRecord)
  {
     return RedirectToAction("fciContactUs");
  }

  [HttpParamAction]
  [ActionName("Action")]
  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult TrySubmit(fciContactUs p_oRecord)
  {
     // This must be the Submit command.
     if (ModelState.IsValid)
     {  ...etc....} 
  }

视图(视图名称是'fciContactUs')表单开始:

The View (view name is 'fciContactUs') form-start:

@using (Html.BeginForm("Action", "Home"))  {

视图按钮:

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

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

Further, this IsValidName method ALWAYS returns false and the methods NEVER get executed.

我担心操作名称、视图名称、控制器名称、按钮名称和 ActionNameSelectorAttribute 类覆盖不一致.

I am concerned that there is an inconsistency in the action-name, the view-name, the controller-name, the button-names and the ActionNameSelectorAttribute class override.

我是 MVC 的新手,这整件事让我很困惑.

I am new to MVC and this whole thing has got me twisted up.

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

Any comments or assistance will be greatly appreciated.

推荐答案

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

Let's start with the HttpParamActionAttribute. This inherits from ActionNameSelectorAttribute which:

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

Represents an attribute that affects the selection of an action method.

所以,当应用于一个动作,并且一个请求(get 或 post)进来时,这个属性将被调用以查看该动作是否确实是正确的动作.

so, when applied to an action, and a request (get or post) comes in, this attribute will be called to see if that action is indeed the correct action.

它通过调用 IsValidName 来确定这一点(有点令人困惑的方法,最好是 'IsMatchingAction' 或类似的方法).有效名称:

It determines this by calling IsValidName (slightly confusing method, would be better 'IsMatchingAction' or similar). IsvalidName:

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

Determines whether the action name is valid in the specified controller context.

带参数:

controllerContext:控制器上下文
actionName:动作的名称
methodInfo:动作方法的信息

controllerContext: The controller context
actionName: The name of the action
methodInfo: Information about the action method

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

taken from the blog post, you can get the request and all the values on that request via the controllerContext.

如果匹配,则返回 true,如果不是我们正在寻找的操作,则返回 false.

This returns true if it matches and false if it isn't the action we're looking for.

当它被击中时:

  • actionName = BeginForm 中的动作名称,硬编码为动作"
  • methodInfo = 应用属性的控制器操作(方法),例如 TrySubmit
  • actionName = the action name from the BeginForm, hardcoded to "Action"
  • methodInfo = the controller-action (method) that the attribute is applied to, eg TrySubmit

所以第一次检查:

if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
    return true;

只是在您在 BeginForm 中指定了除 Action 之外的其他内容的情况下,以便它转到请求的操作(即不是操作").

is just a catch-all in the case where you've specified something other than Action in your BeginForm so that it goes to the requested action (ie not "Action").

第二个检查检查您是否BeginForm

现在是聪明"的部分:

var request = controllerContext.RequestContext.HttpContext.Request;
return request[methodInfo.Name] != null;

这会检查所有 request 参数以查看是否存在与控制器操作(方法)匹配的参数.

this checks all the request parameters to see if there is a parameter that matches the controller-action (method).

当你点击一个submit按钮时,那个提交按钮的name会被传入请求参数

When you click a submit button, the name of that submit button is passed in the request parameters

如果你有:

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

如果您点击提交",则:

if you click your "Submit", then:

HttpContext.Request["TrySubmit"] == "Submit"
HttpContext.Request["DoClearForm"] == null

如果您单击清除表单",则

and if you click your "Clear Form", then

HttpContext.Request["TrySubmit"] == null
HttpContext.Request["DoClearForm"] == "Clear Form"`

不需要实际值(提交"/清除表单"),只要它不为空即可.

the actual value ("Submit"/"Clear Form") isn't needed, only that it's not null.

所以代码

request[methodInfo.Name] 

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

checks the request parameters for the existance of an item which matches the current controller-action (method) name, eg:

[HttpParamAction]
public ActionResult DoClearForm() 
{

<小时>

回答你的第一个问题:


To answer your first question:

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

I see a compare of actionName with methodInfo.Name. How can these EVER be equal when the whole purpose is to name the method different from the controller's action.

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

The first compare is an override for when the BeginForm doesn't specify Action and the BeginForm's action does match the controll-action (method) name.

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

So, in your scenario, no they won't be equal and shouldn't be - it's the last check that's relevant.

现在的问题是:

为什么这对您不起作用?

why doesn't this work for you?

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

The problem is that your action names don't match the expected action names, because you have this:

[ActionName("Action")]

所以 HttpParamAction 属性找到你的控制器动作(方法)并说使用这个",但 MVC 说,但我正在寻找动作"而不是动作"所以我会给你找不到资源".我不是 100% 这样做的原因,但是如果您使用 MVC5 Route("Action") 也是一样的 - 它找不到已经使用属性匹配它的操作.

so the HttpParamAction attribute finds your controller-action (method) and says "use this one", but then MVC says, but I'm looking for "Action" and that's not "Action" so I'll give you "The resource cannot be found". I'm not 100% of the reason it's doing this, but it's the same if you use MVC5 Route("Action") - it can't find the action having already matched it using the attribute.

如果您删除 [ActionName("Action")] 那么一切都应该没问题.

If you remove [ActionName("Action")] then all should be ok.

替代方案:如果您删除前两项检查(如果表单操作 = 控制器操作,如果表单操作 != "Action")并且只将该属性应用于您需要的方法(以及为什么 你会将它应用到其他地方吗?),然后它似乎工作正常.

Alternative: if you remove the first two checks (if form action = controller action and if form action != "Action") and only apply the attribute to the methods you need (and why would you apply it elsewhere?), then it seems to work fine.

现在,我正在使用 [Route("")] 并进行了更改:

Now, I'm using [Route("")] and changed:

表格:

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 更轻松地完成此操作,使其看起来像一个按钮.


As an alternative, it looks like your "ClearForm" button simply redirects to the page. You could do this more easily with a simple @Html.ActionLink("Clear Form", "fciContractUS") and a bit of css to make it look like a button.

如果您有任何客户端验证(例如必填字段),您也会遇到问题,因为您将无法提交"以清除表单,直到它们具有值.

You'll also have an issue if you have any client-side validation (eg required fields) as you won't be able to "submit" to clear the form until they have values.

这篇关于.NET MVC4 ActionNameSelectorAttribute 视图中的多个按钮不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆