使用ControllerActionInvoker简化MVC单Form多按钮的提交
2012-08-07 18:24
260 查看
最近在学习MVC,碰到了一个表单多个提交按钮的处理问题,网上找了一些方法,总觉的不够方便,下面说说我的解决方案:
一、View中我们有如下表单
@using (Ajax.BeginForm(new AjaxOptions()))
{
<input type="submit" name="Submit:Save" value="保存" class="Button" />
<input type="submit" name="Submit:Confirm" value="确认" class="Button" />
<input type="submit" name="Submit:Audit" value="审核" class="Button" />
}
个人比较喜欢无刷新,所以用Ajax.BeginForm,当然你也可以用Html.BeginForm。
我们假设该表单对应的Url为:http://localhost/MvcApp/BusinessCost,由于没有默认的Action,所以实际该请求会路由到BusinessCostController的Index方法。
提交按钮的名称我们以“Submit:”开头,后面跟要执行Action的名称。这样可以很简单的控制这个提交按钮执行哪个Action。
二、BusinessCostController中的方法
public class PermissionRegistrationController : Test.Web.Mvc.Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Save(...)
{
return View();
}
public ActionResult Confirm(...)
{
return View();
}
public ActionResult Audit(...)
{
return View();
}
}
上面方法的参数我没有写,这个不影响我们要操作的内容。
上面我们注意到并没有继承System.Web.Mvc.Controller,而是继承我自己的Test.Web.Mvc.Controller,这样的好处是我们可以放很多通用的东西到自己的Controller中,也是实现本功能的关键点之一。
三、自定义的Test.Web.Mvc.Controller基类
public class Controller : System.Web.Mvc.Controller
{
public Controller()
: base()
{
}
protected override IActionInvoker CreateActionInvoker()
{
return new MultiSubmitControllerActionInvoker();
}
}
在这个基类中我们重写CreateActionInvoker方法,返回我们自己定义的MultiSubmitControllerActionInvoker类。
当然,这个基类也可以增加其他的通用方法,或者重写其他父类中的方法从而实现更复杂的逻辑控制。
四、主角上场-最重要的MultiSubmitControllerActionInvoker类
public class MultiSubmitControllerActionInvoker : ControllerActionInvoker
{
public override bool InvokeAction(ControllerContext controllerContext, string actionName)
{
if (controllerContext.HttpContext.Request.HttpMethod.Equals("POST"))//我这里只有POST才执行特殊逻辑,其实也可以GET
{
string virtualPath = controllerContext.RouteData.Route.GetVirtualPath(controllerContext.RequestContext, controllerContext.RouteData.Values).VirtualPath;
if (!virtualPath.EndsWith("/" + actionName))//只有当Url中没有Action的时候才执行特殊逻辑,如果本身已经有了就执行系统确定的吧!
{
string actionButtonName = controllerContext.HttpContext.Request.Form.AllKeys.FirstOrDefault(key => key.StartsWith("Submit:", StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrWhiteSpace(actionButtonName))//检查提交按钮的name是否符合我们的约定
{
actionName = actionButtonName.Substring(actionButtonName.IndexOf(":") + 1);//符合约定取出冒号后面的名字作为Action的名字
}
}
}
return base.InvokeAction(controllerContext, actionName);
}
}
在我们自定义的ControllerActionInvoker中重写InvokeAction方法。从而决策改变actionName,达到我们想要的结果。
搞定!只要继承我们自己的基类,就可以实现点击提交按钮,从而根据提交按钮的name来判断执行Controller中的哪个Action了。也不用给Action的方法加Attribute,是不是很简单?
本人初学MVC,有不当之处还请指教!
一、View中我们有如下表单
@using (Ajax.BeginForm(new AjaxOptions()))
{
<input type="submit" name="Submit:Save" value="保存" class="Button" />
<input type="submit" name="Submit:Confirm" value="确认" class="Button" />
<input type="submit" name="Submit:Audit" value="审核" class="Button" />
}
个人比较喜欢无刷新,所以用Ajax.BeginForm,当然你也可以用Html.BeginForm。
我们假设该表单对应的Url为:http://localhost/MvcApp/BusinessCost,由于没有默认的Action,所以实际该请求会路由到BusinessCostController的Index方法。
提交按钮的名称我们以“Submit:”开头,后面跟要执行Action的名称。这样可以很简单的控制这个提交按钮执行哪个Action。
二、BusinessCostController中的方法
public class PermissionRegistrationController : Test.Web.Mvc.Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Save(...)
{
return View();
}
public ActionResult Confirm(...)
{
return View();
}
public ActionResult Audit(...)
{
return View();
}
}
上面方法的参数我没有写,这个不影响我们要操作的内容。
上面我们注意到并没有继承System.Web.Mvc.Controller,而是继承我自己的Test.Web.Mvc.Controller,这样的好处是我们可以放很多通用的东西到自己的Controller中,也是实现本功能的关键点之一。
三、自定义的Test.Web.Mvc.Controller基类
public class Controller : System.Web.Mvc.Controller
{
public Controller()
: base()
{
}
protected override IActionInvoker CreateActionInvoker()
{
return new MultiSubmitControllerActionInvoker();
}
}
在这个基类中我们重写CreateActionInvoker方法,返回我们自己定义的MultiSubmitControllerActionInvoker类。
当然,这个基类也可以增加其他的通用方法,或者重写其他父类中的方法从而实现更复杂的逻辑控制。
四、主角上场-最重要的MultiSubmitControllerActionInvoker类
public class MultiSubmitControllerActionInvoker : ControllerActionInvoker
{
public override bool InvokeAction(ControllerContext controllerContext, string actionName)
{
if (controllerContext.HttpContext.Request.HttpMethod.Equals("POST"))//我这里只有POST才执行特殊逻辑,其实也可以GET
{
string virtualPath = controllerContext.RouteData.Route.GetVirtualPath(controllerContext.RequestContext, controllerContext.RouteData.Values).VirtualPath;
if (!virtualPath.EndsWith("/" + actionName))//只有当Url中没有Action的时候才执行特殊逻辑,如果本身已经有了就执行系统确定的吧!
{
string actionButtonName = controllerContext.HttpContext.Request.Form.AllKeys.FirstOrDefault(key => key.StartsWith("Submit:", StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrWhiteSpace(actionButtonName))//检查提交按钮的name是否符合我们的约定
{
actionName = actionButtonName.Substring(actionButtonName.IndexOf(":") + 1);//符合约定取出冒号后面的名字作为Action的名字
}
}
}
return base.InvokeAction(controllerContext, actionName);
}
}
在我们自定义的ControllerActionInvoker中重写InvokeAction方法。从而决策改变actionName,达到我们想要的结果。
搞定!只要继承我们自己的基类,就可以实现点击提交按钮,从而根据提交按钮的name来判断执行Controller中的哪个Action了。也不用给Action的方法加Attribute,是不是很简单?
本人初学MVC,有不当之处还请指教!
相关文章推荐
- ios9 之后,Xcode7不推荐使用UIAlertView,改用UIAlertController+UIAlertAction(按钮)
- SpringMVC MultiActionController的使用-最简化教程
- 使用Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, new { id = "formInfo" })提交数据的问题
- WARN com.opensymphony.xwork2.ognl.OgnlValueStack异常的解决办法[提交按钮使用了图片并设置name属性,对应action无gettersetter]
- UIImagePickerController的简化使用
- Web应用中使用javascript阻止某个提交按钮被重复点击
- Struts2 Action使用通配符提交
- 问题:如何不使用submit按钮来提交表单?
- from表单多个按钮提交用onclick跳转不同action
- Zend_Controller_Action使用技巧
- MVC中使用Ajax提交数据 Jquery Ajax方法传值到action
- MVC中使用Ajax提交数据 Jquery Ajax方法传值到action
- 使用jQuery重用form表单并异步提交到其他action
- zend_controller_action中initView()与render()的使用
- 使用dispatchAction简化对action的请求操作
- JS实现一个表单form,多个submit按钮提交时带不同的action参数
- 5-7使用提交按钮,提交数据
- MVC中使用Ajax提交数据 Jquery Ajax方法传值到action
- 使用<a>标签提交action会执行两次后台方法的原因(反射机制小实例问题的解决)
- 使用Ext Viewport进行页面布局时Panel中的sumit按钮无法提交表单数据