ASP.Net MVC - Multi Form and Multi Submit Button Handling
Introduction
This article is inspired by the blog that showed excelled approach for using ActionNameSelector attribute. I have tried to take this approach little further to support multiple forms and multiple submit buttons without providing any hardcoded value to the attribute but just by specifying name of the form and button this action intended to handle. This makes sense when you don’t want to specify any Value directly inside code, as in case of localization when Value of buttons is not fixed.Let’s design our approach for both the scenarios.
1. Multiple forms on same page
We will have an attribute to handle this scenario that will look for the form name from which the request has been posted. To have this we need to store form name in hidden field. So let’s create extension method of BeginForm to handle this.
public static MvcForm BeginForm(this HtmlHelper htmlHelper, string formName)
{
return BeginForm(htmlHelper, null, formName);
}
public static MvcForm BeginForm(this HtmlHelper htmlHelper, MvcForm form, string formName)
{
if(String.IsNullOrEmpty(formName))
throw new ArgumentNullException("formName");
if (form == null)
form = htmlHelper.BeginForm();
htmlHelper.ViewContext.Writer.WriteLine(htmlHelper.Hidden("n.__formName", formName));
return form;
}
Now we have our hidden field rendered along with form name in output inside the current form tag. Below is the output of the page for View page
@using (Html.BeginForm("LogOn"))
{ }
@using (Html.BeginForm("ChangePassword"))
{ }
View Output
<form action="/" method="post"><input name="n.__formName" type="hidden" value="LogOn" />
</form>
<form action="/" method="post"><input name="n.__formName" type="hidden" value="ChangePassword" />
</form>
Now let’s design ActionNameSelectorAttribute
[AttributeUsage(AttributeTargets.Method)]
public class FormActionSelectorAttribute : ActionNameSelectorAttribute
{
private readonly string[] _formName;
public FormActionSelectorAttribute(params string[] formName)
{
if (formName == null)
throw new ArgumentNullException("formName");
_formName = formName;
}
public string[] FormName
{ get { return _formName; }
}
public override bool IsValidName(ControllerContext controllerContext, string actionName, System.Reflection.MethodInfo methodInfo)
{
return _formName.Contains(controllerContext.RequestContext.HttpContext.Request.Form["n.__formName"]);
}
}
Implementation
[HttpPost]
[FormActionSelector("LogOn")]
public ActionResult Index(LogOnModel logOn)
{
var account = new Account {LogOn = logOn};
return View(account);
}
[HttpPost]
[FormActionSelector("ChangePassword")]
public ActionResult Index(ChangePasswordModel changePasswordModel)
{
var account = new Account {ChangePassword = changePasswordModel};
return View(account);
}
2. Multiple submit buttons inside same form
As we don’t want to do check using value of button we need to follow same approach that we used in form names. But in this scenario our value of hidden filed should be decided on click of that button. So now we will have to handle this from client side. Rather than adding this hidden field right from we will use small script to create only when needed. You can do this just like we did in multi form scenario, but I prefer it this way. Here I’m going to add new attribute to submit button to attach our function on click of it.
Script
/// <reference path="jquery-1.4.4.js" />
(function ($) {
if ($) {
$(document).ready(function () {
$.each(document.forms, function () {
var theForm = this;
$('input[multiSumbit]', theForm).click(function () {
var __sender = $("input[name='n.__sender']", theForm);
if (__sender.length == 0) {
__sender = $("<input name=\"n.__sender\" value=\"" + $(this).attr('name') + "\" type=\"hidden\"/>");
theForm.appendChild(__sender[0]);
}
__sender[0].value = $(this).attr('name');
});
});
});
}
})($);
Let’s create extension method for creating submit input tag for our case.
public static MvcHtmlString SubmitButton(this HtmlHelper htmlHelper, string name, string value = "", Dictionary<string,> htmlAttribute = null)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
var button = new TagBuilder("input");
if (htmlAttribute != null)
button.MergeAttributes(htmlAttribute);
button.MergeAttribute("name", name, true);
if (!String.IsNullOrEmpty(value)) button.MergeAttribute("value", value, true);
button.MergeAttribute("multiSumbit","true", true);
button.MergeAttribute("type", "submit", true);
return new MvcHtmlString(button.ToString(TagRenderMode.SelfClosing));
}</string,>
Usage
@using (Html.BeginForm())
{
@Html.SubmitButton("btnSumbit", "Log On")
@Html.SubmitButton("btnCancel", "Cencel")
}
View Output
<form action="/" method="post">
<input multiSumbit="true" name="btnSumbit" type="submit" value="Log On" />
<input multiSumbit="true" name="btnCancel" type="submit" value="Cencel" />
</form>
As you see only thing that we have added is multiSumbit attribute.
Now let’s design ActionNameSelectorAttribute
[AttributeUsage(AttributeTargets.Method)]
public class SubmitButtonActionSelectorAttribute : ActionNameSelectorAttribute
{
private readonly string[] _buttonNames;
public SubmitButtonActionSelectorAttribute(params string[] buttonNames)
{
if (buttonNames == null)
throw new ArgumentNullException("buttonNames");
_buttonNames = buttonNames;
}
public override bool IsValidName(ControllerContext controllerContext, string actionName, System.Reflection.MethodInfo methodInfo)
{
return _buttonNames.Contains(controllerContext.RequestContext.HttpContext.Request.Form["n.__sender"]);
}
}
Implementation
[HttpPost]
[FormActionSelector("LogOn")]
[SubmitButtonActionSelector("btnSumbit")]
public ActionResult Index(LogOnModel logOn)
{
var account = new Account {LogOn = logOn};
bool isValid = ModelState.IsValid;
return View(account);
}
[HttpPost]
[ActionName("Index")]
[FormActionSelector("LogOn")]
[SubmitButtonActionSelector("btnCancel")]
public ActionResult IndexCancel()
{
var account = new Account();
return View(account);
}
You can also specify multiple button names in same attribute if required as button name parameter I have used is params string[]
Vote and comment if it really helped you :)
History
- 1st Release: 29 Jan 2011
发表评论
Hola! I've been following your web site for a long time now and finally got the bravery to go ahead and give you a shout out from Houston Tx!
Just wanted to tell you keep up the excellent
work! Manchester United fc tröjaI am really enjoying the theme/design of your blog.
Do you ever run into any internet browser compatibility
issues? A few of my blog audience have complained about my site
not working correctly in Explorer but looks great
in Firefox. Do you have any suggestions to help fix this issue?
Neue Wolfsburg trikotDo you have a spam issue on this website; I also am a
blogger, and I was wanting to know your situation; we have created some nice practices and we are looking to trade strategies with
others, please shoot me an e-mail if interested. Billige manchester city draktHi! I just want to offer you a big thumbs up for the great
information you have got here on this post. I will be returning to your website for more soon. Maglia PSG Thiago Silva Poco PrezzoiаЂа?Splendid post writing. I concur. Visit my blog for a free trial now! Enjoy secret enlargement tips. Get big and rich. Did I mention free trial? Visit now.
This is my first time visit at here and i am genuinely impressed to read all at one place.
This article will assist the internet visitors for building up new
you writing this post plus the rest of the website is also
Really enjoyed this blog.Really thank you! Fantastic.
This is one awesome article.Really looking forward to read more. Awesome.
Muchos Gracias for your article post.Really thank you! Really Great.
Thank you ever so for you post.Thanks Again. Fantastic.
This awesome blog is really interesting and besides diverting. I have picked many useful advices out of this source. I ad love to come back over and over again. Thanks a lot!
Wow, great blog.Really looking forward to read more. Will read on
Im grateful for the blog article.Thanks Again. Great.
This content announced was alive extraordinarily informative after that valuable. People individuals are fixing a great post. Prevent go away.
Major thankies for the blog article.Much thanks again.
This is really interesting, You are a very skilled blogger. I have joined your feed and look forward to seeking more of your wonderful post. Also, I ave shared your website in my social networks!
Very good blog.Much thanks again. Want more.
Thanks for the article.Thanks Again. Will read on
What as up colleagues, how is all, and what you desire to say about this piece of writing, in my view its really remarkable designed for me.
Im grateful for the blog.Really looking forward to read more. Want more.
It as hard to come by educated people about this subject, however, you sound like you know what you are talking about! Thanks
Thanks for the post.Really looking forward to read more. Great.
This website was how do I say it? Relevant!! Finally I ave found something which helped me. Thanks!
There are so many options out there that I am completely confused.. Any recommendations? Thanks!
Well I definitely liked reading it. This post provided by you is very constructive for accurate planning.
Just Browsing While I was surfing yesterday I noticed a great post concerning
Thanks for your personal marvelous posting! I seriously enjoyed reading it,
Im grateful for the post.Much thanks again. Much obliged.
Really informative blog.Really looking forward to read more. Fantastic.
It as nearly impossible to find experienced people in this particular topic, however, you sound like you know what you are talking about! Thanks
Very good blog post.Really thank you! Fantastic.
Way cool! Some extremely valid points! I appreciate you penning this write-up plus the rest of the site is very good.
I value the article post.Much thanks again. Keep writing.
You can certainly see your enthusiasm in the work you write. The world hopes for more passionate writers like you who aren at afraid to say how they believe. At all times go after your heart.
Thank you ever so for you article post.Much thanks again. Great.
This very blog is obviously entertaining as well as amusing. I have picked helluva interesting things out of this blog. I ad love to go back again and again. Thanks a lot!
Merely wanna comment that you have a very nice internet site , I enjoy the style it actually stands out.
Looking around I like to look around the internet, regularly I will just go to Stumble Upon and follow thru
Superb, what a website it is! This weblog provides valuable information
superb post.Ne aer knew this, appreciate it for letting me know.
Really informative article. Much obliged.
Wow, awesome blog layout! How long have you been blogging for? you make blogging look easy. The overall look of your website is excellent, as well as the content!
Some genuinely fantastic articles on this website , regards for contribution.
I think other web site proprietors should take this web site as
IaаАабТТаЂааАабТТаБТll complain that you have copied materials from another supply
Perfectly composed articles , regards for selective information.
Thanks to this blog I broadened horizons.
Wow, incredible blog format! How lengthy have you been blogging for? you made running a blog look easy. The total glance of your site is fantastic, as well as the content material!