我使用从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的比较.当整个目的是将方法命名为与控制器的动作不同时,这些EVER如何相等.
对于行为/功能,真或假的返回值实际上是什么意思?
我应该用’动作’覆盖’fciContactUs’动作吗?
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’)form-start:
@using (Html.BeginForm("Action","Home")) {
视图按钮:
<input type="submit" name="TrySubmit" value="Submit" /> <input type="submit" name="DoClearForm" value="Clear Form" />
此外,此IsValidName方法始终返回false并且方法永远不会被执行.
我担心action-name,view-name,controller-name,button-names和ActionNameSelectorAttribute类覆盖中存在不一致.
我是MVC的新手,整个事情让我扭曲了.
任何评论或帮助将不胜感激.
解决方法
Represents an attribute that affects the selection of an action method.
因此,当应用于某个操作,并且请求(获取或发布)进入时,将调用此属性以查看该操作是否确实是正确的操作.
它通过调用IsValidName来确定这一点(稍微有些混乱的方法,会更好’IsMatchingAction’或类似). IsvalidName:
Determines whether the action name is valid in the specified controller context.
带参数:
controllerContext: The controller context
actionName: The name of the action
methodInfo: Information about the action method
从博客文章中获取,您可以通过controllerContext获取请求和该请求的所有值.
如果匹配则返回true,如果不是我们正在寻找的动作则返回false.
当它被击中时:
> actionName = BeginForm中的操作名称,硬编码为“Action”
> methodInfo =应用该属性的controller-action(方法),例如TrySubmit
所以第一次检查:
if (actionName.Equals(methodInfo.Name,StringComparison.InvariantCultureIgnoreCase)) return true;
在您的BeginForm中指定了除Action之外的其他内容以便它转到请求的操作(即不是“Action”)的情况下,这只是一个包罗万象的事情.
第二次检查检查您是否在BeginForm中指定了“Action”
现在是“聪明”的部分:
var request = controllerContext.RequestContext.HttpContext.Request; return request[methodInfo.Name] != null;
这将检查所有请求参数,以查看是否存在与controller-action(方法)匹配的参数.
单击提交按钮时,将在请求参数中传递该提交按钮的名称
所以如果你有:
<input type="submit" name="TrySubmit" value="Submit" /> <input type="submit" name="DoClearForm" value="Clear Form" />
如果你点击“提交”,那么:
HttpContext.Request["TrySubmit"] == "Submit" HttpContext.Request["DoClearForm"] == null
如果你点击“清除表格”,那么
HttpContext.Request["TrySubmit"] == null HttpContext.Request["DoClearForm"] == "Clear Form"`
不需要实际值(“提交”/“清除表单”),只是它不为空.
所以代码
request[methodInfo.Name]
检查请求参数是否存在与当前控制器 – 动作(方法)名称匹配的项目,例如:
[HttpParamAction] public ActionResult DoClearForm() {
回答你的第一个问题:
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的操作与controll-action(方法)名称匹配时的覆盖.
所以,在你的场景中,他们不会是平等的,也不应该是 – 这是最后一次相关的检查.
现在的问题是:
why doesn’t this work for you?
[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,MethodInfo methodInfo) { var request = controllerContext.RequestContext.HttpContext.Request; return request[methodInfo.Name] != null; } }
作为替代方案,看起来您的“ClearForm”按钮只是重定向到页面.您可以使用简单的@ Html.ActionLink(“Clear Form”,“fciContractUS”)和一些css使其看起来像一个按钮,从而更轻松地完成此操作.
如果您有任何客户端验证(例如必填字段),您也会遇到问题,因为在它们有值之前您无法“提交”清除表单.