.NET MVC4 ActionNameSelectorAttribute 视图中的多个按钮不起作用 [英] .NET MVC4 ActionNameSelectorAttribute multiple buttons within View is not working
问题描述
我已经阅读了很多关于允许不同视图按钮的不同控制器操作的帖子.但是,我无法让它发挥作用.
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;
}
}
当我逐步执行此代码时,我看到 actionName
与 methodInfo.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屋!