A quick look around with Google and I found a couple of approaches, but I thought to myself, there must be a cleaner way.
Up till now I've been using the simple approach of creating a controller action where the method takes an extra parameter to describe which action to take like:
Controller:
public class MyController
{
public ViewResult Index() { return View();}
public ViewResult DoSomething(string action, string someData)
{
if(action == "Action1") {}
else if(action == "Action2") {}
else {/*unknown action.*/ }
}
}
xhtml:
<form action="My/DoSomething>
<input name="someData"/>
<input type='submit' name='action' value='Action1' />
<input type='submit' name='action' value='Action2' />
</form>
What I wanted was to be able to define my Controller to have multiple Actions, one for each submit action on a Form, like this:
public class MyController
{
public ViewResult Index() {return View();}
public ViewResult Action1(string someData) {return View();}
public ViewResult Action2(string someData) {return View();}
}
But alas, with MVC I couldn't construct a Route that would do this; MVC routing always uses the Forms action attribute to decide which Controller method to call.
In the end the answer wasn't that hard. I just created a smarter IRouteHander, and applied it to the MVC default route.
The HTML for the form looks almost the same, though I remove the Action from the Form's action attribute, since the route handler will look after that.
xhtml:
<form action="My>
<input name="someData"/>
<input type='submit' name='action' value='Action1' />
<input type='submit' name='action' value='Action2' />
</form>
Now the methods on my controller don't need 'special' arguments, and the world is a better place :D
Here is the custom RouteHandler:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace derek.kowald.MVC | |
{ | |
using System; | |
using System.Web; | |
using System.Web.Mvc; | |
using System.Web.Routing; | |
/// <summary> | |
/// Custom route handler so a form submit button can | |
/// define the mvc action to take. | |
/// </summary> | |
/// <remarks> | |
/// Be careful to only define submit buttons with the name action. | |
/// </remarks> | |
/// <example> | |
/// Update your routes to use this hander: | |
/// routes.MapRoute("Default", | |
/// "{controller}/{action}/{id}", | |
/// new { controller = "Home", action="Index", id = UrlParameter.Optional}) | |
/// .RouteHandler = new SubmitActionHandler(); | |
/// | |
/// Update your markup so sumbit button(s) have the name action: | |
/// <input type='submit' name='action' value='MyAction' /> | |
/// </example> | |
public class SubmitActionHandler : IRouteHandler | |
{ | |
#region IRouteHandler Members | |
/// <summary> | |
/// If an input parameter named 'action' is provided, | |
/// update the RouteData action property with the form data. | |
/// </summary> | |
public IHttpHandler GetHttpHandler(RequestContext requestContext) | |
{ | |
string reqAction = null; | |
if (requestContext.HttpContext != null && | |
requestContext.HttpContext.Request != null) | |
{ | |
reqAction = requestContext.HttpContext.Request["action"]; | |
} | |
if (!String.IsNullOrEmpty(reqAction)) | |
{ | |
requestContext.RouteData.Values["action"] = reqAction; | |
} | |
return new MvcHandler(requestContext); | |
} | |
#endregion | |
} | |
} |
No comments:
Post a Comment