Google Chrome issue - Unable to retrive button(HTML tag) value while submitting form - asp.net-mvc-3

I have a scenario in which a button value is not being posted while submitting form in ASP.NET MVC controller.
This is happening only for Google Chrome browser. For all other browsers Firefox, IE, I am getting Submit_0 value in Controller.
//Server side
public ActionResult Answers(string id, SurveyViewModel model, string Submit, string button)
{
string[] buttonParts = button.Split(new char[]{'_'});
..
...
}
//Client Side
#using (Html.BeginForm("Answers", "Survey"))
{
<button value="Submit_0" name="button" onclick="document.forms[0].submit();"><span><span>Submit</span></span></button>
}
Kindly suggest.

I wonder if it is because the way you wired the button. Why don't you use something like this instead?
<button type="submit" name="button" value="submit_0">Submit</button>
Notice that the button has a type of submit (which eliminate the need to call document.forms[0].submit() manually)

Related

ASP.NET Core MVC submit form in partial view / ViewComponent

I have a menu and a content area which displays content based on the selected item in the menu. Since the user is allowed to change the structure of the main menu, I decided that everything will be on page /home/index and will have a guid assigned to the content which needs to be shown. I started with the idea to introduce partial views, but realized that ASP.NET Core doesn't have RenderAction anymore and was replaced by ViewComponents.
So I used ViewComponents and everything works fine, except that I've stumbled on a situation where I need to have a component as a submit form.
In an example: One menu item is the menu is a component that shows a list of users. Another menu item is a component that creates a new user. On create user component I'll have a form that needs to be filled and on successful submit, I want to redirect the user to the component that shows a list of users. In the case of unsuccessful submit, error, wrong input I would of course not want to redirect the user to the list of users.
Since ViewComponents' job is to display view, how should I approach this issue? I'm looking for pointers in the right direction.
I have little experience in this field so any help would be appreciated.
UPDATE
In Index.cshtml:
<tbody>
#foreach (string item in Model.Components)
{
<tr>
<td>
<div class="col-md-3">
#await Component.InvokeAsync(#item)
</div>
</td>
</tr>
}
</tbody>
This is inside the content area. Components are string names of components I'd like to show in the content area (currently listed one after the other).
My ViewComponent which will get called when I click on the menu item to display the form:
public class TestFormViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync()
{
return View("_TestForm", new TestModelPost());
}
}
My _TestForm.cshtml component:
#model TestModelPost
<form asp-controller="Home" asp-action="TestPost" method="post">
<label asp-for="Name"></label>
<input asp-for="Name" /><br />
<label asp-for="Surname"></label>
<input asp-for="Surname" /><br />
<button type="submit">Go</button>
</form>
And the action TestPost called:
[HttpPost]
public IActionResult TestPost(TestModelPost model)
{
// Save model data, etc
// !ModelState.IsValid -> go back to form
// Success -> go to specific id
return RedirectToAction("Index", new { id = 1 });
}
How should I approach this? Or rather, am I even on the right track? I'm not sure how I would go "back" to that view I created in my _TestForm component in case the input was incorrect.
View components, just like child actions before them in ASP.NET MVC do not support POSTs. You need a full fledged action to handle the form post, which will need to return a full view. Essentially, you just need to think about it more abstractly.
A view component is just ultimately a means of dumping some HTML into the eventual response. When the full response is returned to the client, there's no concept of what was a view component, a partial view, etc. It's just an HTML document. Part of that HTML document is your form. That form will have an action, which ultimately should be a route that's handled by one of your controller actions. A traditional form post cause the entire browser view to change, so the response from this action should either be a full view or a redirect to an action that returns a full view. The redirect is the more appropriate path, following the PRG pattern. It is then the responsibility of that view that is eventually returned to determine how the content is constructed, using view components, partials, etc. as appropriate.
Long and short, this really has nothing to do with your view component at all. All it is doing is just dropping the form code on the page.
For forms like this that are part of the layout, it's usually best to include a hidden input that contains a "return URL" in the form. The action that handles the form, then can redirect back to this URL after doing what it needs to do, in order to give the semblance that the user has stayed in the same place.
Kindly refer to the following link:
https://andrewlock.net/an-introduction-to-viewcomponents-a-login-status-view-component/
it might be of help
public class LoginStatusViewComponent : ViewComponent
{
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly UserManager<ApplicationUser> _userManager;
public LoginStatusViewComponent(SignInManager<ApplicationUser> signInManager, UserManager<ApplicationUser> userManager)
{
_signInManager = signInManager;
_userManager = userManager;
}
public async Task<IViewComponentResult> InvokeAsync()
{
if (_signInManager.IsSignedIn(HttpContext.User))
{
var user = await _userManager.GetUserAsync(HttpContext.User);
return View("LoggedIn", user);
}
else
{
return View();
}
}
}
Our InvokeAsync method is pretty self explanatory. We are checking if the current user is signed in using the SignInManager<>, and if they are we fetch the associated ApplicationUser from the UserManager<>. Finally we call the helper View method, passing in a template to render and the model user. If the user is not signed in, we call the helper View without a template argument.
As per your code segment you can try to modify it as follows:
public class TestFormViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync()
{
if (_signInManager.IsSignedIn(HttpContext.User))
{
//user list display
return View("_TestForm", new TestModelPost());
}
else
{
return View();
}
}
}

MVC3: Button action on the same view

i wish to change the inner html of a view on button click but maintain the view. I know how to change the html content of a div in javascript, but how can I have the action of the button not return a different view?
My buton looks like
<input type="submit" value="submit" onchange="myfunc()"/>
where myfunc() is the function in Javascript changing the div content.
Assuming you want a link to render content using ajax (and hopefully using razor) you can do something like the following:
First, setup the action to render the content partially. this can be done a few ways, but I'll keep with the logic in the action (and make it callable directly or by ajax):
[HttpPost]
public ActionResult Save(SomeModel model)
{
/* build view */
return Request.IsAjaxRequest() ? PartialView(model) : Wiew(model);
}
Next, setup a container in your page where the content will be populated along with the form you're looking to submit. If you want the form to disappear on a save, wrap it in the container. Otherwise, keep the container separated. In the below example, the from will submit and on success it'll come back, otherwise the new content will appear in its place:
<div id="ajaxContentPlaceholder">
#using (Ajax.BeginForm("Save", new AjaxOptions { UpdateTargetId = "ajaxContentPlaceholder" })) {
<!-- form elements -->
<input type="submit" value="save" />
}
</div>

Add and remove textbox at runtime in mvc3

In my page there is one textbox by default and one add button beside it. I need to add the another textbox when user click Add button. And there should be two buttons Add and Remove beside newly added text box. And same process goes on i.e., user can add Textbox using Add button and remove it using remove button.
I am new to mvc 3 so i am confused how to proceed. Is there any way like placeholder in asp.net so that we can add control at runtime.
Any suggestion and idea will be helpful to me
MVC is a very "hands-off" framework compared to Web Forms, so you're free to add the new textboxes how you like. Note that "controls" don't exist in MVC.
Here's how I'd do it:
Model:
class MyModel {
public Boolean AddNewTextBox { get; set; }
public List<String> MultipleTextBoxes { get; set; } // this stores the values of the textboxes.
}
View (I prefer the Web Forms view engine, I'm not a fan of Razor):
<% for(int i=0;i<Model.MultipleTextBoxes.Count;i++) { %>
<%= Html.TextBoxFor( m => m.MultipleTextBoxes[i] ) /* this might look like magic to you... */ %>
<% } %>
<button type="submit" name="AddNewTextbox" value="true">Add New Textbox</button>
<button type="submit">Submit form</button>
Controller:
[HttpPost]
public ActionResult MyAction(MyModel model) {
if( model.AddNewTextBox ) model.MultipleTextBoxes.Add("Yet another");
else if( ModelState.IsValid ) {
// your regular processing
}
}
You can also add more textboxes with Javascript and it work perfectly fine. All that matters is the HTML input elements. There's no cryptic viewstate. MVC is stateless.
Note that because I used <button type="submit"> my example will not work reliably in Internet Explorer 6-8 (sucks, I know), but you can replace them with <input type="submit"> with no ill-effects.
This requires some Javascript/JQuery... The following is a sketch only, but will hopefully be useful as a general approach.
The remove button
You want to render a button that can target its own container for removal. To do that, use some markup like this:
<div class="item-container">
<input type="button" onclick="removeItem(this)" />
</div>
And the Javascript for removeItem:
<script>
function removeItem(element) {
// get the parent element with class "item-container" and remove it from the DOM
$(element).find(".item-container").remove();
}
</script>
The add button
You could either use a partial view with Ajax, or use straight Javascript; which one is best likely depends on whether you need a round-trip to the server to create a new item. Let's say you need to go the the server to generate a new ID or something.
First, create a partial view and corresponding controller action; this should contain the remove button as above, as well as the text box and add button.
Now, create an Ajax form on your main page that gets invoked when you click Add:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
#using (Ajax.BeginForm("New", new AjaxOptions() { UpdateTargetId="ajaxTarget", HttpMethod = "GET" })) {
<input type='submit' value='Add New' />
}
<div id="ajaxTarget"></div>
This code fetches your partial view (from the action New in the current controller) and adds the result to the ajaxTarget element.
Note The Ajax form requires Unobtrusive Ajax, which you can install via Nuget: Install-Package JQuery.Ajax.Unobtrusive.

ASP MVC 3 is it possible to identify the <input> id in the controller [post] method?

I'm using a so as to edit an object, with an <input type="submit"> for validation
I've also another input, type="button" with an onclick event for the cancel button (with a redirect). However, this use a JS call, which I'd like to avoid.
I'd rather prefer to process the validation or cancel choice within the controller, so as to be NoScript compliant.
So is it possible to retrieve, within the controller post method, the id of the <input> that was clicked in the <form>?
Thanks
You can set the name of your
<input type="submit" name="submitButton" />
Then in your controller:
if(Request["submitButton"] != null) {
// ...
}
I'm not sure if I understand you, but if your cancel button does a redirect, it should end in a GET, and your submit button does a POST, that's how you should difference both request.
Check the [HttpPost] attribute in controller action methods.

multiple button click in asp.net MVC 3

I am having multiple dynamic buttons on my asp.net mvc 3 page. what is the best way to handle button click in asp.net mvc 3? there is no event handling in asp.net, so what is the best practice to hadle.?
You could handle the buttons clicks using javascript by subscribing to their click event. For example with jQuery you could give those buttons a class and then:
$(function() {
$('.someClass').click(function() {
// a button was clicked, this will point to the actual button
});
});
or if those are submit buttons of a form you could give them the same name and different values and then on the server test the value of the name parameter. It's value will equal to the button that was clicked.
Let's suppose for example that you have the following form with multiple submit buttons:
#using (Html.BeginForm())
{
... some input fields
<button type="submit" name="Button" value="delete">Delete data</button>
<button type="submit" name="Button" value="save">Save data</button>
}
Now inside the controller action you are posting to you could determine which button was clicked:
[HttpPost]
public ActionResult Index(MyViewModel model)
{
var button = Request["button"];
if (button == "save")
{
// the save button was clicked
}
else if (button == "delete")
{
// the delete button was clicked
}
...
}
If the buttons do not require the same form data, then you can create two forms with different action methods. This is the easiest solution.
If you need to use the same form data, then there are a number of methods, inclduing Darin and tvanfosson's approaches. There is also an approach based on attributes that will select the correct action method based on which button is clicked.
http://www.dotnetcurry.com/ShowArticle.aspx?ID=724
Depends on what the buttons are doing. If they are logically separate actions, then you could have each postback to a separate action on the server side. This often also works they are variants of the same action, Save vs. Cancel, for instance where Save posts back the form and Cancel redirects to you the previous url (say, going back to details from edit). If the buttons represent different data that would get posted back to the same action, you can give them different values. If the buttons are named, the values will get posted back along with the rest of the form, assuming they are included in the form. If posting back from AJAX, you might need to explicitly serialize the button value along with the form.
Example of Save/Cancel
#using (Html.BeginForm())
{
//...
<button type="submit" class="submit-button button">Save</button>
#Html.ActionLink( "Cancel", "details", new { ID = Model.ID }, new { #class = "cancel-button button" } )
}
Then use CSS, perhaps in conjunction with jQuery UI to style the buttons.
<script type="text/javascript">
$(function() {
$('.button').button();
...
});
</script>

Resources